diff --git a/documentation/docs/steps/transportRequestCreate.md b/documentation/docs/steps/transportRequestCreate.md index 433e3916d..321ad7fc3 100644 --- a/documentation/docs/steps/transportRequestCreate.md +++ b/documentation/docs/steps/transportRequestCreate.md @@ -14,12 +14,20 @@ Creates a Transport Request for a Change Document on the Solution Manager. | `credentialsId` | yes | | | | `endpoint` | yes | | | | `clientOpts` | no | | | +| `gitFrom` | no | `origin/master` | | +| `gitTo` | no | `HEAD` | | +| `gitChangeDocumentLabel` | no | `ChangeDocument\s?:` | regex pattern | +| `gitFormat` | no | `%b` | see `git log --help` | * `script` - The common script environment of the Jenkinsfile running. Typically the reference to the script calling the pipeline step is provided with the `this` parameter, as in `script: this`. This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md) for retrieving, for example, configuration parameters. * `changeDocumentId` - The id of the change document to transport. * `credentialsId` - The credentials to connect to the Solution Manager. * `endpoint` - The address of the Solution Manager. * `clientOpts`- Options forwarded to JVM used by the CM client, like `JAVA_OPTS` +* `gitFrom` - The starting point for retrieving the change document id +* `gitTo` - The end point for retrieving the change document id +* `gitChangeDocumentLabel` - A pattern used for identifying lines holding the change document id. +* `gitFormat` - Specifies what part of the commit is scanned. By default the body of the commit message is scanned. ## Step configuration The following parameters can also be specified as step parameters using the global configuration file: diff --git a/documentation/docs/steps/transportRequestUploadFile.md b/documentation/docs/steps/transportRequestUploadFile.md index 2f49986b1..56087acbe 100644 --- a/documentation/docs/steps/transportRequestUploadFile.md +++ b/documentation/docs/steps/transportRequestUploadFile.md @@ -16,6 +16,10 @@ Uploads a file to a Transport Request for a Change Document on the Solution Mana | `filePath` | yes | | | | `credentialsId` | yes | | | | `endpoint` | yes | | | +| `gitFrom` | no | `origin/master` | | +| `gitTo` | no | `HEAD` | | +| `gitChangeDocumentLabel` | no | `ChangeDocument\s?:` | regex pattern | +| `gitFormat` | no | `%b` | see `git log --help` | * `script` - The common script environment of the Jenkinsfile running. Typically the reference to the script calling the pipeline step is provided with the `this` parameter, as in `script: this`. This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md) for retrieving, for example, configuration parameters. * `changeDocumentId` - The id of the change document related to the transport request to release. @@ -24,6 +28,10 @@ Uploads a file to a Transport Request for a Change Document on the Solution Mana * `filePath` - The path of the file to upload. * `credentialsId` - The credentials to connect to the Solution Manager. * `endpoint` - The address of the Solution Manager. +* `gitFrom` - The starting point for retrieving the change document id +* `gitTo` - The end point for retrieving the change document id +* `gitChangeDocumentLabel` - A pattern used for identifying lines holding the change document id. +* `gitFormat` - Specifies what part of the commit is scanned. By default the body of the commit message is scanned. ## Step configuration The following parameters can also be specified as step parameters using the global configuration file: diff --git a/resources/default_pipeline_environment.yml b/resources/default_pipeline_environment.yml index a859e7f34..cf0ecc851 100644 --- a/resources/default_pipeline_environment.yml +++ b/resources/default_pipeline_environment.yml @@ -8,12 +8,15 @@ steps: timestampTemplate: '%Y%m%d%H%M%S' tagPrefix: 'build_' commitVersion: true - maven: - filePath: 'pom.xml' - versioningTemplate: '${version}-${timestamp}${commitId?"_"+commitId:""}' docker: filePath: 'Dockerfile' versioningTemplate: '${version}-${timestamp}${commitId?"_"+commitId:""}' + maven: + filePath: 'pom.xml' + versioningTemplate: '${version}-${timestamp}${commitId?"_"+commitId:""}' + mta: + filePath: 'mta.yaml' + versioningTemplate: '${version}-${timestamp}${commitId?"+"+commitId:""}' checksPublishResults: aggregation: active: true @@ -92,7 +95,7 @@ steps: newmanCollection: '**/*.postman_collection.json' newmanEnvironment: '' newmanGlobals: '' - newmanRunCommand: "run ${config.newmanCollection} --environment '${config.newmanEnvironment}' --globals '${config.newmanGlobals}' --reporters junit,html --reporter-junit-export target/newman/TEST-${config.newmanCollection.toString().replaceAll('/','_').tokenize('.').first()}.xml --reporter-html-export target/newman/TEST-${config.newmanCollection.toString().replaceAll('/','_').tokenize('.').first()}.html" + newmanRunCommand: "run ${config.newmanCollection} --environment '${config.newmanEnvironment}' --globals '${config.newmanGlobals}' --reporters junit,html --reporter-junit-export target/newman/TEST-${collectionDisplayName}.xml --reporter-html-export target/newman/TEST-${collectionDisplayName}.html" pipelineStashFilesAfterBuild: runOpaTests: false stashIncludes: diff --git a/src/com/sap/piper/ConfigurationHelper.groovy b/src/com/sap/piper/ConfigurationHelper.groovy index 4e6bb6627..ee78dc459 100644 --- a/src/com/sap/piper/ConfigurationHelper.groovy +++ b/src/com/sap/piper/ConfigurationHelper.groovy @@ -109,10 +109,7 @@ class ConfigurationHelper implements Serializable { def getMandatoryProperty(key, defaultValue = null, errorMessage = null) { - def paramValue = config[key] - - if (paramValue == null) - paramValue = defaultValue + def paramValue = getConfigProperty(key, defaultValue) if (paramValue == null) { if(! errorMessage) errorMessage = "ERROR - NO VALUE AVAILABLE FOR ${key}" diff --git a/src/com/sap/piper/VersionUtils.groovy b/src/com/sap/piper/VersionUtils.groovy index 270125837..9e1087e26 100644 --- a/src/com/sap/piper/VersionUtils.groovy +++ b/src/com/sap/piper/VersionUtils.groovy @@ -5,9 +5,12 @@ import hudson.AbortException class VersionUtils implements Serializable { - def static verifyVersion(script, name, executable, String version, versionOption) { + def static getVersion(script, name, executable, versionOption) { - script.echo "Verifying $name version $version or compatible version." + return new Version(getVersionDesc(script, name, executable, versionOption)) + } + + def static getVersionDesc(script, name, executable, versionOption) { def toolVersion try { @@ -16,25 +19,47 @@ class VersionUtils implements Serializable { } catch(AbortException e) { throw new AbortException("The verification of $name failed. Please check '$executable'. $e.message.") } - def installedVersion = new Version(toolVersion) + + return toolVersion + } + + def static verifyVersion(script, name, executable, String version, versionOption) { + + script.echo "Verifying $name version $version or compatible version." + + Version installedVersion = getVersion(script, name, executable, versionOption) + if (!installedVersion.isCompatibleVersion(new Version(version))) { throw new AbortException("The installed version of $name is ${installedVersion.toString()}. Please install version $version or a compatible version.") } script.echo "Verification success. $name version ${installedVersion.toString()} is installed." } + def static verifyVersion(script, name, String versionDesc, String versionExpected) { + + script.echo "Verifying $name version $versionExpected or compatible version." + + Version versionAvailable = new Version(versionDesc) + + if (!versionAvailable.isCompatibleVersion(new Version(versionExpected))) { + throw new AbortException("The installed version of $name is ${versionAvailable.toString()}. Please install version $versionExpected or a compatible version.") + } + script.echo "Verification success. $name version ${versionAvailable.toString()} is installed." + } + + def static verifyVersion(script, name, executable, Map versions, versionOption) { - def toolVersion - try { - toolVersion = script.sh returnStdout: true, script: """#!/bin/bash - $executable $versionOption""" - } catch(AbortException e) { - throw new AbortException("The verification of $name failed. Please check '$executable'. $e.message.") - } + def versionDesc = getVersionDesc(script, name, executable, versionOption) + + verifyVersion(script, name, versionDesc, versions) + } + + def static verifyVersion(script, name, String versionDesc, Map versions) { + for (def entry : versions) { - if (toolVersion.contains(entry.getKey())) { - def installedVersion = new Version(toolVersion) + if (versionDesc.contains(entry.getKey())) { + def installedVersion = new Version(versionDesc) def expectedVersion = entry.getValue() script.echo "Verifying $name version $expectedVersion or compatible version." if (!installedVersion.isCompatibleVersion(new Version(expectedVersion))) { diff --git a/src/com/sap/piper/cm/ChangeManagement.groovy b/src/com/sap/piper/cm/ChangeManagement.groovy index a1bb73de9..985768299 100644 --- a/src/com/sap/piper/cm/ChangeManagement.groovy +++ b/src/com/sap/piper/cm/ChangeManagement.groovy @@ -42,13 +42,13 @@ public class ChangeManagement implements Serializable { return changeIds.get(0) } - boolean isChangeInDevelopment(String changeId, String endpoint, String username, String password, String cmclientOpts = '') { + boolean isChangeInDevelopment(String changeId, String endpoint, String username, String password, String clientOpts = '') { int rc = script.sh(returnStatus: true, script: getCMCommandLine(endpoint, username, password, 'is-change-in-development', ['-cID', "'${changeId}'", '--return-code'], - cmclientOpts)) + clientOpts)) if(rc == 0) { return true @@ -72,13 +72,14 @@ public class ChangeManagement implements Serializable { } } - void uploadFileToTransportRequest(String changeId, String transportRequestId, String applicationId, String filePath, String endpoint, String username, String password) { + void uploadFileToTransportRequest(String changeId, String transportRequestId, String applicationId, String filePath, String endpoint, String username, String password, String cmclientOpts = '') { int rc = script.sh(returnStatus: true, script: getCMCommandLine(endpoint, username, password, 'upload-file-to-transport', ['-cID', changeId, '-tID', transportRequestId, - applicationId, filePath])) + applicationId, filePath], + cmclientOpts)) if(rc == 0) { return @@ -87,12 +88,13 @@ public class ChangeManagement implements Serializable { } } - void releaseTransportRequest(String changeId, String transportRequestId, String endpoint, String username, String password) { + void releaseTransportRequest(String changeId, String transportRequestId, String endpoint, String username, String password, String clientOpts = '') { int rc = script.sh(returnStatus: true, script: getCMCommandLine(endpoint, username, password, 'release-transport', ['-cID', changeId, - '-tID', transportRequestId])) + '-tID', transportRequestId], + clientOpts)) if(rc == 0) { return @@ -106,11 +108,11 @@ public class ChangeManagement implements Serializable { String password, String command, List args, - String cmclientOpts = '') { + String clientOpts = '') { String cmCommandLine = '#!/bin/bash' - if(cmclientOpts) { + if(clientOpts) { cmCommandLine += """ - export CMCLIENT_OPTS="${cmclientOpts}" """ + export CMCLIENT_OPTS="${clientOpts}" """ } cmCommandLine += """ cmclient -e '$endpoint' \ diff --git a/src/com/sap/piper/tools/ToolDescriptor.groovy b/src/com/sap/piper/tools/ToolDescriptor.groovy index 0f4681889..7886d5c9b 100644 --- a/src/com/sap/piper/tools/ToolDescriptor.groovy +++ b/src/com/sap/piper/tools/ToolDescriptor.groovy @@ -108,8 +108,9 @@ class ToolDescriptor implements Serializable { def verifyVersion(script, configuration) { def executable = getToolExecutable(script, configuration, false) - if (singleVersion) VersionUtils.verifyVersion(script, name, executable, singleVersion, versionOption) - if (multipleVersions) VersionUtils.verifyVersion(script, name, executable, multipleVersions, versionOption) + def versionDesc = VersionUtils.getVersionDesc(script, name, executable, versionOption) + if (singleVersion) VersionUtils.verifyVersion(script, name, versionDesc, singleVersion) + if (multipleVersions) VersionUtils.verifyVersion(script, name, versionDesc, multipleVersions) } def getMessage() { diff --git a/src/com/sap/piper/versioning/ArtifactVersioning.groovy b/src/com/sap/piper/versioning/ArtifactVersioning.groovy index f16cbbf54..7cdfa744b 100644 --- a/src/com/sap/piper/versioning/ArtifactVersioning.groovy +++ b/src/com/sap/piper/versioning/ArtifactVersioning.groovy @@ -12,6 +12,8 @@ abstract class ArtifactVersioning implements Serializable { public static getArtifactVersioning(buildTool, script, configuration) { switch (buildTool) { + case 'mta': + return new MtaArtifactVersioning(script, configuration) case 'maven': return new MavenArtifactVersioning(script, configuration) case 'docker': diff --git a/src/com/sap/piper/versioning/MtaArtifactVersioning.groovy b/src/com/sap/piper/versioning/MtaArtifactVersioning.groovy new file mode 100644 index 000000000..dfbc39eb6 --- /dev/null +++ b/src/com/sap/piper/versioning/MtaArtifactVersioning.groovy @@ -0,0 +1,21 @@ +package com.sap.piper.versioning + +class MtaArtifactVersioning extends ArtifactVersioning { + + protected MtaArtifactVersioning (script, configuration) { + super(script, configuration) + } + + @Override + def getVersion() { + def mtaYaml = script.readYaml file: configuration.filePath + return mtaYaml.version + } + + @Override + def setVersion(version) { + def search = "version: ${getVersion()}" + def replacement = "version: ${version}" + script.sh "sed -i 's/${search}/${replacement}/g' ${configuration.filePath}" + } +} diff --git a/test/groovy/CheckChangeInDevelopmentTest.groovy b/test/groovy/CheckChangeInDevelopmentTest.groovy index 037acf3fd..d030dabe1 100644 --- a/test/groovy/CheckChangeInDevelopmentTest.groovy +++ b/test/groovy/CheckChangeInDevelopmentTest.groovy @@ -134,8 +134,10 @@ class CheckChangeInDevelopmentTest extends BasePiperTest { @Test public void nullChangeDocumentIdTest() { - thrown.expect(AbortException) - thrown.expectMessage("ChangeId is null or empty.") + thrown.expect(IllegalArgumentException) + thrown.expectMessage("No changeDocumentId provided. Neither via parameter 'changeDocumentId' " + + "nor via label 'ChangeDocument\\s?:' in commit range " + + "[from: origin/master, to: HEAD].") ChangeManagement cm = getChangeManagementUtils(false, null) jsr.step.checkChangeInDevelopment( @@ -146,8 +148,10 @@ class CheckChangeInDevelopmentTest extends BasePiperTest { @Test public void emptyChangeDocumentIdTest() { - thrown.expect(AbortException) - thrown.expectMessage("ChangeId is null or empty.") + thrown.expect(IllegalArgumentException) + thrown.expectMessage("No changeDocumentId provided. Neither via parameter 'changeDocumentId' " + + "nor via label 'ChangeDocument\\s?:' in commit range " + + "[from: origin/master, to: HEAD].") ChangeManagement cm = getChangeManagementUtils(false, '') jsr.step.checkChangeInDevelopment( diff --git a/test/groovy/NewmanExecuteTest.groovy b/test/groovy/NewmanExecuteTest.groovy index 30369bd7d..8b80b55dc 100644 --- a/test/groovy/NewmanExecuteTest.groovy +++ b/test/groovy/NewmanExecuteTest.groovy @@ -86,11 +86,11 @@ class NewmanExecuteTest extends BasePiperTest { void testExecuteNewmanWithFolder() throws Exception { jsr.step.newmanExecute( script: nullScript, - newmanRunCommand: 'run ${config.newmanCollection} --iteration-data testDataFile --reporters junit,html --reporter-junit-export target/newman/TEST-${config.newmanCollection.toString().replaceAll(\'/\',\'_\').tokenize(\'.\').first()}.xml --reporter-html-export target/newman/TEST-${config.newmanCollection.toString().replaceAll(\'/\',\'_\').tokenize(\'.\').first()}.html' + newmanRunCommand: 'run ${config.newmanCollection} --iteration-data testDataFile --reporters junit,html --reporter-junit-export target/newman/TEST-${config.newmanCollection.toString().replace(File.separatorChar,(char)\'_\').tokenize(\'.\').first()}.xml --reporter-html-export target/newman/TEST-${config.newmanCollection.toString().replace(File.separatorChar,(char)\'_\').tokenize(\'.\').first()}.html' ) // asserts - assertThat(jscr.shell, hasItem('newman run testCollectionsFolder/A.postman_collection.json --iteration-data testDataFile --reporters junit,html --reporter-junit-export target/newman/TEST-testCollectionsFolder_A.xml --reporter-html-export target/newman/TEST-testCollectionsFolder_A.html')) - assertThat(jscr.shell, hasItem('newman run testCollectionsFolder/B.postman_collection.json --iteration-data testDataFile --reporters junit,html --reporter-junit-export target/newman/TEST-testCollectionsFolder_B.xml --reporter-html-export target/newman/TEST-testCollectionsFolder_B.html')) + assertThat(jscr.shell, hasItem('newman run testCollectionsFolder'+File.separatorChar+'A.postman_collection.json --iteration-data testDataFile --reporters junit,html --reporter-junit-export target/newman/TEST-testCollectionsFolder_A.xml --reporter-html-export target/newman/TEST-testCollectionsFolder_A.html')) + assertThat(jscr.shell, hasItem('newman run testCollectionsFolder'+File.separatorChar+'B.postman_collection.json --iteration-data testDataFile --reporters junit,html --reporter-junit-export target/newman/TEST-testCollectionsFolder_B.xml --reporter-html-export target/newman/TEST-testCollectionsFolder_B.html')) assertJobStatusSuccess() } } diff --git a/test/groovy/ToolValidateTest.groovy b/test/groovy/ToolValidateTest.groovy index c3d52b6a6..c6538b752 100644 --- a/test/groovy/ToolValidateTest.groovy +++ b/test/groovy/ToolValidateTest.groovy @@ -144,17 +144,6 @@ class ToolValidateTest extends BasePiperTest { jsr.step.call(tool: 'mta', home: home) } - @Test - void validateNeoIncompatibleVersionTest() { - - thrown.expect(AbortException) - thrown.expectMessage('The installed version of SAP Cloud Platform Console Client is 1.126.51.') - - helper.registerAllowedMethod('sh', [Map], { Map m -> getIncompatibleVersion(m) }) - - jsr.step.call(tool: 'neo', home: home) - } - @Test void validateCmIncompatibleVersionTest() { @@ -195,9 +184,6 @@ class ToolValidateTest extends BasePiperTest { helper.registerAllowedMethod('sh', [Map], { Map m -> getVersion(m) }) jsr.step.call(tool: 'neo', home: home) - - assert jlr.log.contains('Verifying SAP Cloud Platform Console Client version 3.39.10 or compatible version.') - assert jlr.log.contains('SAP Cloud Platform Console Client version 3.39.10 is installed.') } @Test diff --git a/test/groovy/TransportRequestCreateTest.groovy b/test/groovy/TransportRequestCreateTest.groovy index be6750d71..269b8ec98 100644 --- a/test/groovy/TransportRequestCreateTest.groovy +++ b/test/groovy/TransportRequestCreateTest.groovy @@ -61,17 +61,27 @@ public class TransportRequestCreateTest extends BasePiperTest { @Test public void changeIdNotProvidedTest() { - thrown.expect(AbortException) - thrown.expectMessage("Change document id not provided (parameter: 'changeDocumentId').") + thrown.expect(IllegalArgumentException) + thrown.expectMessage("Change document id not provided (parameter: 'changeDocumentId' or via commit history).") + ChangeManagement cm = new ChangeManagement(nullScript) { + String getChangeDocumentId( + String from, + String to, + String label, + String format + ) { + throw new ChangeManagementException('Cannot retrieve changeId from git commits.') + } + } - jsr.step.call(script: nullScript, developmentSystemId: '001') + jsr.step.call(script: nullScript, developmentSystemId: '001', cmUtils: cm) } @Test public void developmentSystemIdNotProvidedTest() { - thrown.expect(AbortException) - thrown.expectMessage("Development system id not provided (parameter: 'developmentSystemId').") + thrown.expect(IllegalArgumentException) + thrown.expectMessage("ERROR - NO VALUE AVAILABLE FOR developmentSystemId") jsr.step.call(script: nullScript, changeDocumentId: '001') } diff --git a/test/groovy/TransportRequestReleaseTest.groovy b/test/groovy/TransportRequestReleaseTest.groovy index 6bb8fc1f1..9f7b79ddb 100644 --- a/test/groovy/TransportRequestReleaseTest.groovy +++ b/test/groovy/TransportRequestReleaseTest.groovy @@ -69,8 +69,8 @@ public class TransportRequestReleaseTest extends BasePiperTest { } } - thrown.expect(AbortException) - thrown.expectMessage("Change document id not provided (parameter: 'changeDocumentId' or via commit history).") + thrown.expect(IllegalArgumentException) + thrown.expectMessage("ERROR - NO VALUE AVAILABLE FOR changeDocumentId") jsr.step.call(script: nullScript, transportRequestId: '001', cmUtils: cm) } @@ -78,8 +78,8 @@ public class TransportRequestReleaseTest extends BasePiperTest { @Test public void transportRequestIdNotProvidedTest() { - thrown.expect(AbortException) - thrown.expectMessage("Transport Request id not provided (parameter: 'transportRequestId').") + thrown.expect(IllegalArgumentException) + thrown.expectMessage("ERROR - NO VALUE AVAILABLE FOR transportRequestId") jsr.step.call(script: nullScript, changeDocumentId: '001') } diff --git a/test/groovy/TransportRequestUploadFileTest.groovy b/test/groovy/TransportRequestUploadFileTest.groovy index cfaf6b60f..08ab99eee 100644 --- a/test/groovy/TransportRequestUploadFileTest.groovy +++ b/test/groovy/TransportRequestUploadFileTest.groovy @@ -60,17 +60,28 @@ public class TransportRequestUploadFileTest extends BasePiperTest { @Test public void changeDocumentIdNotProvidedTest() { - thrown.expect(AbortException) - thrown.expectMessage("Change document id not provided (parameter: 'changeDocumentId').") + thrown.expect(IllegalArgumentException) + thrown.expectMessage("Change document id not provided (parameter: 'changeDocumentId' or via commit history).") - jsr.step.call(script: nullScript, transportRequestId: '001', applicationId: 'app', filePath: '/path') + ChangeManagement cm = new ChangeManagement(nullScript) { + String getChangeDocumentId( + String from, + String to, + String pattern, + String format + ) { + throw new ChangeManagementException('Cannot retrieve changeId from git commits.') + } + } + + jsr.step.call(script: nullScript, transportRequestId: '001', applicationId: 'app', filePath: '/path', cmUtils: cm) } @Test public void transportRequestIdNotProvidedTest() { - thrown.expect(AbortException) - thrown.expectMessage("Transport Request id not provided (parameter: 'transportRequestId').") + thrown.expect(IllegalArgumentException) + thrown.expectMessage("ERROR - NO VALUE AVAILABLE FOR transportRequestId") jsr.step.call(script: nullScript, changeDocumentId: '001', applicationId: 'app', filePath: '/path') } @@ -78,8 +89,8 @@ public class TransportRequestUploadFileTest extends BasePiperTest { @Test public void applicationIdNotProvidedTest() { - thrown.expect(AbortException) - thrown.expectMessage("Application id not provided (parameter: 'applicationId').") + thrown.expect(IllegalArgumentException) + thrown.expectMessage("ERROR - NO VALUE AVAILABLE FOR applicationId") jsr.step.call(script: nullScript, changeDocumentId: '001', transportRequestId: '001', filePath: '/path') } @@ -87,8 +98,8 @@ public class TransportRequestUploadFileTest extends BasePiperTest { @Test public void filePathNotProvidedTest() { - thrown.expect(AbortException) - thrown.expectMessage("File path not provided (parameter: 'filePath').") + thrown.expect(IllegalArgumentException) + thrown.expectMessage("ERROR - NO VALUE AVAILABLE FOR filePath") jsr.step.call(script: nullScript, changeDocumentId: '001', transportRequestId: '001', applicationId: 'app') } @@ -103,7 +114,8 @@ public class TransportRequestUploadFileTest extends BasePiperTest { String filePath, String endpoint, String username, - String password) { + String password, + String cmclientOpts) { throw new ChangeManagementException('Exception message') } } diff --git a/test/groovy/com/sap/piper/VersionUtilsTest.groovy b/test/groovy/com/sap/piper/VersionUtilsTest.groovy new file mode 100644 index 000000000..118b7d8d2 --- /dev/null +++ b/test/groovy/com/sap/piper/VersionUtilsTest.groovy @@ -0,0 +1,83 @@ +package com.sap.piper + +import hudson.AbortException +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.ExpectedException +import org.junit.rules.RuleChain +import util.BasePiperTest +import util.JenkinsShellCallRule +import util.Rules + +import static org.junit.Assert.assertEquals +import static org.hamcrest.Matchers.equalTo +import static org.junit.Assert.assertTrue +import static org.junit.Assert.assertFalse +import static org.hamcrest.Matchers.is +import static org.hamcrest.Matchers.notNullValue +import static org.junit.Assert.assertNotNull +import static org.junit.Assert.assertNull +import static org.junit.Assert.assertThat + +class VersionUtilsTest extends BasePiperTest { + + ExpectedException thrown = ExpectedException.none() + + @Rule + public RuleChain ruleChain = Rules.getCommonRules(this).around(thrown) + + @Before + void init() throws Exception { + } + + @Test + void test_if_getVersionDesc_returns_desc() { + helper.registerAllowedMethod('sh', [Map], { Map m -> return 'SAP Cloud Platform Console Client\n\n\nSDK version : 2.129.5.1\nRuntime : neo-javaee6-wp\n'}) + + assertEquals('SAP Cloud Platform Console Client\n\n\nSDK version : 2.129.5.1\nRuntime : neo-javaee6-wp\n',VersionUtils.getVersionDesc(nullScript, "test", "test.sh", "version")) + } + + @Test + void test_if_getVersion_returns_version() { + helper.registerAllowedMethod('sh', [Map], { Map m -> return 'SAP Cloud Platform Console Client\n\n\nSDK version : 2.129.5.1\nRuntime : neo-javaee6-wp\n'}) + + assertEquals(new Version('2.129.5.1'),VersionUtils.getVersion(nullScript, "test", "test.sh", "version")) + } + + @Test + void test_if_verifyVersion_succeeds_compatible() { + helper.registerAllowedMethod('sh', [Map], { Map m -> return 'version : 1.0.0\runtime: key' }) + VersionUtils.verifyVersion(nullScript, "test", "test.sh", '1.0.0', "version") + } + + @Test + void test_if_verifyVersion_fails_incompatible() { + helper.registerAllowedMethod('sh', [Map], { Map m -> return 'version : 1.0.0\runtime: key' }) + + thrown.expect(AbortException) + thrown.expectMessage("The installed version of test is 1.0.0. Please install version 1.0.1 or a compatible version.") + + VersionUtils.verifyVersion(nullScript, "test", "test.sh", '1.0.1', "version") + } + + @Test + void test_if_verifyVersion_map_succeeds_compatible() { + Map versionMap = ['key1': '1.0.0', 'key2': '2.0.0', 'key3': '3.0.0'] + helper.registerAllowedMethod('sh', [Map], { Map m -> return 'version : 1.0.0\runtime: key1' }) + VersionUtils.verifyVersion(nullScript, "test", "test.sh", versionMap, "version") + } + + @Test + void test_if_verifyVersion_map_fails_incompatible() { + Map versionMap = ['key1': '1.0.1', 'key2': '2.0.1', 'key3': '3.0.1'] + helper.registerAllowedMethod('sh', [Map], { Map m -> return 'version : 1.0.0\runtime: key1' }) + + thrown.expect(AbortException) + thrown.expectMessage("The installed version of test is 1.0.0. Please install version 1.0.1 or a compatible version.") + + VersionUtils.verifyVersion(nullScript, "test", "test.sh", versionMap, "version") + } + + +} diff --git a/test/groovy/com/sap/piper/tools/ToolDescriptorTest.groovy b/test/groovy/com/sap/piper/tools/ToolDescriptorTest.groovy index 69506d281..11da4eff4 100644 --- a/test/groovy/com/sap/piper/tools/ToolDescriptorTest.groovy +++ b/test/groovy/com/sap/piper/tools/ToolDescriptorTest.groovy @@ -193,6 +193,17 @@ class ToolDescriptorTest extends BasePiperTest { tool.verifyVersion(script, configuration) } + @Test + void verifyToolVersion_without_version_check() { + + def tool = new ToolDescriptor('SAP Cloud Platform Console Client', 'NEO_HOME', 'neoHome', '/tools/', 'neo.sh', null, 'version') + + helper.registerAllowedMethod('sh', [Map], { Map m -> getVersion(m) }) + + tool.verifyVersion(script, configuration) + } + + private getEnvVars(Map m) { diff --git a/test/groovy/com/sap/piper/versioning/MtaArtifactVersioningTest.groovy b/test/groovy/com/sap/piper/versioning/MtaArtifactVersioningTest.groovy new file mode 100644 index 000000000..770b63d46 --- /dev/null +++ b/test/groovy/com/sap/piper/versioning/MtaArtifactVersioningTest.groovy @@ -0,0 +1,31 @@ +package com.sap.piper.versioning + +import org.junit.Rule +import org.junit.Test +import org.junit.rules.RuleChain +import util.BasePiperTest +import util.JenkinsReadYamlRule +import util.JenkinsShellCallRule +import util.Rules + +import static org.junit.Assert.assertEquals + +class MtaArtifactVersioningTest extends BasePiperTest{ + + JenkinsReadYamlRule jryr = new JenkinsReadYamlRule(this, 'test/resources/versioning/MtaArtifactVersioning/') + JenkinsShellCallRule jscr = new JenkinsShellCallRule(this) + + @Rule + public RuleChain ruleChain = Rules + .getCommonRules(this) + .around(jryr) + .around(jscr) + + @Test + void testVersioning() { + MtaArtifactVersioning av = new MtaArtifactVersioning(nullScript, [filePath: 'mta.yaml']) + assertEquals('1.2.3', av.getVersion()) + av.setVersion('1.2.3-20180101') + assertEquals("sed -i 's/version: 1.2.3/version: 1.2.3-20180101/g' mta.yaml", jscr.shell[0]) + } +} diff --git a/test/groovy/util/JenkinsLoggingRule.groovy b/test/groovy/util/JenkinsLoggingRule.groovy index 8401c97ad..ed0ef0048 100644 --- a/test/groovy/util/JenkinsLoggingRule.groovy +++ b/test/groovy/util/JenkinsLoggingRule.groovy @@ -1,20 +1,33 @@ package util import com.lesfurets.jenkins.unit.BasePipelineTest + +import org.junit.Assert import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement +import static org.hamcrest.Matchers.containsString +import static org.junit.Assert.assertThat; + +import org.hamcrest.Matchers + class JenkinsLoggingRule implements TestRule { final BasePipelineTest testInstance + def expected = [] + String log = "" JenkinsLoggingRule(BasePipelineTest testInstance) { this.testInstance = testInstance } + public void expect(String substring) { + expected.add(substring) + } + @Override Statement apply(Statement base, Description description) { return statement(base) @@ -30,7 +43,30 @@ class JenkinsLoggingRule implements TestRule { log += "$echoInput \n" }) - base.evaluate() + Throwable caught + + try { + base.evaluate() + } catch(Throwable thr) { + caught = thr + } finally { + if(caught instanceof AssertionError) { + // Be polite, give other rules the advantage. + // We expect other rules located closer to the test case + // to throw an AssertionError in case of a violation. + throw caught + } + + expected.each { substring -> assertThat("Substring '${substring}' not contained in log.", + log, + containsString(substring)) } + + if(caught != null) { + // do not swallow, so that other rules located farer away + // to the test case can react + throw caught + } + } } } } diff --git a/test/groovy/util/JenkinsReadYamlRule.groovy b/test/groovy/util/JenkinsReadYamlRule.groovy index 09b3248a2..89820f2e2 100644 --- a/test/groovy/util/JenkinsReadYamlRule.groovy +++ b/test/groovy/util/JenkinsReadYamlRule.groovy @@ -8,12 +8,12 @@ import org.junit.runners.model.Statement import org.yaml.snakeyaml.Yaml class JenkinsReadYamlRule implements TestRule { - final BasePipelineTest testInstance + final String testRoot - - JenkinsReadYamlRule(BasePipelineTest testInstance) { + JenkinsReadYamlRule(BasePipelineTest testInstance, testRoot = '') { this.testInstance = testInstance + this.testRoot = testRoot } @Override @@ -29,7 +29,7 @@ class JenkinsReadYamlRule implements TestRule { if(m.text) { return new Yaml().load(m.text) } else if(m.file) { - return new Yaml().load((m.file as File).text) + return new Yaml().load(("${this.testRoot}${m.file}" as File).text) } else { throw new IllegalArgumentException("Key 'text' is missing in map ${m}.") } diff --git a/test/resources/versioning/MtaArtifactVersioning/mta.yaml b/test/resources/versioning/MtaArtifactVersioning/mta.yaml new file mode 100644 index 000000000..ccf2fbb91 --- /dev/null +++ b/test/resources/versioning/MtaArtifactVersioning/mta.yaml @@ -0,0 +1,11 @@ +_schema-version: "2.0" +ID: com.sap.samples.anything +version: 1.2.3 + +modules: + - name: any-ui + type: html5 + path: any-ui/ + +resources: + - name: any-resource diff --git a/vars/checkChangeInDevelopment.groovy b/vars/checkChangeInDevelopment.groovy index dc7bfeda9..64b2c6b49 100644 --- a/vars/checkChangeInDevelopment.groovy +++ b/vars/checkChangeInDevelopment.groovy @@ -2,14 +2,14 @@ import com.sap.piper.GitUtils import groovy.transform.Field import hudson.AbortException +import com.sap.piper.ConfigurationHelper import com.sap.piper.ConfigurationMerger import com.sap.piper.cm.ChangeManagement import com.sap.piper.cm.ChangeManagementException @Field def STEP_NAME = 'checkChangeInDevelopment' -@Field Set parameterKeys = [ - 'changeDocumentId', +@Field Set stepConfigurationKeys = [ 'cmClientOpts', 'credentialsId', 'endpoint', @@ -20,31 +20,28 @@ import com.sap.piper.cm.ChangeManagementException 'gitFormat' ] -@Field Set stepConfigurationKeys = [ - 'changeDocumentId', - 'cmClientOpts', - 'credentialsId', - 'endpoint', - 'failIfStatusIsNotInDevelopment', - 'gitFrom', - 'gitTo', - 'gitChangeDocumentLabel', - 'gitFormat' - ] +@Field Set parameterKeys = stepConfigurationKeys.plus('changeDocumentId') + +@Field Set generalConfigurationKeys = stepConfigurationKeys def call(parameters = [:]) { handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) { - prepareDefaultValues script: this + def script = parameters.script ?: [commonPipelineEnvironment: commonPipelineEnvironment] GitUtils gitUtils = parameters?.gitUtils ?: new GitUtils() - ChangeManagement cm = parameters?.cmUtils ?: new ChangeManagement(parameters.script, gitUtils) + ChangeManagement cm = parameters?.cmUtils ?: new ChangeManagement(script, gitUtils) - Map configuration = ConfigurationMerger.merge(parameters.script, STEP_NAME, - parameters, parameterKeys, - stepConfigurationKeys) + ConfigurationHelper configHelper = ConfigurationHelper + .loadStepDefaults(this) + .mixinGeneralConfig(script.commonPipelineEnvironment, generalConfigurationKeys) + .mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, stepConfigurationKeys) + .mixinStepConfig(script.commonPipelineEnvironment, stepConfigurationKeys) + .mixin(parameters, parameterKeys) + + Map configuration = configHelper.use() def changeId = configuration.changeDocumentId @@ -66,17 +63,23 @@ def call(parameters = [:]) { ) if(changeId?.trim()) { echo "[INFO] ChangeDocumentId '${changeId}' retrieved from commit history" - } else { - throw new ChangeManagementException("ChangeId is null or empty.") } } catch(ChangeManagementException ex) { throw new AbortException(ex.getMessage()) } } + configuration = configHelper.mixin([changeDocumentId: changeId?.trim() ?: null], ['changeDocumentId'] as Set) + .withMandatoryProperty('endpoint') + .withMandatoryProperty('changeDocumentId', + "No changeDocumentId provided. Neither via parameter 'changeDocumentId' " + + "nor via label '${configuration.gitChangeDocumentLabel}' in commit range " + + "[from: ${configuration.gitFrom}, to: ${configuration.gitTo}].") + .use() + boolean isInDevelopment - echo "[INFO] Checking if change document '$changeId' is in development." + echo "[INFO] Checking if change document '${configuration.changeDocumentId}' is in development." withCredentials([usernamePassword( credentialsId: configuration.credentialsId, @@ -84,7 +87,11 @@ def call(parameters = [:]) { usernameVariable: 'username')]) { try { - isInDevelopment = cm.isChangeInDevelopment(changeId, configuration.endpoint, username, password, configuration.cmClientOpts) + isInDevelopment = cm.isChangeInDevelopment(configuration.changeDocumentId, + configuration.endpoint, + username, + password, + configuration.cmClientOpts) } catch(ChangeManagementException ex) { throw new AbortException(ex.getMessage()) } diff --git a/vars/neoDeploy.groovy b/vars/neoDeploy.groovy index f4150ad9b..8cfec18df 100644 --- a/vars/neoDeploy.groovy +++ b/vars/neoDeploy.groovy @@ -148,8 +148,7 @@ def call(parameters = [:]) { deployAccount = utils.getMandatoryParameter(configuration, 'account') } - def neoVersions = ['neo-java-web': '3.39.10', 'neo-javaee6-wp': '2.132.6', 'neo-javaee7-wp': '1.21.13'] - def neo = new ToolDescriptor('SAP Cloud Platform Console Client', 'NEO_HOME', 'neoHome', '/tools/', 'neo.sh', neoVersions, 'version') + def neo = new ToolDescriptor('SAP Cloud Platform Console Client', 'NEO_HOME', 'neoHome', '/tools/', 'neo.sh', null, 'version') def neoExecutable = neo.getToolExecutable(this, configuration) def neoDeployScript = """#!/bin/bash "${neoExecutable}" ${warAction} \ diff --git a/vars/newmanExecute.groovy b/vars/newmanExecute.groovy index 4bc721318..876622641 100644 --- a/vars/newmanExecute.groovy +++ b/vars/newmanExecute.groovy @@ -37,10 +37,14 @@ def call(Map parameters = [:]) { ) { sh 'npm install newman --global --quiet' for(String collection : collectionList){ + def collectionDisplayName = collection.toString().replace(File.separatorChar,(char)'_').tokenize('.').first() // resolve templates def command = SimpleTemplateEngine.newInstance() .createTemplate(config.newmanRunCommand) - .make([config: config.plus([newmanCollection: collection])]).toString() + .make([ + config: config.plus([newmanCollection: collection]), + collectionDisplayName: collectionDisplayName + ]).toString() if(!config.failOnError) command += ' --suppress-exit-code' sh "newman ${command}" } diff --git a/vars/toolValidate.groovy b/vars/toolValidate.groovy index f1551a28b..eb840e060 100644 --- a/vars/toolValidate.groovy +++ b/vars/toolValidate.groovy @@ -31,8 +31,7 @@ def call(Map parameters = [:]) { mta.verifyVersion(this, [mtaJarLocation: home]) return case 'neo': - def neoVersions = ['neo-java-web': '3.39.10', 'neo-javaee6-wp': '2.132.6', 'neo-javaee7-wp': '1.21.13'] - def neo = new ToolDescriptor('SAP Cloud Platform Console Client', 'NEO_HOME', 'neoHome', '/tools/', 'neo.sh', neoVersions, 'version') + def neo = new ToolDescriptor('SAP Cloud Platform Console Client', 'NEO_HOME', 'neoHome', '/tools/', 'neo.sh', null, 'version') neo.verifyVersion(this, [neoHome: home]) return case 'cm': diff --git a/vars/transportRequestCreate.groovy b/vars/transportRequestCreate.groovy index f737d9d37..c0db4852c 100644 --- a/vars/transportRequestCreate.groovy +++ b/vars/transportRequestCreate.groovy @@ -1,6 +1,7 @@ import com.sap.piper.GitUtils import groovy.transform.Field +import com.sap.piper.ConfigurationHelper import com.sap.piper.ConfigurationMerger import com.sap.piper.cm.ChangeManagement import com.sap.piper.cm.ChangeManagementException @@ -10,20 +11,20 @@ import hudson.AbortException @Field def STEP_NAME = 'transportRequestCreate' -@Field Set parameterKeys = [ - 'changeDocumentId', - 'clientOpts', - 'developmentSystemId', - 'credentialsId', - 'endpoint' - ] - @Field Set stepConfigurationKeys = [ 'credentialsId', 'clientOpts', - 'endpoint' + 'endpoint', + 'gitFrom', + 'gitTo', + 'gitChangeDocumentLabel', + 'gitFormat' ] +@Field Set parameterKeys = stepConfigurationKeys.plus(['changeDocumentId', 'developmentSystemId']) + +@Field generalConfigurationKeys = stepConfigurationKeys + def call(parameters = [:]) { handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) { @@ -32,33 +33,63 @@ def call(parameters = [:]) { ChangeManagement cm = parameters.cmUtils ?: new ChangeManagement(script) - Map configuration = ConfigurationMerger.merge(parameters.script, STEP_NAME, - parameters, parameterKeys, - stepConfigurationKeys) + ConfigurationHelper configHelper = ConfigurationHelper + .loadStepDefaults(this) + .mixinGeneralConfig(script.commonPipelineEnvironment, generalConfigurationKeys) + .mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, stepConfigurationKeys) + .mixinStepConfig(script.commonPipelineEnvironment, stepConfigurationKeys) + .mixin(parameters, parameterKeys) + .withMandatoryProperty('endpoint') + .withMandatoryProperty('developmentSystemId') + + Map configuration = configHelper.use() def changeDocumentId = configuration.changeDocumentId - if(!changeDocumentId) throw new AbortException('Change document id not provided (parameter: \'changeDocumentId\').') - def developmentSystemId = configuration.developmentSystemId - if(!developmentSystemId) throw new AbortException('Development system id not provided (parameter: \'developmentSystemId\').') + if(changeDocumentId?.trim()) { - def credentialsId = configuration.credentialsId - if(!credentialsId) throw new AbortException('Credentials id not provided (parameter: \'credentialsId\').') + echo "[INFO] ChangeDocumentId '${changeDocumentId}' retrieved from parameters." - def endpoint = configuration.endpoint - if(!endpoint) throw new AbortException('Solution Manager endpoint not provided (parameter: \'endpoint\').') + } else { + + echo "[INFO] Retrieving ChangeDocumentId from commit history [from: ${configuration.gitFrom}, to: ${configuration.gitTo}]." + + "Searching for pattern '${configuration.gitChangeDocumentLabel}'. Searching with format '${configuration.gitFormat}'." + + try { + changeDocumentId = cm.getChangeDocumentId( + configuration.gitFrom, + configuration.gitTo, + configuration.gitChangeDocumentLabel, + configuration.gitFormat + ) + + echo "[INFO] ChangeDocumentId '${changeDocumentId}' retrieved from commit history" + } catch(ChangeManagementException ex) { + echo "[WARN] Cannot retrieve changeDocumentId from commit history: ${ex.getMessage()}." + } + } + + configuration = configHelper.mixin([changeDocumentId: changeDocumentId?.trim() ?: null], ['changeDocumentId'] as Set) + .withMandatoryProperty('changeDocumentId', + "Change document id not provided (parameter: \'changeDocumentId\' or via commit history).") + .use() def transportRequestId - echo "[INFO] Creating transport request for change document '$changeDocumentId' and development system '$developmentSystemId'." + echo "[INFO] Creating transport request for change document '${configuration.changeDocumentId}' and development system '${configuration.developmentSystemId}'." withCredentials([usernamePassword( - credentialsId: credentialsId, + credentialsId: configuration.credentialsId, passwordVariable: 'password', usernameVariable: 'username')]) { try { - transportRequestId = cm.createTransportRequest(changeDocumentId, developmentSystemId, endpoint, username, password, configuration.clientOpts) + transportRequestId = cm.createTransportRequest(configuration.changeDocumentId, + configuration.developmentSystemId, + configuration.endpoint, + username, + password, + configuration.clientOpts) } catch(ChangeManagementException ex) { throw new AbortException(ex.getMessage()) } diff --git a/vars/transportRequestRelease.groovy b/vars/transportRequestRelease.groovy index e549377c6..e1afd6a40 100644 --- a/vars/transportRequestRelease.groovy +++ b/vars/transportRequestRelease.groovy @@ -1,6 +1,7 @@ import com.sap.piper.GitUtils import groovy.transform.Field +import com.sap.piper.ConfigurationHelper import com.sap.piper.ConfigurationMerger import com.sap.piper.cm.ChangeManagement import com.sap.piper.cm.ChangeManagementException @@ -10,17 +11,6 @@ import hudson.AbortException @Field def STEP_NAME = 'transportRequestRelease' -@Field Set parameterKeys = [ - 'changeDocumentId', - 'transportRequestId', - 'credentialsId', - 'endpoint', - 'gitChangeDocumentLabel', - 'gitFormat', - 'gitFrom', - 'gitTo' - ] - @Field Set stepConfigurationKeys = [ 'credentialsId', 'endpoint', @@ -30,6 +20,13 @@ import hudson.AbortException 'gitTo' ] +@Field Set parameterKeys = stepConfigurationKeys.plus([ + 'changeDocumentId', + 'transportRequestId', + ]) + +@Field Set generalConfigurationKeys = stepConfigurationKeys + def call(parameters = [:]) { handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) { @@ -38,9 +35,16 @@ def call(parameters = [:]) { ChangeManagement cm = parameters.cmUtils ?: new ChangeManagement(script) - Map configuration = ConfigurationMerger.merge(script, STEP_NAME, - parameters, parameterKeys, - stepConfigurationKeys) + Map configuration = ConfigurationHelper + .loadStepDefaults(this) + .mixinGeneralConfig(script.commonPipelineEnvironment, generalConfigurationKeys) + .mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, stepConfigurationKeys) + .mixinStepConfig(script.commonPipelineEnvironment, stepConfigurationKeys) + .mixin(parameters, parameterKeys) + .withMandatoryProperty('changeDocumentId') + .withMandatoryProperty('transportRequestId') + .withMandatoryProperty('endpoint') + .use() def changeDocumentId = configuration.changeDocumentId @@ -72,31 +76,25 @@ def call(parameters = [:]) { throw new AbortException("Change document id not provided (parameter: 'changeDocumentId' or via commit history).") } - boolean isInDevelopment - - def transportRequestId = configuration.transportRequestId - if(!transportRequestId) throw new AbortException("Transport Request id not provided (parameter: 'transportRequestId').") - - def credentialsId = configuration.credentialsId - if(!credentialsId) throw new AbortException("Credentials id not provided (parameter: 'credentialsId').") - - def endpoint = configuration.endpoint - if(!endpoint) throw new AbortException("Solution Manager endpoint not provided (parameter: 'endpoint').") - - echo "[INFO] Closing transport request '$transportRequestId' for change document '$changeDocumentId'." + echo "[INFO] Closing transport request '${configuration.transportRequestId}' for change document '${configuration.changeDocumentId}'." withCredentials([usernamePassword( - credentialsId: credentialsId, + credentialsId: configuration.credentialsId, passwordVariable: 'password', usernameVariable: 'username')]) { try { - cm.releaseTransportRequest(changeDocumentId, transportRequestId, endpoint, username, password) + cm.releaseTransportRequest(configuration.changeDocumentId, + configuration.transportRequestId, + configuration.endpoint, + username, + password, + configuration.cmClientOpts) } catch(ChangeManagementException ex) { throw new AbortException(ex.getMessage()) } } - echo "[INFO] Transport Request '${transportRequestId}' has been successfully closed." + echo "[INFO] Transport Request '${configuration.transportRequestId}' has been successfully closed." } } diff --git a/vars/transportRequestUploadFile.groovy b/vars/transportRequestUploadFile.groovy index 8984af844..55fc4c978 100644 --- a/vars/transportRequestUploadFile.groovy +++ b/vars/transportRequestUploadFile.groovy @@ -1,6 +1,7 @@ import com.sap.piper.GitUtils import groovy.transform.Field +import com.sap.piper.ConfigurationHelper import com.sap.piper.ConfigurationMerger import com.sap.piper.cm.ChangeManagement import com.sap.piper.cm.ChangeManagementException @@ -10,20 +11,24 @@ import hudson.AbortException @Field def STEP_NAME = 'transportRequestUploadFile' -@Field Set parameterKeys = [ - 'changeDocumentId', - 'transportRequestId', - 'applicationId', - 'filePath', - 'credentialsId', - 'endpoint' - ] - @Field Set generalConfigurationKeys = [ 'credentialsId', - 'endpoint' + 'cmClientOpts', + 'endpoint', + 'gitFrom', + 'gitTo', + 'gitChangeDocumentLabel', + 'gitFormat' ] +@Field Set parameterKeys = generalConfigurationKeys.plus([ + 'applicationId', + 'changeDocumentId', + 'filePath', + 'transportRequestId']) + +@Field Set stepConfigurationKeys = generalConfigurationKeys + def call(parameters = [:]) { handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) { @@ -32,42 +37,72 @@ def call(parameters = [:]) { ChangeManagement cm = parameters.cmUtils ?: new ChangeManagement(script) - Map configuration = ConfigurationMerger.merge(parameters.script, STEP_NAME, - parameters, parameterKeys, - generalConfigurationKeys) + ConfigurationHelper configHelper = + ConfigurationHelper.loadStepDefaults(this) + .mixinGeneralConfig(script.commonPipelineEnvironment, generalConfigurationKeys) + .mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, stepConfigurationKeys) + .mixinStepConfig(script.commonPipelineEnvironment, stepConfigurationKeys) + .mixin(parameters, parameterKeys) + .withMandatoryProperty('endpoint') + .withMandatoryProperty('transportRequestId') + .withMandatoryProperty('applicationId') + .withMandatoryProperty('filePath') + + Map configuration = configHelper.use() def changeDocumentId = configuration.changeDocumentId - if(!changeDocumentId) throw new AbortException("Change document id not provided (parameter: 'changeDocumentId').") - def transportRequestId = configuration.transportRequestId - if(!transportRequestId) throw new AbortException("Transport Request id not provided (parameter: 'transportRequestId').") + if(changeDocumentId?.trim()) { - def applicationId = configuration.applicationId - if(!applicationId) throw new AbortException("Application id not provided (parameter: 'applicationId').") + echo "[INFO] ChangeDocumentId '${changeDocumentId}' retrieved from parameters." - def filePath = configuration.filePath - if(!filePath) throw new AbortException("File path not provided (parameter: 'filePath').") + } else { - def credentialsId = configuration.credentialsId - if(!credentialsId) throw new AbortException("Credentials id not provided (parameter: 'credentialsId').") + echo "[INFO] Retrieving ChangeDocumentId from commit history [from: ${configuration.gitFrom}, to: ${configuration.gitTo}]." + + "Searching for pattern '${configuration.gitChangeDocumentLabel}'. Searching with format '${configuration.gitFormat}'." - def endpoint = configuration.endpoint - if(!endpoint) throw new AbortException("Solution Manager endpoint not provided (parameter: 'endpoint').") + try { + changeDocumentId = cm.getChangeDocumentId( + configuration.gitFrom, + configuration.gitTo, + configuration.gitChangeDocumentLabel, + configuration.gitFormat + ) - echo "[INFO] Uploading file '$filePath' to transport request '$transportRequestId' of change document '$changeDocumentId'." + echo "[INFO] ChangeDocumentId '${changeDocumentId}' retrieved from commit history" + + } catch(ChangeManagementException ex) { + echo "[WARN] Cannot retrieve changeDocumentId from commit history: ${ex.getMessage()}." + } + } + + configuration = configHelper + .mixin([changeDocumentId: changeDocumentId?.trim() ?: null], ['changeDocumentId'] as Set) + .withMandatoryProperty('changeDocumentId', + "Change document id not provided (parameter: \'changeDocumentId\' or via commit history).") + .use() + + echo "[INFO] Uploading file '${configuration.filePath}' to transport request '${configuration.transportRequestId}' of change document '${configuration.changeDocumentId}'." withCredentials([usernamePassword( - credentialsId: credentialsId, + credentialsId: configuration.credentialsId, passwordVariable: 'password', usernameVariable: 'username')]) { try { - cm.uploadFileToTransportRequest(changeDocumentId, transportRequestId, applicationId, filePath, endpoint, username, password) + cm.uploadFileToTransportRequest(configuration.changeDocumentId, + configuration.transportRequestId, + configuration.applicationId, + configuration.filePath, + configuration.endpoint, + username, + password, + configuration.cmClientOpts) } catch(ChangeManagementException ex) { throw new AbortException(ex.getMessage()) } } - echo "[INFO] File '$filePath' has been successfully uploaded to transport request '$transportRequestId' of change document '$changeDocumentId'." + echo "[INFO] File '${configuration.filePath}' has been successfully uploaded to transport request '${configuration.transportRequestId}' of change document '${configuration.changeDocumentId}'." } }