diff --git a/.gitignore b/.gitignore index 7022ed0ad..bc3ccbbce 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ consumer-test/**/workspace *.code-workspace /piper /piper.exe +.factorypath diff --git a/src/com/sap/piper/Utils.groovy b/src/com/sap/piper/Utils.groovy index b3f996626..5109b20e0 100644 --- a/src/com/sap/piper/Utils.groovy +++ b/src/com/sap/piper/Utils.groovy @@ -123,3 +123,20 @@ static String downloadSettingsFromUrl(script, String url, String targetFile = 's script.writeFile(file: targetFile, text: settings.getContent()) return targetFile } + +/* + * Uses the Maven Help plugin to evaluate the given expression into the resolved values + * that maven sees at / generates at runtime. This way, the exact Maven coordinates and + * variables can be used. + */ +static String evaluateFromMavenPom(Script script, String pomFileName, String pomPathExpression) { + + String resolvedExpression = script.mavenExecute( + script: script, + pomPath: pomFileName, + goals: 'org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate', + defines: "-Dexpression=$pomPathExpression -DforceStdout -q", + returnStdout: true + ) + return resolvedExpression +} diff --git a/src/com/sap/piper/versioning/MavenArtifactVersioning.groovy b/src/com/sap/piper/versioning/MavenArtifactVersioning.groovy index 68956a95d..4b80ee55a 100644 --- a/src/com/sap/piper/versioning/MavenArtifactVersioning.groovy +++ b/src/com/sap/piper/versioning/MavenArtifactVersioning.groovy @@ -1,5 +1,7 @@ package com.sap.piper.versioning +import com.sap.piper.Utils + class MavenArtifactVersioning extends ArtifactVersioning { protected MavenArtifactVersioning (script, configuration) { super(script, configuration) @@ -7,8 +9,9 @@ class MavenArtifactVersioning extends ArtifactVersioning { @Override def getVersion() { - def mavenPom = script.readMavenPom (file: configuration.filePath) - return mavenPom.getVersion().replaceAll(/-SNAPSHOT$/, "") + String pomFile = configuration.filePath + String version = Utils.evaluateFromMavenPom(script, pomFile, 'project.version') + return version.replaceAll(/-SNAPSHOT$/, "") } @Override diff --git a/test/groovy/ArtifactSetVersionTest.groovy b/test/groovy/ArtifactSetVersionTest.groovy index 8c7e6a372..38570d362 100644 --- a/test/groovy/ArtifactSetVersionTest.groovy +++ b/test/groovy/ArtifactSetVersionTest.groovy @@ -74,6 +74,7 @@ class ArtifactSetVersionTest extends BasePiperTest { @Before void init() throws Throwable { dockerParameters = [:] + String version = '1.2.3' nullScript.commonPipelineEnvironment.setArtifactVersion(null) nullScript.commonPipelineEnvironment.setGitSshUrl('git@test.url') @@ -83,6 +84,8 @@ class ArtifactSetVersionTest extends BasePiperTest { return closure() }) + shellRule.setReturnValue("mvn --file 'pom.xml' --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate -Dexpression=project.version -DforceStdout -q", version) + shellRule.setReturnValue("mvn --file 'snapshot/pom.xml' --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate -Dexpression=project.version", version) shellRule.setReturnValue("date --utc +'%Y%m%d%H%M%S'", '20180101010203') shellRule.setReturnValue('git diff --quiet HEAD', 0) @@ -219,7 +222,7 @@ class ArtifactSetVersionTest extends BasePiperTest { )) } - + @Test void testVersioningPushViaHTTPSEncodingDoesNotRevealSecrets() { diff --git a/test/groovy/CommonStepsTest.groovy b/test/groovy/CommonStepsTest.groovy index 69cce2c05..68c0596df 100644 --- a/test/groovy/CommonStepsTest.groovy +++ b/test/groovy/CommonStepsTest.groovy @@ -229,6 +229,7 @@ public class CommonStepsTest extends BasePiperTest{ def whitelist = [ 'durationMeasure', + 'mavenExecute' ] for(def step in getSteps()) { diff --git a/test/groovy/MavenExecuteTest.groovy b/test/groovy/MavenExecuteTest.groovy index 164f72d78..c64d91e8f 100644 --- a/test/groovy/MavenExecuteTest.groovy +++ b/test/groovy/MavenExecuteTest.groovy @@ -11,7 +11,6 @@ import util.Rules import static org.hamcrest.Matchers.allOf import static org.hamcrest.Matchers.containsString -import static org.hamcrest.Matchers.containsString import static org.hamcrest.Matchers.not import static org.junit.Assert.assertEquals import static org.junit.Assert.assertThat @@ -101,4 +100,11 @@ class MavenExecuteTest extends BasePiperTest { |--show-version''' as CharSequence).stripMargin()) assertThat(shellRule.shell[0], not(containsString('--batch-mode'))) } + + @Test + void testMavenExecuteReturnsStdout() { + shellRule.setReturnValue('mvn --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn clean install', "[INFO] BUILD SUCCESS") + String commandOutput = stepRule.step.mavenExecute(script: nullScript, goals: 'clean install', returnStdout: true) + assertEquals(commandOutput, '[INFO] BUILD SUCCESS') + } } diff --git a/test/groovy/com/sap/piper/versioning/MavenArtifactVersioningTest.groovy b/test/groovy/com/sap/piper/versioning/MavenArtifactVersioningTest.groovy index b54b45770..d5a3eeab2 100644 --- a/test/groovy/com/sap/piper/versioning/MavenArtifactVersioningTest.groovy +++ b/test/groovy/com/sap/piper/versioning/MavenArtifactVersioningTest.groovy @@ -19,6 +19,7 @@ class MavenArtifactVersioningTest extends BasePiperTest{ def commonPipelineEnvironment MavenArtifactVersioning av + String version = '1.2.3' JenkinsShellCallRule shellRule = new JenkinsShellCallRule(this) @@ -38,14 +39,17 @@ class MavenArtifactVersioningTest extends BasePiperTest{ dockerParameters = parameters closure() }) + + shellRule.setReturnValue("mvn --file 'pom.xml' --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate -Dexpression=project.version -DforceStdout -q", version) + shellRule.setReturnValue("mvn --file 'snapshot/pom.xml' --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate -Dexpression=project.version -DforceStdout -q", version) } @Test void testVersioning() { av = new MavenArtifactVersioning(nullScript, [filePath: 'pom.xml']) - assertEquals('1.2.3', av.getVersion()) + assertEquals(version, av.getVersion()) av.setVersion('1.2.3-20180101') - assertEquals('mvn --file \'pom.xml\' --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn versions:set -DnewVersion=1.2.3-20180101 -DgenerateBackupPoms=false', shellRule.shell[0]) + assertEquals('mvn --file \'pom.xml\' --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn versions:set -DnewVersion=1.2.3-20180101 -DgenerateBackupPoms=false', shellRule.shell[1]) } @Test @@ -53,6 +57,6 @@ class MavenArtifactVersioningTest extends BasePiperTest{ av = new MavenArtifactVersioning(nullScript, [filePath: 'snapshot/pom.xml']) assertEquals('1.2.3', av.getVersion()) av.setVersion('1.2.3-20180101') - assertEquals('mvn --file \'snapshot/pom.xml\' --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn versions:set -DnewVersion=1.2.3-20180101 -DgenerateBackupPoms=false', shellRule.shell[0]) + assertEquals('mvn --file \'snapshot/pom.xml\' --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn versions:set -DnewVersion=1.2.3-20180101 -DgenerateBackupPoms=false', shellRule.shell[1]) } } diff --git a/vars/mavenExecute.groovy b/vars/mavenExecute.groovy index 573bd2700..82c8d5ef7 100644 --- a/vars/mavenExecute.groovy +++ b/vars/mavenExecute.groovy @@ -36,31 +36,38 @@ import static com.sap.piper.Utils.downloadSettingsFromUrl * Configures maven to log successful downloads. This is set to `false` by default to reduce the noise in build logs. * @possibleValues `true`, `false` */ - 'logSuccessfulMavenTransfers' + 'logSuccessfulMavenTransfers', + /** + * Returns the standard output of the maven command for further processing. By default stdout will be printed to the console but not returned by mavenExecute. + * @possibleValues `true`, `false` + */ + 'returnStdout' ]) /** * Executes a maven command inside a Docker container. */ @GenerateDocumentation -void call(Map parameters = [:]) { +def call(Map parameters = [:]) { + + final script = checkScript(this, parameters) ?: this + String commandOutput = '' + + // load default & individual configuration + Map configuration = ConfigurationHelper.newInstance(this) + .loadStepDefaults() + .mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS) + .mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS) + .mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName ?: env.STAGE_NAME, STEP_CONFIG_KEYS) + .mixin(parameters, PARAMETER_KEYS) + .use() + handlePipelineStepErrors(stepName: STEP_NAME, stepParameters: parameters) { - final script = checkScript(this, parameters) ?: this - - // load default & individual configuration - Map configuration = ConfigurationHelper.newInstance(this) - .loadStepDefaults() - .mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS) - .mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS) - .mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, STEP_CONFIG_KEYS) - .mixin(parameters, PARAMETER_KEYS) - .use() - new Utils().pushToSWA([ - step: STEP_NAME, + step : STEP_NAME, stepParamKey1: 'scriptMissing', - stepParam1: parameters?.script == null + stepParam1 : parameters?.script == null ], configuration) String command = "mvn" @@ -74,7 +81,7 @@ void call(Map parameters = [:]) { } String m2Path = configuration.m2Path - if(m2Path?.trim()) { + if (m2Path?.trim()) { command += " -Dmaven.repo.local='${m2Path}'" } @@ -87,7 +94,7 @@ void call(Map parameters = [:]) { } String pomPath = configuration.pomPath - if(pomPath?.trim()){ + if (pomPath?.trim()) { command += " --file '${pomPath}'" } @@ -114,11 +121,19 @@ void call(Map parameters = [:]) { command += " ${mavenGoals}" } def defines = configuration.defines - if (defines?.trim()){ + if (defines?.trim()) { command += " ${defines}" } + dockerExecute(script: script, dockerImage: configuration.dockerImage, dockerOptions: configuration.dockerOptions) { - sh command + if (configuration.returnStdout) { + commandOutput = sh(returnStdout: true, script: command) + } else { + sh command + } } } + if (configuration.returnStdout) { + return commandOutput + } }