1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-14 11:03:09 +02:00

Merge remote-tracking branch 'github/master' into HEAD

This commit is contained in:
Marcus Holl 2018-08-14 10:56:34 +02:00
commit bfb131407d
55 changed files with 1935 additions and 440 deletions

View File

@ -1,7 +1,7 @@
language: groovy
sudo: false
install:
- pip install --user mkdocs mkdocs-material
- pip install --user mkdocs==0.17.5 mkdocs-material==2.9.4
script:
- mvn test -B
- |

View File

@ -0,0 +1,83 @@
# Configuration
Configuration is done via a yml-file, located at `.pipeline/config.yml` in the **master branch** of your source code repository.
Your configuration inherits from the default configuration located at [https://github.com/SAP/jenkins-library/blob/master/resources/default_pipeline_environment.yml](https://github.com/SAP/jenkins-library/blob/master/resources/default_pipeline_environment.yml).
!!! caution "Adding custom parameters"
Please note that adding custom parameters to the configuration is at your own risk.
We may introduce new parameters at any time which may clash with your custom parameters.
Configuration of the Piper steps as well the Piper templates can be done in a hierarchical manner.
1. Directly passed step parameters will always take precedence over other configuration values and defaults
2. Stage configuration parameters define a Jenkins pipeline stage dependent set of parameters (e.g. deployment options for the `Acceptance` stage)
3. Step configuration defines how steps behave in general (e.g. step `cloudFoundryDeploy`)
4. General configuration parameters define parameters which are available across step boundaries
5. Default configuration comes with the Piper library and is always available
![Piper Configuration](images/piper_config.png)
## Collecting telemetry data
In order to improve this Jenkins library we are collecting telemetry data.
Data is send using [`com.sap.piper.pushToSWA`](https://github.com/SAP/jenkins-library/blob/master/src/com/sap/piper/Utils.groovy)
Following data (non-personal) is collected for example:
* Hashed job url, e.g. `4944f745e03f5f79daf0001eec9276ce351d3035` hash calculation is done in your Jenkins server and no original values are transmitted
* Name of library step which has been executed, like e.g. `artifactSetVersion`
* Certain parameters of the executed steps, e.g. `buildTool=maven`
**We store the telemetry data for not longer than 6 months on premises of SAP SE.**
!!! note "Disable collection of telemetry data"
If you do not want to send telemetry data you can easily deactivate this.
This is done with either of the following two ways:
1. General deactivation in your `.pipeline/config.yml` file by setting the configuration parameter `general -> collectTelemetryData: false` (default setting can be found in the [library defaults](https://github.com/SAP/jenkins-library/blob/master/resources/default_pipeline_environment.yml)).
**Please note: this will only take effect in all steps if you run `setupCommonPipelineEnvironment` at the beginning of your pipeline**
2. Individual deactivation per step by passing the parameter `collectTelemetryData: false`, like e.g. `setVersion script:this, collectTelemetryData: false`
## Example configuration
```
general:
gitSshKeyCredentialsId: GitHub_Test_SSH
steps:
cloudFoundryDeploy:
deployTool: 'cf_native'
cloudFoundry:
org: 'testOrg'
space: 'testSpace'
credentialsId: 'MY_CF_CREDENTIALSID_IN_JENKINS'
newmanExecute:
newmanCollection: 'myNewmanCollection.file'
newmanEnvironment: 'myNewmanEnvironment'
newmanGlobals: 'myNewmanGlobals'
```
## Access to configuration from custom scripts
Configuration is loaded into `commonPipelineEnvironment` during step [setupCommonPipelineEnvironment](steps/setupCommonPipelineEnvironment.md).
You can access the configuration values via `commonPipelineEnvironment.configuration` which will return you the complete configuration map.
Thus following access is for example possible (accessing `gitSshKeyCredentialsId` from `general` section):
```
commonPipelineEnvironment.configuration.general.gitSshKeyCredentialsId
```
## Access to configuration in custom library steps
Within library steps the `ConfigurationHelper` object is used.
You can see its usage in all the Piper steps, for example [newmanExecute](https://github.com/SAP/jenkins-library/blob/master/vars/newmanExecute.groovy#L23).

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View File

@ -23,19 +23,19 @@ none
| ----------|-----------|---------|-----------------|
| script | no | empty `commonPipelineEnvironment` | |
| artifactType | no | | 'appContainer' |
| buildTool | no | maven | maven, docker |
| buildTool | no | maven | docker, dlang, golang, maven, mta, npm, pip, sbt |
| commitVersion | no | `true` | `true`, `false` |
| dockerVersionSource | no | `''` | FROM, (ENV name),appVersion |
| filePath | no | buildTool=`maven`: pom.xml <br />docker: Dockerfile | |
| filePath | no | buildTool=`docker`: Dockerfile <br />buildTool=`dlang`: dub.json <br />buildTool=`golang`: VERSION <br />buildTool=`maven`: pom.xml <br />buildTool=`mta`: mta.yaml <br />buildTool=`npm`: package.json <br />buildTool=`pip`: version.txt <br />buildTool=`sbt`: sbtDescriptor.json| |
| gitCommitId | no | `GitUtils.getGitCommitId()` | |
| gitCredentialsId | If `commitVersion` is `true` | as defined in custom configuration | |
| gitSshCredentialsId | If `commitVersion` is `true` | as defined in custom configuration | |
| gitUserEMail | no | | |
| gitUserName | no | | |
| gitSshUrl | If `commitVersion` is `true` | | |
| tagPrefix | no | 'build_' | |
| timestamp | no | current time in format according to `timestampTemplate` | |
| timestampTemplate | no | `%Y%m%d%H%M%S` | |
| versioningTemplate | no | depending on `buildTool`<br />maven: `${version}-${timestamp}${commitId?"_"+commitId:""}` | |
| versioningTemplate | no |buildTool=`docker`: `${version}-${timestamp}${commitId?"_"+commitId:""}`<br> />buildTool=`dlang`: `${version}-${timestamp}${commitId?"+"+commitId:""}`<br />buildTool=`golang`:`${version}-${timestamp}${commitId?"+"+commitId:""}`<br />buildTool=`maven`: `${version}-${timestamp}${commitId?"_"+commitId:""}`<br />buildTool=`mta`: `${version}-${timestamp}${commitId?"+"+commitId:""}`<br />buildTool=`npm`: `${version}-${timestamp}${commitId?"+"+commitId:""}`<br />buildTool=`pip`: `${version}.${timestamp}${commitId?"."+commitId:""}`<br />buildTool=`sbt`: `${version}-${timestamp}${commitId?"+"+commitId:""}`| |
* `script` defines the global script environment of the Jenkinsfile run. Typically `this` is passed to this parameter. This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md) for retrieving e.g. configuration parameters.
* `artifactType` defines the type of the artifact.
@ -49,7 +49,7 @@ none
* Using `filePath` you could define a custom path to the descriptor file.
* `gitCommitId` defines the version prefix of the automatically generated version. By default it will take the long commitId hash. You could pass any other string (e.g. the short commitId hash) to be used. In case you don't want to have the gitCommitId added to the automatic versioning string you could set the value to an empty string: `''`.
* `gitCredentialsId`defines the ssh git credentials to be used for writing the tag.
* `gitSshCredentialsId`defines the ssh git credentials to be used for writing the tag.
* The parameters `gitUserName` and `gitUserEMail` allow to overwrite the global git settings available on your Jenkins server
* `gitSshUrl` defines the git ssh url to the source code repository.
* `tagPrefix` defines the prefix wich is used for the git tag which is written during the versioning run.

View File

@ -1,11 +1,11 @@
# checkChangeInDevelopment
## Description
Checks if a Change Document is in status 'in development'. The change document id is retrieved from the git commit history. The change document id
Checks if a Change Document in SAP Solution Manager is in status 'in development'. The change document id is retrieved from the git commit history. The change document id
can also be provided via parameter `changeDocumentId`. Any value provided as parameter has a higher precedence than a value from the commit history.
By default the git commit messages between `origin/master` and `HEAD` are scanned for a line like `ChangeDocument : <changeDocumentId>`. The commit
range and the pattern can be configured. For details see 'parameters' table.
range and the pattern can be configured. For details see 'parameters' table.
## Prerequisites
* **[Change Management Client 2.0.0 or compatible version](http://central.maven.org/maven2/com/sap/devops/cmclient/dist.cli/)** - available for download on Maven Central.
@ -15,27 +15,72 @@ range and the pattern can be configured. For details see 'parameters' table.
| -------------------|-----------|--------------------------------------------------------|--------------------|
| `script` | yes | | |
| `changeDocumentId` | 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` |
| `changeManagement/changeDocumentLabel` | no | `ChangeDocument\s?:` | regex pattern |
| `changeManagement/credentialsId` | yes | | |
| `changeManagement/endpoint` | yes | | |
| `changeManagement/git/from` | no | `origin/master` | |
| `changeManagement/git/to` | no | `HEAD` | |
| `changeManagement/git/format` | no | `%b` | see `git log --help` |
| `failIfStatusIsNotInDevelopment` | no | `true` | `true`, `false` |
* `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. If not provided, it is retrieved from the git commit history.
* `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.
* `changeManagement/changeDocumentLabel` - A pattern used for identifying lines holding the change document id.
* `changeManagement/credentialsId` - The id of the credentials to connect to the Solution Manager. The credentials needs to be maintained on Jenkins.
* `changeManagement/endpoint` - The address of the Solution Manager.
* `changeManagement/git/from` - The starting point for retrieving the change document id
* `changeManagement/git/to` - The end point for retrieving the change document id
* `changeManagement/git/format` - Specifies what part of the commit is scanned. By default the body of the commit message is scanned.
* `failIfStatusIsNotInDevelopment` - when set to `false` the step will not fail in case the step is not in status 'in development'.
## Step configuration
The following parameters can also be specified as step parameters using the global configuration file:
The step is configured using a customer configuration file provided as
resource in an custom shared library.
* `credentialsId`
* `endpoint`
```
@Library('piper-library-os@master') _
// the shared lib containing the additional configuration
// needs to be configured in Jenkins
@Library(foo@master') __
// inside the shared lib denoted by 'foo' the additional configuration file
// needs to be located under 'resources' ('resoures/myConfig.yml')
prepareDefaultValues script: this,
customDefaults: 'myConfig.yml'
```
Example content of ```'resources/myConfig.yml'``` in branch ```'master'``` of the repository denoted by
```'foo'```:
```
general:
changeManagement:
changeDocumentLabel: 'ChangeDocument\s?:'
cmClientOpts: '-Djavax.net.ssl.trustStore=<path to truststore>'
credentialsId: 'CM'
endpoint: 'https://example.org/cm'
git:
from: 'HEAD~1'
to: 'HEAD'
format: '%b'
```
The properties configured in section `'general/changeManagement'` are shared between all change managment related steps.
The properties can also be configured on a per-step basis:
```
[...]
steps:
checkChangeInDevelopment:
changeManagement:
endpoint: 'https://example.org/cm'
[...]
failIfStatusIsNotInDevelopment: true
```
The parameters can also be provided when the step is invoked. For examples see below.
## Return value
`true` in case the change document is in status 'in development'. Otherwise an hudson.AbortException is thrown. In case `failIfStatusIsNotInDevelopment`
@ -45,9 +90,26 @@ is set to `false`, `false` is returned in case the change document is not in sta
* `AbortException`:
* If the change id is not provided via parameter and if the change document id cannot be retrieved from the commit history.
* If the change is not in status `in development`. In this case no exception will be thrown when `failIfStatusIsNotInDevelopment` is set to `false`.
## Example
* `IllegalArgumentException`:
* If a mandatory property is not provided.
## Examples
```groovy
// simple case. All mandatory parameters provided via
// configuration, changeDocumentId provided via commit
// history
checkChangeInDevelopment script:this
```
```groovy
// explict endpoint provided, we search for changeDocumentId
// starting at the previous commit (HEAD~1) rather than on
// 'origin/master' (the default).
checkChangeInDevelopment script:this
changeManagement: [
endpoint: 'https:example.org/cm'
git: [
from: 'HEAD~1'
]
]
```

View File

@ -11,41 +11,88 @@ Creates a Transport Request for a Change Document on the Solution Manager.
| -----------------|-----------|--------------------------------------------------------|--------------------|
| `script` | yes | | |
| `changeDocumentId` | yes | | |
| `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` |
| `changeManagement/credentialsId` | yes | | |
| `changeManagement/endpoint` | yes | | |
| `changeManagement/clientOpts` | no | | |
| `changeManagement/git/from` | no | `origin/master` | |
| `changeManagement/git/to` | no | `HEAD` | |
| `changeManagement/changeDocumentLabel` | no | `ChangeDocument\s?:` | regex pattern |
| `changeManagement/git/format` | 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.
* `changeManagement/credentialsId` - The credentials to connect to the Solution Manager.
* `changeManagement/endpoint` - The address of the Solution Manager.
* `changeManagement/clientOpts`- Options forwarded to JVM used by the CM client, like `JAVA_OPTS`
* `changeManagement/git/from` - The starting point for retrieving the change document id
* `changeManagement/git/to` - The end point for retrieving the change document id
* `changeManagement/changeDocumentLabel` - A pattern used for identifying lines holding the change document id.
* `changeManagement/git/format` - 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:
The step is configured using a customer configuration file provided as
resource in an custom shared library.
* `credentialsId`
* `endpoint`
* `clientOpts`
```
@Library('piper-library-os@master') _
// the shared lib containing the additional configuration
// needs to be configured in Jenkins
@Library(foo@master') __
// inside the shared lib denoted by 'foo' the additional configuration file
// needs to be located under 'resources' ('resoures/myConfig.yml')
prepareDefaultValues script: this,
customDefaults: 'myConfig.yml'
```
Example content of ```'resources/myConfig.yml'``` in branch ```'master'``` of the repository denoted by
```'foo'```:
```
general:
changeManagement:
changeDocumentLabel: 'ChangeDocument\s?:'
cmClientOpts: '-Djavax.net.ssl.trustStore=<path to truststore>'
credentialsId: 'CM'
endpoint: 'https://example.org/cm'
git:
from: 'HEAD~1'
to: 'HEAD'
format: '%b'
```
The properties configured in section `'general/changeManagement'` are shared between
all change managment related steps.
The properties can also be configured on a per-step basis:
```
[...]
steps:
transportRequestCreate:
changeManagement:
endpoint: 'https://example.org/cm'
[...]
```
The parameters can also be provided when the step is invoked. For examples see below.
## Return value
The id of the Transport Request that has been created.
## Exceptions
* `AbortException`:
* If the change id is not provided.
* If the creation of the transport request fails.
* `IllegalStateException`:
* If the change id is not provided.
## Example
```groovy
def transportRequestId = transportRequestCreate script:this, changeDocumentId: '001'
def transportRequestId = transportRequestCreate script:this,
changeDocumentId: '001,'
changeManagement: [
endpoint: 'https://example.org/cm'
]
```

View File

@ -12,42 +12,90 @@ Releases a Transport Request for a Change Document on the Solution Manager.
| `script` | yes | | |
| `changeDocumentId` | yes | | |
| `transportRequestId`| yes | | |
| `credentialsId` | yes | | |
| `endpoint` | yes | | |
| `gitTransportRequestLabel` | no | `TransportRequest\s?:` | regex pattern |
| `gitFrom` | no | `origin/master` | |
| `gitTo` | no | `HEAD` | |
| `gitChangeDocumentLabel` | no | `ChangeDocument\s?:` | regex pattern |
| `gitFormat` | no | `%b` | see `git log --help` |
| `changeManagement/changeDocumentLabel` | no | `ChangeDocument\s?:` | regex pattern |
| `changeManagment/transportRequestLabel` | no | `TransportRequest\s?:` | regex pattern |
| `changeManagement/credentialsId` | yes | | |
| `changeManagement/endpoint` | yes | | |
| `changeManagement/git/from` | no | `origin/master` | |
| `changeManagement/git/to` | no | `HEAD` | |
| `changeManagement/git/format` | 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.
* `transportRequestId` - The id of the transport request to release.
* `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.
* `gitTransportReqeustLabel` - A pattern used for identifying lines holding the transport request id.
* `gitFormat` - Specifies what part of the commit is scanned. By default the body of the commit message is scanned.
* `changeManagement/changeDocumentLabel` - A pattern used for identifying lines holding the change document id.
* `changeManagment/transportRequestLabel` - A pattern used for identifying lines holding the transport request id.
* `changeManagement/credentialsId` - The id of the credentials to connect to the Solution Manager. The credentials needs to be maintained on Jenkins.
* `changeManagement/endpoint` - The address of the Solution Manager.
* `changeManagement/git/from` - The starting point for retrieving the change document id
* `changeManagement/git/to` - The end point for retrieving the change document id
* `changeManagement/git/format` - 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:
The step is configured using a customer configuration file provided as
resource in an custom shared library.
* `credentialsId`
* `endpoint`
```
@Library('piper-library-os@master') _
// the shared lib containing the additional configuration
// needs to be configured in Jenkins
@Library(foo@master') __
// inside the shared lib denoted by 'foo' the additional configuration file
// needs to be located under 'resources' ('resoures/myConfig.yml')
prepareDefaultValues script: this,
customDefaults: 'myConfig.yml'
```
Example content of ```'resources/myConfig.yml'``` in branch ```'master'``` of the repository denoted by
```'foo'```:
```
general:
changeManagement:
changeDocumentLabel: 'ChangeDocument\s?:'
cmClientOpts: '-Djavax.net.ssl.trustStore=<path to truststore>'
credentialsId: 'CM'
endpoint: 'https://example.org/cm'
git:
from: 'HEAD~1'
to: 'HEAD'
format: '%b'
```
The properties configured in section `'general/changeManagement'` are shared between all change managment related steps.
The properties can also be configured on a per-step basis:
```
[...]
steps:
transportRequestRelease:
changeManagement:
endpoint: 'https://example.org/cm'
[...]
```
The parameters can also be provided when the step is invoked. For examples see below.
## Return value
None.
## Exceptions
* `AbortException`:
* `IllegalArgumentException`:
* If the change id is not provided.
* If the transport request id is not provided.
* `AbortException`:
* If the release of the transport request fails.
## Example
```groovy
transportRequestRelease script:this, changeDocumentId: '001', transportRequestId: '001'
transportRequestRelease script:this,
changeDocumentId: '001',
transportRequestId: '001',
changeManagement: [
endpoint: 'https://example.org/cm'
]
```

View File

@ -14,46 +14,97 @@ Uploads a file to a Transport Request for a Change Document on the Solution Mana
| `transportRequestId`| yes | | |
| `applicationId` | yes | | |
| `filePath` | yes | | |
| `credentialsId` | yes | | |
| `endpoint` | yes | | |
| `gitFrom` | no | `origin/master` | |
| `gitTo` | no | `HEAD` | |
| `gitChangeDocumentLabel` | no | `ChangeDocument\s?:` | regex pattern |
| `gitTransportRequestLabel` | no | `TransportRequest\s?:` | regex pattern |
| `gitFormat` | no | `%b` | see `git log --help` |
| `changeManagement/credentialsId` | yes | | |
| `changeManagement/endpoint` | yes | | |
| `changeManagement/git/from` | no | `origin/master` | |
| `changeManagement/git/to` | no | `HEAD` | |
| `changeManagement/changeDocumentLabel` | no | `ChangeDocument\s?:` | regex pattern |
| `changeManagement/transportRequestLabel` | no | `TransportRequest\s?:` | regex pattern |
| `changeManagement/git/format` | 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.
* `transportRequestId` - The id of the transport request to release.
* `applicationId` - The id of the application.
* `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.
* `gitTransportRequestLabel` - A pattern used for identifying lines holding the transport request id.
* `gitFormat` - Specifies what part of the commit is scanned. By default the body of the commit message is scanned.
* `changeManagement/credentialsId` - The credentials to connect to the Solution Manager.
* `changeManagement/endpoint` - The address of the Solution Manager.
* `changeManagement/git/from` - The starting point for retrieving the change document id
* `changeManagement/git/to` - The end point for retrieving the change document id
* `changeManagement/changeDocumentLabel` - A pattern used for identifying lines holding the change document id.
* `changeManagement/transportRequestLabel` - A pattern used for identifying lines holding the transport request id.
* `changeManagement/git/format` - 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:
The step is configured using a customer configuration file provided as
resource in an custom shared library.
* `credentialsId`
* `endpoint`
```
@Library('piper-library-os@master') _
// the shared lib containing the additional configuration
// needs to be configured in Jenkins
@Library(foo@master') __
// inside the shared lib denoted by 'foo' the additional configuration file
// needs to be located under 'resources' ('resoures/myConfig.yml')
prepareDefaultValues script: this,
customDefaults: 'myConfig.yml'
```
Example content of ```'resources/myConfig.yml'``` in branch ```'master'``` of the repository denoted by
```'foo'```:
```
general:
changeManagement:
changeDocumentLabel: 'ChangeDocument\s?:'
cmClientOpts: '-Djavax.net.ssl.trustStore=<path to truststore>'
credentialsId: 'CM'
endpoint: 'https://example.org/cm'
git:
from: 'HEAD~1'
to: 'HEAD'
format: '%b'
```
The properties configured in section `'general/changeManagement'` are shared between all change managment related steps.
The properties can also be configured on a per-step basis:
```
[...]
steps:
transportRequestUploadFile:
applicationId: 'FOO'
changeManagement:
endpoint: 'https://example.org/cm'
[...]
```
The parameters can also be provided when the step is invoked. For examples see below.
## Return value
None.
## Exceptions
* `AbortException`:
* `IllegalArgumentException`:
* If the change id is not provided.
* If the transport request id is not provided.
* If the application id is not provided.
* If the file path is not provided.
* `AbortException`:
* If the upload fails.
## Example
```groovy
transportRequestUploadFile script:this, changeDocumentId: '001', transportRequestId: '001', applicationId: '001', filePath: '/path'
transportRequestUploadFile script:this,
changeDocumentId: '001',
transportRequestId: '001',
applicationId: '001',
filePath: '/path',
changeManagement:[
endpoint: 'https://example.org/cm'
]
```

View File

@ -1,9 +1,10 @@
site_name: Jenkins 2.0 Pipelines
pages:
- Home: index.md
- Configuration: configuration.md
- 'Library steps':
- artifactSetVersion: steps/artifactSetVersion.md
- checkChangeInDevelopment: steps/checkChangeInDevelopment.md
- checkChangeInDevelopment: steps/checkChangeInDevelopment.md
- commonPipelineEnvironment: steps/commonPipelineEnvironment.md
- dockerExecute: steps/dockerExecute.md
- durationMeasure: steps/durationMeasure.md

View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
# this is simply testing if the application root returns HTTP STATUS_CODE
curl -so /dev/null -w '%{response_code}' https://$1 | grep $STATUS_CODE

View File

@ -1,22 +1,47 @@
#Project Setup
general:
productiveBranch: 'master'
collectTelemetryData: true
changeManagement:
transportRequestLabel: 'TransportRequest\s?:'
changeDocumentLabel: 'ChangeDocument\s?:'
clientOpts: ''
credentialsId: 'CM'
git:
from: 'origin/master'
to: 'HEAD'
format: '%b'
gitSshKeyCredentialsId: '' #needed to allow sshagent to run with local ssh key
#Steps Specific Configuration
steps:
artifactSetVersion:
timestampTemplate: '%Y%m%d%H%M%S'
tagPrefix: 'build_'
commitVersion: true
dlang:
filePath: 'dub.json'
versioningTemplate: '${version}-${timestamp}${commitId?"+"+commitId:""}'
docker:
filePath: 'Dockerfile'
versioningTemplate: '${version}-${timestamp}${commitId?"_"+commitId:""}'
golang:
filePath: 'VERSION'
versioningTemplate: '${version}-${timestamp}${commitId?"+"+commitId:""}'
maven:
filePath: 'pom.xml'
versioningTemplate: '${version}-${timestamp}${commitId?"_"+commitId:""}'
mta:
filePath: 'mta.yaml'
versioningTemplate: '${version}-${timestamp}${commitId?"+"+commitId:""}'
npm:
filePath: 'package.json'
versioningTemplate: '${version}-${timestamp}${commitId?"+"+commitId:""}'
pip:
filePath: 'version.txt'
versioningTemplate: '${version}.${timestamp}${commitId?"."+commitId:""}'
sbt:
filePath: 'sbtDescriptor.json'
versioningTemplate: '${version}-${timestamp}${commitId?"+"+commitId:""}'
checksPublishResults:
aggregation:
active: true
@ -76,6 +101,23 @@ steps:
fail:
high: '0'
archive: false
cloudFoundryDeploy:
cloudFoundry:
apiEndpoint: 'https://api.cf.eu10.hana.ondemand.com'
deployTool: 'cf_native'
deployType: 'standard'
mtaDeployParameters: '-f'
mtaExtensionDescriptor: ''
mtaPath: ''
smokeTestScript: 'blueGreenCheckScript.sh'
smokeTestStatusCode: 200
stashContent: []
cf_native:
dockerImage: 's4sdk/docker-cf-cli'
dockerWorkspace: '/home/piper'
mtaDeployPlugin:
dockerImage: 's4sdk/docker-cf-cli'
dockerWorkspace: '/home/piper'
influxWriteData:
influxServer: 'jenkins'
mavenExecute:
@ -85,6 +127,7 @@ steps:
buildTarget: 'NEO'
mtaJarLocation: 'mta.jar'
neoDeploy:
dockerImage: 's4sdk/docker-neo-cli'
deployMode: 'mta'
warAction: 'deploy'
vmSize: 'lite'
@ -96,6 +139,8 @@ steps:
newmanEnvironment: ''
newmanGlobals: ''
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"
stashContent:
- 'tests'
pipelineStashFilesAfterBuild:
runOpaTests: false
stashIncludes:
@ -174,29 +219,8 @@ steps:
archive: false
active: false
checkChangeInDevelopment:
credentialsId: 'CM'
failIfStatusIsNotInDevelopment: true
gitFrom: 'origin/master'
gitTo: 'HEAD'
gitChangeDocumentLabel: 'ChangeDocument\s?:'
gitFormat: '%b'
transportRequestCreate:
credentialsId: 'CM'
gitFrom: 'origin/master'
gitTo: 'HEAD'
gitChangeDocumentLabel: 'ChangeDocument\s?:'
gitFormat: '%b'
developmentSystemId: null
transportRequestUploadFile:
credentialsId: 'CM'
gitFrom: 'origin/master'
gitTo: 'HEAD'
gitChangeDocumentLabel: 'ChangeDocument\s?:'
gitTransportRequestLabel: 'TransportRequest\s?:'
gitFormat: '%b'
transportRequestRelease:
credentialsId: 'CM'
gitFrom: 'origin/master'
gitTo: 'HEAD'
gitChangeDocumentLabel: 'ChangeDocument\s?:'
gitTransportRequestLabel: 'TransportRequest\s?:'
gitFormat: '%b'

View File

@ -26,27 +26,56 @@ class ConfigurationHelper implements Serializable {
return this
}
ConfigurationHelper mixinGeneralConfig(commonPipelineEnvironment, Set filter = null){
ConfigurationHelper mixinGeneralConfig(commonPipelineEnvironment, Set filter = null, Script step = null, Map compatibleParameters = [:]){
Map stepConfiguration = ConfigurationLoader.generalConfiguration([commonPipelineEnvironment: commonPipelineEnvironment])
return mixin(stepConfiguration, filter)
return mixin(stepConfiguration, filter, step, compatibleParameters)
}
ConfigurationHelper mixinStageConfig(commonPipelineEnvironment, stageName, Set filter = null){
ConfigurationHelper mixinStageConfig(commonPipelineEnvironment, stageName, Set filter = null, Script step = null, Map compatibleParameters = [:]){
Map stageConfiguration = ConfigurationLoader.stageConfiguration([commonPipelineEnvironment: commonPipelineEnvironment], stageName)
return mixin(stageConfiguration, filter)
return mixin(stageConfiguration, filter, step, compatibleParameters)
}
ConfigurationHelper mixinStepConfig(commonPipelineEnvironment, Set filter = null){
ConfigurationHelper mixinStepConfig(commonPipelineEnvironment, Set filter = null, Script step = null, Map compatibleParameters = [:]){
if(!name) throw new IllegalArgumentException('Step has no public name property!')
Map stepConfiguration = ConfigurationLoader.stepConfiguration([commonPipelineEnvironment: commonPipelineEnvironment], name)
return mixin(stepConfiguration, filter)
return mixin(stepConfiguration, filter, step, compatibleParameters)
}
ConfigurationHelper mixin(Map parameters, Set filter = null){
ConfigurationHelper mixin(Map parameters, Set filter = null, Script step = null, Map compatibleParameters = [:]){
if (parameters.size() > 0 && compatibleParameters.size() > 0) {
parameters = ConfigurationMerger.merge(handleCompatibility(step, compatibleParameters, parameters), null, parameters)
}
if (filter) {
filter.add('collectTelemetryData')
}
config = ConfigurationMerger.merge(parameters, filter, config)
return this
}
private Map handleCompatibility(Script step, Map compatibleParameters, String paramStructure = '', Map configMap ) {
Map newConfig = [:]
compatibleParameters.each {entry ->
if (entry.getValue() instanceof Map) {
paramStructure = (paramStructure ? paramStructure + '.' : '') + entry.getKey()
newConfig[entry.getKey()] = handleCompatibility(step, entry.getValue(), paramStructure, configMap)
} else {
def configSubMap = configMap
for(String key in paramStructure.tokenize('.')){
configSubMap = configSubMap?.get(key)
}
if (configSubMap == null || (configSubMap != null && configSubMap[entry.getKey()] == null)) {
newConfig[entry.getKey()] = configMap[entry.getValue()]
def paramName = (paramStructure ? paramStructure + '.' : '') + entry.getKey()
if (step && configMap[entry.getValue()] != null) {
step.echo ("[INFO] The parameter '${entry.getValue()}' is COMPATIBLE to the parameter '${paramName}'")
}
}
}
}
return newConfig
}
Map dependingOn(dependentKey){
return [
mixin: {key ->
@ -74,10 +103,7 @@ class ConfigurationHelper implements Serializable {
}
def getConfigProperty(key) {
if (config[key] != null && config[key].class == String) {
return config[key].trim()
}
return config[key]
return getConfigPropertyNested(config, key)
}
def getConfigProperty(key, defaultValue) {
@ -88,6 +114,27 @@ class ConfigurationHelper implements Serializable {
return value
}
private getConfigPropertyNested(Map config, key) {
def separator = '/'
// reason for cast to CharSequence: String#tokenize(./.) causes a deprecation warning.
List parts = (key in String) ? (key as CharSequence).tokenize(separator) : ([key] as List)
if(config[parts.head()] != null) {
if(config[parts.head()] in Map && ! parts.tail().isEmpty()) {
return getConfigPropertyNested(config[parts.head()], (parts.tail() as Iterable).join(separator))
}
if (config[parts.head()].class == String) {
return (config[parts.head()] as String).trim()
}
}
return config[parts.head()]
}
def isPropertyDefined(key){
def value = getConfigProperty(key)
@ -118,8 +165,13 @@ class ConfigurationHelper implements Serializable {
return paramValue
}
def withMandatoryProperty(key, errorMessage = null){
getMandatoryProperty(key, null, errorMessage)
def withMandatoryProperty(key, errorMessage = null, condition = null){
if(condition){
if(condition(this.config))
getMandatoryProperty(key, null, errorMessage)
}else{
getMandatoryProperty(key, null, errorMessage)
}
return this
}
}

View File

@ -1,6 +1,7 @@
package com.sap.piper
import com.cloudbees.groovy.cps.NonCPS
import org.jenkinsci.plugins.workflow.steps.MissingContextVariableException
@NonCPS
def getMandatoryParameter(Map map, paramName, defaultValue = null) {
@ -51,3 +52,64 @@ def unstashAll(stashContent) {
return unstashedContent
}
def generateSha1Inline(input) {
return "`echo -n '${input}' | sha1sum | sed 's/ -//'`"
}
void pushToSWA(Map parameters, Map config) {
try {
//allow opt-out via configuration
if (!config.collectTelemetryData) {
return
}
def swaCustom = [:]
/* SWA custom parameters:
custom3 = step name (passed as parameter step)
custom4 = job url hashed (calculated)
custom5 = build url hashed (calculated)
custom11 = step related parameter 1 (passed as parameter stepParam1)
custom12 = step related parameter 2 (passed as parameter stepParam2)
custom13 = step related parameter 3 (passed as parameter stepParam3)
custom14 = step related parameter 4 (passed as parameter stepParam4)
custom15 = step related parameter 5 (passed as parameter stepParam5)
*/
def swaUrl = 'https://webanalytics.cfapps.eu10.hana.ondemand.com/tracker/log'
def action_name = 'Piper Library OS'
def idsite = '827e8025-1e21-ae84-c3a3-3f62b70b0130'
def url = 'https://github.com/SAP/jenkins-library'
def event_type = 'library-os'
swaCustom.custom3 = parameters.get('step')
swaCustom.custom4 = generateSha1Inline(env.JOB_URL)
swaCustom.custom5 = generateSha1Inline(env.BUILD_URL)
swaCustom.custom11 = parameters.get('stepParam1')
swaCustom.custom12 = parameters.get('stepParam2')
swaCustom.custom13 = parameters.get('stepParam3')
swaCustom.custom14 = parameters.get('stepParam4')
swaCustom.custom15 = parameters.get('stepParam5')
def options = []
options.push("-G")
options.push("-v \"${swaUrl}\"")
options.push("--data-urlencode \"action_name=${action_name}\"")
options.push("--data-urlencode \"idsite=${idsite}\"")
options.push("--data-urlencode \"url=${url}\"")
options.push("--data-urlencode \"event_type=${event_type}\"")
for(def key : ['custom3', 'custom4', 'custom5', 'custom11', 'custom12', 'custom13', 'custom14', 'custom15']){
if (swaCustom[key] != null) options.push("--data-urlencode \"${key}=${swaCustom[key]}\"")
}
options.push("--connect-timeout 5")
options.push("--max-time 20")
sh(returnStatus: true, script: "#!/bin/sh +x\ncurl ${options.join(' ')} > /dev/null 2>&1 || echo '[${parameters.get('step')}] Telemetry Report to SWA failed!'")
} catch (MissingContextVariableException noNode) {
echo "[${parameters.get('step')}] Telemetry Report to SWA skipped, no node available!"
} catch (ignore) {
// some error occured in SWA reporting. This should not break anything though.
}
}

View File

@ -64,60 +64,62 @@ public class ChangeManagement implements Serializable {
return items[0]
}
boolean isChangeInDevelopment(String changeId, String endpoint, String username, String password, String clientOpts = '') {
boolean isChangeInDevelopment(String changeId, String endpoint, String credentialsId, String clientOpts = '') {
int rc = executeWithCredentials(endpoint, credentialsId, 'is-change-in-development', ['-cID', "'${changeId}'", '--return-code'],
clientOpts) as int
int rc = script.sh(returnStatus: true,
script: getCMCommandLine(endpoint, username, password,
'is-change-in-development', ['-cID', "'${changeId}'",
'--return-code'],
clientOpts))
if(rc == 0) {
return true
} else if(rc == 3) {
return false
} else {
throw new ChangeManagementException("Cannot retrieve status for change document '${changeId}'. Does this change exist? Return code from cmclient: ${rc}.")
}
}
String createTransportRequest(String changeId, String developmentSystemId, String endpoint, String username, String password, String clientOpts = '') {
try {
String transportRequest = script.sh(returnStdout: true,
script: getCMCommandLine(endpoint, username, password, 'create-transport', ['-cID', changeId,
'-dID', developmentSystemId],
clientOpts))
return transportRequest.trim()
} catch(AbortException e) {
throw new ChangeManagementException("Cannot create a transport request for change id '$changeId'. $e.message.")
if (rc == 0) {
return true
} else if (rc == 3) {
return false
} else {
throw new ChangeManagementException("Cannot retrieve status for change document '${changeId}'. Does this change exist? Return code from cmclient: ${rc}.")
}
}
void uploadFileToTransportRequest(String changeId, String transportRequestId, String applicationId, String filePath, String endpoint, String username, String password, String cmclientOpts = '') {
String createTransportRequest(String changeId, String developmentSystemId, String endpoint, String credentialsId, String clientOpts = '') {
try {
def transportRequest = executeWithCredentials(endpoint, credentialsId, 'create-transport', ['-cID', changeId, '-dID', developmentSystemId],
clientOpts)
return transportRequest.trim() as String
}catch(AbortException e) {
throw new ChangeManagementException("Cannot create a transport request for change id '$changeId'. $e.message.")
}
}
int rc = script.sh(returnStatus: true,
script: getCMCommandLine(endpoint, username, password,
'upload-file-to-transport', ['-cID', changeId,
'-tID', transportRequestId,
applicationId, filePath],
cmclientOpts))
void uploadFileToTransportRequest(String changeId, String transportRequestId, String applicationId, String filePath, String endpoint, String credentialsId, String cmclientOpts = '') {
int rc = executeWithCredentials(endpoint, credentialsId, 'upload-file-to-transport', ['-cID', changeId,
'-tID', transportRequestId,
applicationId, filePath],
cmclientOpts) as int
if(rc == 0) {
return
} else {
throw new ChangeManagementException("Cannot upload file '$filePath' for change document '$changeId' with transport request '$transportRequestId'. Return code from cmclient: $rc.")
}
}
void releaseTransportRequest(String changeId, String transportRequestId, String endpoint, String username, String password, String clientOpts = '') {
def executeWithCredentials(String endpoint, String credentialsId, String command, List<String> args, String clientOpts = '') {
script.withCredentials([script.usernamePassword(
credentialsId: credentialsId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
def returnValue = script.sh(returnStatus: true,
script: getCMCommandLine(endpoint, script.username, script.password,
command, args,
clientOpts))
return returnValue;
int rc = script.sh(returnStatus: true,
script: getCMCommandLine(endpoint, username, password,
'release-transport', ['-cID', changeId,
'-tID', transportRequestId],
clientOpts))
}
}
void releaseTransportRequest(String changeId, String transportRequestId, String endpoint, String credentialsId, String clientOpts = '') {
int rc = executeWithCredentials( endpoint, credentialsId, 'release-transport', ['-cID', changeId,
'-tID', transportRequestId], clientOpts) as int
if(rc == 0) {
return
} else {

View File

@ -12,12 +12,22 @@ 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 'dlang':
return new DlangArtifactVersioning(script, configuration)
case 'docker':
return new DockerArtifactVersioning(script, configuration)
case 'golang':
return new GolangArtifactVersioning(script, configuration)
case 'maven':
return new MavenArtifactVersioning(script, configuration)
case 'mta':
return new MtaArtifactVersioning(script, configuration)
case 'npm':
return new NpmArtifactVersioning(script, configuration)
case 'pip':
return new PipArtifactVersioning(script, configuration)
case 'sbt':
return new SbtArtifactVersioning(script, configuration)
default:
throw new IllegalArgumentException("No versioning implementation for buildTool: ${buildTool} available.")
}

View File

@ -0,0 +1,20 @@
package com.sap.piper.versioning
class DlangArtifactVersioning extends ArtifactVersioning {
protected DlangArtifactVersioning(script, configuration) {
super(script, configuration)
}
@Override
def getVersion() {
def descriptor = script.readJSON file: configuration.filePath
return descriptor.version
}
@Override
def setVersion(version) {
def descriptor = script.readJSON file: configuration.filePath
descriptor.version = new String(version)
script.writeJSON file: configuration.filePath, json: descriptor
}
}

View File

@ -5,13 +5,29 @@ class DockerArtifactVersioning extends ArtifactVersioning {
super(script, configuration)
}
@Override
def getVersion() {
if (configuration.dockerVersionSource == 'FROM')
return getVersionFromDockerBaseImageTag(configuration.filePath)
else
//standard assumption: version is assigned to an env variable
return getVersionFromDockerEnvVariable(configuration.filePath, configuration.dockerVersionSource)
if(configuration.artifactType == 'appContainer' && configuration.dockerVersionSource == 'appVersion'){
//replace + sign if available since + is not allowed in a Docker tag
if (script.commonPipelineEnvironment.getArtifactVersion()){
return script.commonPipelineEnvironment.getArtifactVersion().replace('+', '_')
}else{
throw new IllegalArgumentException("No artifact version available for 'dockerVersionSource: appVersion' -> executeBuild needs to run for the application artifact first to set the appVersion attribute.'")
}
} else if (configuration.dockerVersionSource == 'FROM') {
def version = getVersionFromDockerBaseImageTag(configuration.filePath)
if (version) {
return getVersionFromDockerBaseImageTag(configuration.filePath)
} else {
throw new IllegalArgumentException("No version information available in FROM statement")
}
} else {
def version = getVersionFromDockerEnvVariable(configuration.filePath, configuration.dockerVersionSource)
if (version) {
return version
} else {
throw new IllegalArgumentException("ENV variable '${configuration.dockerVersionSource}' not found.")
}
}
}
@Override

View File

@ -0,0 +1,17 @@
package com.sap.piper.versioning
class GolangArtifactVersioning extends ArtifactVersioning {
protected GolangArtifactVersioning(script, configuration) {
super(script, configuration)
}
@Override
def getVersion() {
return script.readFile(configuration.filePath).split('\n')[0].trim()
}
@Override
def setVersion(version) {
script.writeFile file: configuration.filePath, text: version
}
}

View File

@ -0,0 +1,20 @@
package com.sap.piper.versioning
class NpmArtifactVersioning extends ArtifactVersioning {
protected NpmArtifactVersioning(script, configuration) {
super(script, configuration)
}
@Override
def getVersion() {
def packageJson = script.readJSON file: configuration.filePath
return packageJson.version
}
@Override
def setVersion(version) {
def packageJson = script.readJSON file: configuration.filePath
packageJson.version = new String(version)
script.writeJSON file: configuration.filePath, json: packageJson
}
}

View File

@ -0,0 +1,17 @@
package com.sap.piper.versioning
class PipArtifactVersioning extends ArtifactVersioning {
protected PipArtifactVersioning(script, configuration) {
super(script, configuration)
}
@Override
def getVersion() {
return script.readFile(configuration.filePath).split('\n')[0].trim()
}
@Override
def setVersion(version) {
script.writeFile file: configuration.filePath, text: version
}
}

View File

@ -0,0 +1,20 @@
package com.sap.piper.versioning
class SbtArtifactVersioning extends ArtifactVersioning {
protected SbtArtifactVersioning(script, configuration) {
super(script, configuration)
}
@Override
def getVersion() {
def sbtDescriptorJson = script.readJSON file: configuration.filePath
return sbtDescriptorJson.version
}
@Override
def setVersion(version) {
def sbtDescriptorJson = script.readJSON file: configuration.filePath
sbtDescriptorJson.version = new String(version)
script.writeJSON file: configuration.filePath, json: sbtDescriptorJson
}
}

View File

@ -47,6 +47,9 @@ class ArtifactSetVersionTest extends BasePiperTest {
void init() throws Throwable {
dockerParameters = [:]
nullScript.commonPipelineEnvironment.setArtifactVersion(null)
nullScript.commonPipelineEnvironment.setGitSshUrl('git@test.url')
helper.registerAllowedMethod("sshagent", [List.class, Closure.class], { list, closure ->
sshAgentList = list
return closure()
@ -64,7 +67,7 @@ class ArtifactSetVersionTest extends BasePiperTest {
@Test
void testVersioning() {
jsr.step.call(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'maven', gitSshUrl: 'myGitSshUrl')
jsr.step.artifactSetVersion(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'maven', gitSshUrl: 'myGitSshUrl')
assertEquals('1.2.3-20180101010203_testCommitId', jer.env.getArtifactVersion())
assertEquals('testCommitId', jer.env.getGitCommitId())
@ -79,7 +82,7 @@ class ArtifactSetVersionTest extends BasePiperTest {
@Test
void testVersioningWithoutCommit() {
jsr.step.call(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'maven', commitVersion: false)
jsr.step.artifactSetVersion(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'maven', commitVersion: false)
assertEquals('1.2.3-20180101010203_testCommitId', jer.env.getArtifactVersion())
assertThat(jscr.shell, hasItem("mvn --file 'pom.xml' --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn versions:set -DnewVersion=1.2.3-20180101010203_testCommitId"))
@ -87,7 +90,7 @@ class ArtifactSetVersionTest extends BasePiperTest {
@Test
void testVersioningWithoutScript() {
jsr.step.call(juStabGitUtils: gitUtils, buildTool: 'maven', commitVersion: false)
jsr.step.artifactSetVersion(juStabGitUtils: gitUtils, buildTool: 'maven', commitVersion: false)
assertEquals('1.2.3-20180101010203_testCommitId', jer.env.getArtifactVersion())
assertThat(jscr.shell, hasItem("mvn --file 'pom.xml' --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn versions:set -DnewVersion=1.2.3-20180101010203_testCommitId"))
@ -95,14 +98,14 @@ class ArtifactSetVersionTest extends BasePiperTest {
@Test
void testVersioningCustomGitUserAndEMail() {
jsr.step.call(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'maven', gitSshUrl: 'myGitSshUrl', gitUserEMail: 'test@test.com', gitUserName: 'test')
jsr.step.artifactSetVersion(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'maven', gitSshUrl: 'myGitSshUrl', gitUserEMail: 'test@test.com', gitUserName: 'test')
assertThat(jscr.shell, hasItem("git -c user.email=\"test@test.com\" -c user.name=\"test\" commit -m 'update version 1.2.3-20180101010203_testCommitId'"))
}
@Test
void testVersioningWithTimestamp() {
jsr.step.call(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'maven', timestamp: '2018')
jsr.step.artifactSetVersion(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'maven', timestamp: '2018')
assertEquals('1.2.3-2018_testCommitId', jer.env.getArtifactVersion())
}
@ -110,23 +113,35 @@ class ArtifactSetVersionTest extends BasePiperTest {
void testVersioningNoBuildTool() {
thrown.expect(Exception)
thrown.expectMessage('ERROR - NO VALUE AVAILABLE FOR buildTool')
jsr.step.call(script: jsr.step, juStabGitUtils: gitUtils)
jsr.step.artifactSetVersion(script: jsr.step, juStabGitUtils: gitUtils)
}
@Test
void testVersioningWithCustomTemplate() {
jsr.step.call(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'maven', versioningTemplate: '${version}-xyz')
jsr.step.artifactSetVersion(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'maven', versioningTemplate: '${version}-xyz')
assertEquals('1.2.3-xyz', jer.env.getArtifactVersion())
}
@Test
void testVersioningWithTypeAppContainer() {
nullScript.commonPipelineEnvironment.setAppContainerProperty('gitSshUrl', 'git@test.url')
jer.env.setArtifactVersion('1.2.3-xyz')
jsr.step.call(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'docker', artifactType: 'appContainer', dockerVersionSource: 'appVersion')
jsr.step.artifactSetVersion(script: jsr.step, juStabGitUtils: gitUtils, buildTool: 'docker', artifactType: 'appContainer', dockerVersionSource: 'appVersion')
assertEquals('1.2.3-xyz', jer.env.getArtifactVersion())
assertEquals('1.2.3-xyz', jwfr.files['VERSION'])
}
@Test
void testCredentialCompatibility() {
jsr.step.artifactSetVersion (
script: nullScript,
buildTool: 'maven',
gitCredentialsId: 'testCredentials',
juStabGitUtils: gitUtils
)
assertThat(sshAgentList, hasItem('testCredentials'))
}
void prepareObjectInterceptors(object) {
object.metaClass.invokeMethod = helper.getMethodInterceptor()
object.metaClass.static.invokeMethod = helper.getMethodInterceptor()

View File

@ -1,5 +1,5 @@
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
@ -26,7 +26,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
.around(thrown)
.around(jsr)
.around(new JenkinsCredentialsRule(this)
.withCredentials('CM', 'anonymous', '********'))
.withCredentials('CM', 'anonymous', '********'))
@After
public void tearDown() {
@ -41,16 +41,14 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(true)
boolean inDevelopment = jsr.step.checkChangeInDevelopment(
cmUtils: cm,
endpoint: 'https://example.org/cm')
changeManagement: [endpoint: 'https://example.org/cm'])
assert inDevelopment
assert cmUtilReceivedParams == [
changeId: '001',
endpoint: 'https://example.org/cm',
userName: 'anonymous',
password: '********',
cmclientOpts: null
credentialsId: 'CM',
cmclientOpts: ''
]
}
@ -63,7 +61,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(false)
jsr.step.checkChangeInDevelopment(
cmUtils: cm,
endpoint: 'https://example.org/cm')
changeManagement: [endpoint: 'https://example.org/cm'])
}
@Test
@ -72,7 +70,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(false)
boolean inDevelopment = jsr.step.checkChangeInDevelopment(
cmUtils: cm,
endpoint: 'https://example.org/cm',
changeManagement: [endpoint: 'https://example.org/cm'],
failIfStatusIsNotInDevelopment: false)
assert !inDevelopment
}
@ -84,7 +82,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
jsr.step.checkChangeInDevelopment(
changeDocumentId: '42',
cmUtils: cm,
endpoint: 'https://example.org/cm')
changeManagement: [endpoint: 'https://example.org/cm'])
assert cmUtilReceivedParams.changeId == '42'
}
@ -95,7 +93,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
jsr.step.checkChangeInDevelopment(
cmUtils: cm,
endpoint: 'https://example.org/cm')
changeManagement : [endpoint: 'https://example.org/cm'])
assert cmUtilReceivedParams.changeId == '0815'
}
@ -103,8 +101,9 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
@Test
public void changeDocumentIdRetrievalFailsTest() {
thrown.expect(AbortException)
thrown.expectMessage('Something went wrong')
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 = new ChangeManagement(nullScript, null) {
@ -119,7 +118,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
jsr.step.checkChangeInDevelopment(
cmUtils: cm,
endpoint: 'https://example.org/cm')
changeManagement: [endpoint: 'https://example.org/cm'])
}
@Test
@ -133,7 +132,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(false, null)
jsr.step.checkChangeInDevelopment(
cmUtils: cm,
endpoint: 'https://example.org/cm')
changeManagement: [endpoint: 'https://example.org/cm'])
}
@Test
@ -147,7 +146,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(false, '')
jsr.step.checkChangeInDevelopment(
cmUtils: cm,
endpoint: 'https://example.org/cm')
changeManagement: [endpoint: 'https://example.org/cm'])
}
private ChangeManagement getChangeManagementUtils(boolean inDevelopment, String changeDocumentId = '001') {
@ -162,11 +161,10 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
return changeDocumentId
}
boolean isChangeInDevelopment(String changeId, String endpoint, String userName, String password, String cmclientOpts) {
boolean isChangeInDevelopment(String changeId, String endpoint, String credentialsId, String cmclientOpts) {
cmUtilReceivedParams.changeId = changeId
cmUtilReceivedParams.endpoint = endpoint
cmUtilReceivedParams.userName = userName
cmUtilReceivedParams.password = password
cmUtilReceivedParams.credentialsId = credentialsId
cmUtilReceivedParams.cmclientOpts = cmclientOpts
return inDevelopment

View File

@ -0,0 +1,271 @@
#!groovy
import groovy.json.JsonSlurperClassic
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.RuleChain
import org.yaml.snakeyaml.Yaml
import util.BasePiperTest
import util.JenkinsEnvironmentRule
import util.JenkinsDockerExecuteRule
import util.JenkinsLoggingRule
import util.JenkinsShellCallRule
import util.JenkinsStepRule
import util.JenkinsWriteFileRule
import util.Rules
import static org.junit.Assert.assertTrue
import static org.junit.Assert.assertEquals
class CloudFoundryDeployTest extends BasePiperTest {
private ExpectedException thrown = ExpectedException.none()
private JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
private JenkinsShellCallRule jscr = new JenkinsShellCallRule(this)
private JenkinsWriteFileRule jwfr = new JenkinsWriteFileRule(this)
private JenkinsDockerExecuteRule jedr = new JenkinsDockerExecuteRule(this)
private JenkinsStepRule jsr = new JenkinsStepRule(this)
private JenkinsEnvironmentRule jer = new JenkinsEnvironmentRule(this)
@Rule
public RuleChain rules = Rules
.getCommonRules(this)
.around(thrown)
.around(jlr)
.around(jscr)
.around(jwfr)
.around(jedr)
.around(jer)
.around(jsr) // needs to be activated after jedr, otherwise executeDocker is not mocked
@Before
void init() throws Throwable {
helper.registerAllowedMethod('usernamePassword', [Map], { m -> return m })
helper.registerAllowedMethod('withCredentials', [List, Closure], { l, c ->
if(l[0].credentialsId == 'test_cfCredentialsId') {
binding.setProperty('username', 'test_cf')
binding.setProperty('password', '********')
} else if(l[0].credentialsId == 'test_camCredentialsId') {
binding.setProperty('username', 'test_cam')
binding.setProperty('password', '********')
}
try {
c()
} finally {
binding.setProperty('username', null)
binding.setProperty('password', null)
}
})
}
@Test
void testNoTool() throws Exception {
nullScript.commonPipelineEnvironment.configuration = [
general: [
camSystemRole: 'testRole',
cfCredentialsId: 'myCreds'
],
stages: [
acceptance: [
cfOrg: 'testOrg',
cfSpace: 'testSpace',
deployUser: 'testUser',
]
],
steps: [
cloudFoundryDeploy: []
]
]
jsr.step.cloudFoundryDeploy([
script: nullScript,
juStabUtils: utils,
deployTool: '',
stageName: 'acceptance',
])
assertTrue(jlr.log.contains('[cloudFoundryDeploy] General parameters: deployTool=, deployType=standard, cfApiEndpoint=https://api.cf.eu10.hana.ondemand.com, cfOrg=testOrg, cfSpace=testSpace, cfCredentialsId=myCreds, deployUser=testUser'))
}
@Test
void testNotAvailableTool() throws Exception {
nullScript.commonPipelineEnvironment.configuration = [
general: [
cfCredentialsId: 'myCreds'
],
stages: [
acceptance: [
cfOrg: 'testOrg',
cfSpace: 'testSpace',
deployUser: 'testUser',
]
],
steps: [
cloudFoundryDeploy: []
]
]
jsr.step.cloudFoundryDeploy([
script: nullScript,
juStabUtils: utils,
deployTool: 'notAvailable',
stageName: 'acceptance'
])
assertTrue(jlr.log.contains('[cloudFoundryDeploy] General parameters: deployTool=notAvailable, deployType=standard, cfApiEndpoint=https://api.cf.eu10.hana.ondemand.com, cfOrg=testOrg, cfSpace=testSpace, cfCredentialsId=myCreds, deployUser=testUser'))
}
@Test
void testCfNativeWithAppName() {
jsr.step.cloudFoundryDeploy([
script: nullScript,
juStabUtils: utils,
deployTool: 'cf_native',
cfOrg: 'testOrg',
cfSpace: 'testSpace',
cfCredentialsId: 'test_cfCredentialsId',
cfAppName: 'testAppName',
cfManifest: 'test.yml'
])
assertEquals('s4sdk/docker-cf-cli', jedr.dockerParams.dockerImage)
assertEquals('/home/piper', jedr.dockerParams.dockerWorkspace)
assertEquals('200', jedr.dockerParams.dockerEnvVars.STATUS_CODE.toString())
assertTrue(jscr.shell[1].contains('cf login -u "test_cf" -p \'********\' -a https://api.cf.eu10.hana.ondemand.com -o "testOrg" -s "testSpace"'))
assertTrue(jscr.shell[1].contains('cf push "testAppName" -f "test.yml"'))
}
@Test
void testCfNativeWithAppNameCustomApi() {
jsr.step.cloudFoundryDeploy([
script: nullScript,
juStabUtils: utils,
deployTool: 'cf_native',
cfApiEndpoint: 'https://customApi',
cfOrg: 'testOrg',
cfSpace: 'testSpace',
cfCredentialsId: 'test_cfCredentialsId',
cfAppName: 'testAppName',
cfManifest: 'test.yml'
])
assertTrue(jscr.shell[1].contains('cf login -u "test_cf" -p \'********\' -a https://customApi -o "testOrg" -s "testSpace"'))
}
@Test
void testCfNativeWithAppNameCompatible() {
jsr.step.cloudFoundryDeploy([
script: nullScript,
juStabUtils: utils,
deployTool: 'cf_native',
cloudFoundry: [
org: 'testOrg',
space: 'testSpace',
credentialsId: 'test_cfCredentialsId',
appName: 'testAppName',
manifest: 'test.yml'
]
])
assertEquals('s4sdk/docker-cf-cli', jedr.dockerParams.dockerImage)
assertEquals('/home/piper', jedr.dockerParams.dockerWorkspace)
assertEquals('200', jedr.dockerParams.dockerEnvVars.STATUS_CODE.toString())
assertTrue(jscr.shell[1].contains('cf login -u "test_cf" -p \'********\' -a https://api.cf.eu10.hana.ondemand.com -o "testOrg" -s "testSpace"'))
assertTrue(jscr.shell[1].contains('cf push "testAppName" -f "test.yml"'))
}
@Test
void testCfNativeAppNameFromManifest() {
helper.registerAllowedMethod('fileExists', [String.class], { s -> return true })
helper.registerAllowedMethod("readYaml", [Map], { Map m ->
if(m.text) {
return new Yaml().load(m.text)
} else if(m.file == 'test.yml') {
return [applications: [[name: 'manifestAppName']]]
} else if(m.file) {
return new Yaml().load((m.file as File).text)
} else {
throw new IllegalArgumentException("Key 'text' is missing in map ${m}.")
}
})
jsr.step.cloudFoundryDeploy([
script: nullScript,
juStabUtils: utils,
deployTool: 'cf_native',
cfOrg: 'testOrg',
cfSpace: 'testSpace',
cfCredentialsId: 'test_cfCredentialsId',
cfManifest: 'test.yml'
])
assertTrue(jscr.shell[1].contains('cf login -u "test_cf" -p \'********\' -a https://api.cf.eu10.hana.ondemand.com -o "testOrg" -s "testSpace"'))
assertTrue(jscr.shell[1].contains('cf push -f "test.yml"'))
}
@Test
void testCfNativeWithoutAppName() {
helper.registerAllowedMethod('fileExists', [String.class], { s -> return true })
helper.registerAllowedMethod("readYaml", [Map], { Map m ->
if(m.text) {
return new Yaml().load(m.text)
} else if(m.file == 'test.yml') {
return [applications: [[]]]
} else if(m.file) {
return new Yaml().load((m.file as File).text)
} else {
throw new IllegalArgumentException("Key 'text' is missing in map ${m}.")
}
})
thrown.expect(hudson.AbortException)
thrown.expectMessage('[cloudFoundryDeploy] ERROR: No appName available in manifest test.yml.')
jsr.step.cloudFoundryDeploy([
script: nullScript,
juStabUtils: utils,
deployTool: 'cf_native',
cfOrg: 'testOrg',
cfSpace: 'testSpace',
cfCredentialsId: 'test_cfCredentialsId',
cfManifest: 'test.yml'
])
}
@Test
void testMta() {
jsr.step.cloudFoundryDeploy([
script: nullScript,
juStabUtils: utils,
cfOrg: 'testOrg',
cfSpace: 'testSpace',
cfCredentialsId: 'test_cfCredentialsId',
deployTool: 'mtaDeployPlugin',
mtaPath: 'target/test.mtar'
])
assertEquals('s4sdk/docker-cf-cli', jedr.dockerParams.dockerImage)
assertEquals('/home/piper', jedr.dockerParams.dockerWorkspace)
assertTrue(jscr.shell[0].contains('cf login -u test_cf -p \'********\' -a https://api.cf.eu10.hana.ondemand.com -o "testOrg" -s "testSpace"'))
assertTrue(jscr.shell[0].contains("cf deploy target/test.mtar -f".toString()))
}
}

View File

@ -7,9 +7,15 @@ import util.JenkinsShellCallRule
import util.JenkinsStepRule
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
import static org.junit.Assert.assertTrue
class MavenExecuteTest extends BasePiperTest {
Map dockerParameters
@ -63,10 +69,34 @@ class MavenExecuteTest extends BasePiperTest {
@Test
void testMavenCommandForwardsDockerOptions() throws Exception {
jsr.step.mavenExecute(script: nullScript, goals: 'clean install')
assertEquals('maven:3.5-jdk-7', jder.dockerParams.dockerImage)
assert jscr.shell[0] == 'mvn --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn clean install'
assertEquals('mvn --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn clean install', jscr.shell[0])
}
@Test
void testMavenCommandWithShortBatchModeFlag() throws Exception {
jsr.step.mavenExecute(script: nullScript, goals: 'clean install', flags: '-B')
assertEquals('maven:3.5-jdk-7', jder.dockerParams.dockerImage)
assertEquals('mvn -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn clean install', jscr.shell[0])
}
@Test
void testMavenCommandWithFalsePositiveMinusBFlag() throws Exception {
jsr.step.mavenExecute(script: nullScript, goals: 'clean install', flags: '-Blah')
assertEquals('maven:3.5-jdk-7', jder.dockerParams.dockerImage)
assertThat(jscr.shell[0],
allOf(containsString('-Blah'),
containsString('--batch-mode')))
}
@Test
void testMavenCommandWithBatchModeMultiline() throws Exception {
jsr.step.mavenExecute(script: nullScript, goals: 'clean install', flags: ('''-B\\
|--show-version''' as CharSequence).stripMargin())
assertThat(jscr.shell[0], not(containsString('--batch-mode')))
}
}

View File

@ -15,8 +15,10 @@ import util.JenkinsLoggingRule
import util.JenkinsShellCallRule
import util.JenkinsDockerExecuteRule
import util.Rules
import org.junit.rules.ExpectedException
class NewmanExecuteTest extends BasePiperTest {
private ExpectedException thrown = ExpectedException.none()
private JenkinsStepRule jsr = new JenkinsStepRule(this)
private JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
private JenkinsShellCallRule jscr = new JenkinsShellCallRule(this)
@ -25,21 +27,25 @@ class NewmanExecuteTest extends BasePiperTest {
@Rule
public RuleChain rules = Rules
.getCommonRules(this)
.around(thrown)
.around(jedr)
.around(jscr)
.around(jlr)
.around(jsr) // needs to be activated after jedr, otherwise executeDocker is not mocked
def testRepository
def gitMap
@Before
void init() throws Exception {
helper.registerAllowedMethod('git', [String.class], {s ->
testRepository = s
helper.registerAllowedMethod('stash', [String.class], null)
helper.registerAllowedMethod('git', [Map.class], {m ->
gitMap = m
})
helper.registerAllowedMethod("findFiles", [Map.class], { map ->
def files
if(map.glob == '**/*.postman_collection.json')
if(map.glob == 'notFound.json')
files = []
else if(map.glob == '**/*.postman_collection.json')
files = [
new File("testCollectionsFolder/A.postman_collection.json"),
new File("testCollectionsFolder/B.postman_collection.json")
@ -54,6 +60,7 @@ class NewmanExecuteTest extends BasePiperTest {
void testExecuteNewmanDefault() throws Exception {
jsr.step.newmanExecute(
script: nullScript,
juStabUtils: utils,
newmanCollection: 'testCollection',
newmanEnvironment: 'testEnvironment',
newmanGlobals: 'testGlobals'
@ -61,13 +68,28 @@ class NewmanExecuteTest extends BasePiperTest {
// asserts
assertThat(jscr.shell, hasItem('newman run testCollection --environment \'testEnvironment\' --globals \'testGlobals\' --reporters junit,html --reporter-junit-export target/newman/TEST-testCollection.xml --reporter-html-export target/newman/TEST-testCollection.html'))
assertThat(jedr.dockerParams.dockerImage, is('node:8-stretch'))
assertThat(jlr.log, containsString('[newmanExecute] Found files [testCollection]'))
assertJobStatusSuccess()
}
@Test
void testExecuteNewmanWithNoCollection() throws Exception {
thrown.expectMessage('[newmanExecute] No collection found with pattern \'notFound.json\'')
jsr.step.newmanExecute(
script: nullScript,
juStabUtils: utils,
newmanCollection: 'notFound.json'
)
// asserts
assertJobStatusFailure()
}
@Test
void testExecuteNewmanFailOnError() throws Exception {
jsr.step.newmanExecute(
script: nullScript,
juStabUtils: utils,
newmanCollection: 'testCollection',
newmanEnvironment: 'testEnvironment',
newmanGlobals: 'testGlobals',
@ -77,7 +99,7 @@ class NewmanExecuteTest extends BasePiperTest {
)
// asserts
assertThat(jedr.dockerParams.dockerImage, is('testImage'))
assertThat(testRepository, is('testRepo'))
assertThat(gitMap.url, is('testRepo'))
assertThat(jscr.shell, hasItem('newman run testCollection --environment \'testEnvironment\' --globals \'testGlobals\' --reporters junit,html --reporter-junit-export target/newman/TEST-testCollection.xml --reporter-html-export target/newman/TEST-testCollection.html --suppress-exit-code'))
assertJobStatusSuccess()
}
@ -86,6 +108,7 @@ class NewmanExecuteTest extends BasePiperTest {
void testExecuteNewmanWithFolder() throws Exception {
jsr.step.newmanExecute(
script: nullScript,
juStabUtils: utils,
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

View File

@ -33,12 +33,18 @@ public class TransportRequestCreateTest extends BasePiperTest {
@Before
public void setup() {
nullScript.commonPipelineEnvironment.configuration = [steps:
[transportRequestCreate:
nullScript.commonPipelineEnvironment.configuration = [general:
[changeManagement:
[
credentialsId: 'CM',
endpoint: 'https://example.org/cm',
clientOpts: '-DmyProp=myVal'
clientOpts: '-DmyProp=myVal',
changeDocumentLabel: 'ChangeId\\s?:',
git: [from: 'origin/master',
to: 'HEAD',
format: '%b']
]
]
]
@ -80,8 +86,7 @@ public class TransportRequestCreateTest extends BasePiperTest {
String createTransportRequest(String changeId,
String developmentSystemId,
String cmEndpoint,
String username,
String password,
String credentialId,
String clientOpts) {
throw new ChangeManagementException('Exception message.')
@ -105,15 +110,14 @@ public class TransportRequestCreateTest extends BasePiperTest {
String createTransportRequest(String changeId,
String developmentSystemId,
String cmEndpoint,
String username,
String password,
String credentialId,
String clientOpts) {
result.changeId = changeId
result.developmentSystemId = developmentSystemId
result.cmEndpoint = cmEndpoint
result.username = username
result.password = password
result.credentialId = credentialId
result.clientOpts = clientOpts
return '001'
}
@ -125,8 +129,7 @@ public class TransportRequestCreateTest extends BasePiperTest {
assert result == [changeId: '001',
developmentSystemId: '001',
cmEndpoint: 'https://example.org/cm',
username: 'anonymous',
password: '********',
credentialId: 'CM',
clientOpts: '-DmyProp=myVal'
]

View File

@ -34,8 +34,8 @@ public class TransportRequestReleaseTest extends BasePiperTest {
@Before
public void setup() {
nullScript.commonPipelineEnvironment.configuration = [steps:
[transportRequestRelease:
nullScript.commonPipelineEnvironment.configuration = [general:
[changeManagement:
[
credentialsId: 'CM',
endpoint: 'https://example.org/cm'
@ -57,7 +57,7 @@ public class TransportRequestReleaseTest extends BasePiperTest {
}
thrown.expect(IllegalArgumentException)
thrown.expectMessage("ERROR - NO VALUE AVAILABLE FOR changeDocumentId")
thrown.expectMessage("Change document id not provided (parameter: 'changeDocumentId' or via commit history).")
jsr.step.call(script: nullScript, transportRequestId: '001', cmUtils: cm)
}
@ -87,11 +87,11 @@ public class TransportRequestReleaseTest extends BasePiperTest {
thrown.expectMessage("Something went wrong")
ChangeManagement cm = new ChangeManagement(nullScript) {
void releaseTransportRequest(String changeId,
String transportRequestId,
String endpoint,
String username,
String password,
String credentialsId,
String clientOpts) {
throw new ChangeManagementException('Something went wrong')
@ -113,15 +113,13 @@ public class TransportRequestReleaseTest extends BasePiperTest {
void releaseTransportRequest(String changeId,
String transportRequestId,
String endpoint,
String username,
String password,
String credentialsId,
String clientOpts) {
receivedParams.changeId = changeId
receivedParams.transportRequestId = transportRequestId
receivedParams.endpoint = endpoint
receivedParams.username = username
receivedParams.password = password
receivedParams.credentialsId = credentialsId
receivedParams.clientOpts = clientOpts
}
}
@ -131,8 +129,7 @@ public class TransportRequestReleaseTest extends BasePiperTest {
assert receivedParams == [changeId: '001',
transportRequestId: '002',
endpoint: 'https://example.org/cm',
username: 'anonymous',
password: '********',
clientOpts: null]
credentialsId: 'CM',
clientOpts: '']
}
}

View File

@ -39,8 +39,8 @@ public class TransportRequestUploadFileTest extends BasePiperTest {
cmUtilReceivedParams.clear()
nullScript.commonPipelineEnvironment.configuration = [steps:
[transportRequestUploadFile:
nullScript.commonPipelineEnvironment.configuration = [general:
[changeManagement:
[
credentialsId: 'CM',
endpoint: 'https://example.org/cm'
@ -116,8 +116,7 @@ public class TransportRequestUploadFileTest extends BasePiperTest {
String applicationId,
String filePath,
String endpoint,
String username,
String password,
String credentialsId,
String cmclientOpts) {
throw new ChangeManagementException('Exception message')
}
@ -146,8 +145,7 @@ public class TransportRequestUploadFileTest extends BasePiperTest {
String applicationId,
String filePath,
String endpoint,
String username,
String password,
String credentialsId,
String cmclientOpts) {
cmUtilReceivedParams.changeId = changeId
@ -155,8 +153,7 @@ public class TransportRequestUploadFileTest extends BasePiperTest {
cmUtilReceivedParams.applicationId = applicationId
cmUtilReceivedParams.filePath = filePath
cmUtilReceivedParams.endpoint = endpoint
cmUtilReceivedParams.username = username
cmUtilReceivedParams.password = password
cmUtilReceivedParams.credentialsId = credentialsId
cmUtilReceivedParams.cmclientOpts = cmclientOpts
}
}
@ -175,12 +172,68 @@ public class TransportRequestUploadFileTest extends BasePiperTest {
applicationId: 'app',
filePath: '/path',
endpoint: 'https://example.org/cm',
username: 'anonymous',
password: '********',
cmclientOpts: null
credentialsId: 'CM',
cmclientOpts: ''
]
}
@Test
public void uploadFileToTransportRequestFilePathFromParameters() {
// this one is not used when file path is provided via signature
nullScript.commonPipelineEnvironment.setMtarFilePath('/path2')
ChangeManagement cm = new ChangeManagement(nullScript) {
void uploadFileToTransportRequest(String changeId,
String transportRequestId,
String applicationId,
String filePath,
String endpoint,
String credentialsId,
String cmclientOpts) {
cmUtilReceivedParams.filePath = filePath
}
}
jsr.step.call(script: nullScript,
changeDocumentId: '001',
transportRequestId: '002',
applicationId: 'app',
filePath: '/path',
cmUtils: cm)
assert cmUtilReceivedParams.filePath == '/path'
}
@Test
public void uploadFileToTransportRequestFilePathFromCommonPipelineEnvironment() {
// this one is used since there is nothing in the signature
nullScript.commonPipelineEnvironment.setMtarFilePath('/path2')
ChangeManagement cm = new ChangeManagement(nullScript) {
void uploadFileToTransportRequest(String changeId,
String transportRequestId,
String applicationId,
String filePath,
String endpoint,
String credentialsId,
String cmclientOpts) {
cmUtilReceivedParams.filePath = filePath
}
}
jsr.step.call(script: nullScript,
changeDocumentId: '001',
transportRequestId: '002',
applicationId: 'app',
cmUtils: cm)
assert cmUtilReceivedParams.filePath == '/path2'
}
@Test
public void uploadFileToTransportRequestUploadFailureTest() {
@ -193,8 +246,7 @@ public class TransportRequestUploadFileTest extends BasePiperTest {
String applicationId,
String filePath,
String endpoint,
String username,
String password,
String credentialsId,
String cmclientOpts) {
throw new ChangeManagementException('Upload failure.')
}

View File

@ -3,7 +3,10 @@ package com.sap.piper
import groovy.test.GroovyAssert
import static org.hamcrest.Matchers.*
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertThat
import org.hamcrest.Matchers
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
@ -29,6 +32,41 @@ class ConfigurationHelperTest {
Assert.assertFalse(configuration.isPropertyDefined('something'))
}
@Test
void testGetPropertyNestedLeafNodeIsString() {
def configuration = new ConfigurationHelper([a:[b: 'c']])
assertThat(configuration.getConfigProperty('a/b'), is('c'))
}
@Test
void testGetPropertyNestedLeafNodeIsMap() {
def configuration = new ConfigurationHelper([a:[b: [c: 'd']]])
assertThat(configuration.getConfigProperty('a/b'), is([c: 'd']))
}
@Test
void testGetPropertyNestedPathNotFound() {
def configuration = new ConfigurationHelper([a:[b: 'c']])
assertThat(configuration.getConfigProperty('a/c'), is((nullValue())))
}
void testGetPropertyNestedPathStartsWithTokenizer() {
def configuration = new ConfigurationHelper([k:'v'])
assertThat(configuration.getConfigProperty('/k'), is(('v')))
}
@Test
void testGetPropertyNestedPathEndsWithTokenizer() {
def configuration = new ConfigurationHelper([k:'v'])
assertThat(configuration.getConfigProperty('k/'), is(('v')))
}
@Test
void testGetPropertyNestedPathManyTokenizer() {
def configuration = new ConfigurationHelper([k1:[k2 : 'v']])
assertThat(configuration.getConfigProperty('///k1/////k2///'), is(('v')))
}
@Test
void testIsPropertyDefined() {
def configuration = new ConfigurationHelper(getConfiguration())
@ -120,6 +158,69 @@ class ConfigurationHelperTest {
Assert.assertThat(config, hasEntry('executeDocker3', false))
}
@Test
void testHandleCompatibility() {
def configuration = new ConfigurationHelper()
.mixin([old1: 'oldValue1', old2: 'oldValue2', test: 'testValue'], null, null, [newStructure: [new1: 'old1', new2: 'old2']])
.use()
Assert.assertThat(configuration.size(), is(4))
Assert.assertThat(configuration.newStructure.new1, is('oldValue1'))
Assert.assertThat(configuration.newStructure.new2, is('oldValue2'))
}
@Test
void testHandleCompatibilityFlat() {
def configuration = new ConfigurationHelper()
.mixin([old1: 'oldValue1', old2: 'oldValue2', test: 'testValue'], null, null, [new1: 'old1', new2: 'old2'])
.use()
Assert.assertThat(configuration.size(), is(5))
Assert.assertThat(configuration.new1, is('oldValue1'))
Assert.assertThat(configuration.new2, is('oldValue2'))
}
@Test
void testHandleCompatibilityDeep() {
def configuration = new ConfigurationHelper()
.mixin([old1: 'oldValue1', old2: 'oldValue2', test: 'testValue'], null, null, [deep:[deeper:[newStructure: [new1: 'old1', new2: 'old2']]]])
.use()
Assert.assertThat(configuration.size(), is(4))
Assert.assertThat(configuration.deep.deeper.newStructure.new1, is('oldValue1'))
Assert.assertThat(configuration.deep.deeper.newStructure.new2, is('oldValue2'))
}
@Test
void testHandleCompatibilityNewAvailable() {
def configuration = new ConfigurationHelper([old1: 'oldValue1', newStructure: [new1: 'newValue1'], test: 'testValue'])
.mixin([old1: 'oldValue1', newStructure: [new1: 'newValue1'], test: 'testValue'], null, null, [newStructure: [new1: 'old1', new2: 'old2']])
.use()
Assert.assertThat(configuration.size(), is(3))
Assert.assertThat(configuration.newStructure.new1, is('newValue1'))
}
@Test
void testHandleCompatibilityOldNotSet() {
def configuration = new ConfigurationHelper([old1: null, test: 'testValue'])
.mixin([old1: null, test: 'testValue'], null, null, [newStructure: [new1: 'old1', new2: 'old2']])
.use()
Assert.assertThat(configuration.size(), is(2))
Assert.assertThat(configuration.newStructure.new1, is(null))
}
@Test
void testHandleCompatibilityNoneAvailable() {
def configuration = new ConfigurationHelper([old1: null, test: 'testValue'])
.mixin([test: 'testValue'], null, null, [newStructure: [new1: 'old1', new2: 'old2']])
.use()
Assert.assertThat(configuration.size(), is(2))
Assert.assertThat(configuration.newStructure.new1, is(null))
}
@Test
public void testWithMandoryParameterReturnDefaultFailureMessage() {
@ -148,4 +249,34 @@ class ConfigurationHelperTest {
new ConfigurationHelper([myKey: 'myValue']).withMandatoryProperty('myKey')
}
@Test
public void testWithMandoryWithFalseCondition() {
new ConfigurationHelper([verify: false])
.withMandatoryProperty('missingKey', null, { c -> return c.get('verify') })
}
@Test
public void testWithMandoryWithTrueConditionMissingValue() {
thrown.expect(IllegalArgumentException)
thrown.expectMessage('ERROR - NO VALUE AVAILABLE FOR missingKey')
new ConfigurationHelper([verify: true])
.withMandatoryProperty('missingKey', null, { c -> return c.get('verify') })
}
@Test
public void testWithMandoryWithTrueConditionExistingValue() {
new ConfigurationHelper([existingKey: 'anyValue', verify: true])
.withMandatoryProperty('existingKey', null, { c -> return c.get('verify') })
}
@Test
public void testTelemetryConfigurationAvailable() {
Set filter = ['test']
def configuration = new ConfigurationHelper([test: 'testValue'])
.mixin([collectTelemetryData: false], filter)
.use()
Assert.assertThat(configuration, hasEntry('collectTelemetryData', false))
}
}

View File

@ -21,6 +21,7 @@ import util.BasePiperTest
import util.JenkinsLoggingRule
import util.JenkinsScriptLoaderRule
import util.JenkinsShellCallRule
import util.JenkinsCredentialsRule
import util.Rules
import hudson.AbortException
@ -37,6 +38,7 @@ public class ChangeManagementTest extends BasePiperTest {
.around(thrown)
.around(script)
.around(logging)
.around(new JenkinsCredentialsRule(this).withCredentials('me','user','password'))
@Test
public void testRetrieveChangeDocumentIdOutsideGitWorkTreeTest() {
@ -90,8 +92,7 @@ public class ChangeManagementTest extends BasePiperTest {
public void testIsChangeInDevelopmentReturnsTrueWhenChangeIsInDevelopent() {
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, "cmclient.*is-change-in-development -cID '001'", 0)
boolean inDevelopment = new ChangeManagement(nullScript, null).isChangeInDevelopment('001', 'endpoint', 'user', 'password')
boolean inDevelopment = new ChangeManagement(nullScript, null).isChangeInDevelopment('001', 'endpoint', 'me')
assertThat(inDevelopment, is(equalTo(true)))
assertThat(script.shell[0], allOf(containsString("cmclient"),
@ -111,8 +112,7 @@ public class ChangeManagementTest extends BasePiperTest {
boolean inDevelopment = new ChangeManagement(nullScript, null)
.isChangeInDevelopment('001',
'endpoint',
'user',
'password')
'me')
assertThat(inDevelopment, is(equalTo(false)))
}
@ -124,8 +124,7 @@ public class ChangeManagementTest extends BasePiperTest {
thrown.expectMessage('Cannot retrieve status for change document \'001\'. Does this change exist? Return code from cmclient: 1.')
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, "cmclient.*is-change-in-development -cID '001'", 1)
new ChangeManagement(nullScript, null).isChangeInDevelopment('001', 'endpoint', 'user', 'password')
new ChangeManagement(nullScript, null).isChangeInDevelopment('001', 'endpoint', 'me')
}
@Test
@ -139,7 +138,7 @@ public class ChangeManagementTest extends BasePiperTest {
commandLine = commandLine.replaceAll(' +', " ")
assertThat(commandLine, not(containsString("CMCLIENT_OPTS")))
assertThat(commandLine, containsString("cmclient -e 'https://example.org/cm' -u 'me' -p 'topSecret' -t SOLMAN the-command -key1 val1 -key2 val2"))
}
}
@Test
public void testGetCommandLineWithCMClientOpts() {
@ -158,7 +157,7 @@ public void testGetCommandLineWithCMClientOpts() {
public void testCreateTransportRequestSucceeds() {
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, ".*cmclient.*create-transport -cID 001 -dID 002.*", '004')
def transportRequestId = new ChangeManagement(nullScript).createTransportRequest('001', '002', '003', 'me', 'openSesame')
def transportRequestId = new ChangeManagement(nullScript).createTransportRequest('001', '002', '003', 'me')
// the check for the transportRequestID is sufficient. This checks implicit the command line since that value is
// returned only in case the shell call matches.
@ -180,8 +179,7 @@ public void testGetCommandLineWithCMClientOpts() {
'XXX',
'/path',
'https://example.org/cm',
'me',
'openSesame')
'me')
}
@Test
@ -195,8 +193,7 @@ public void testGetCommandLineWithCMClientOpts() {
'XXX',
'/path',
'https://example.org/cm',
'me',
'openSesame')
'me')
// no assert required here, since the regex registered above to the script rule is an implicit check for
// the command line.
@ -216,8 +213,7 @@ public void testGetCommandLineWithCMClientOpts() {
'XXX',
'/path',
'https://example.org/cm',
'me',
'openSesame')
'me')
}
@Test

View File

@ -0,0 +1,32 @@
package com.sap.piper.versioning
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import util.BasePiperTest
import util.JenkinsReadJsonRule
import util.JenkinsWriteJsonRule
import util.Rules
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertTrue
class DlangArtifactVersioningTest extends BasePiperTest{
JenkinsReadJsonRule jrjr = new JenkinsReadJsonRule(this, 'test/resources/versioning/DlangArtifactVersioning/')
JenkinsWriteJsonRule jwjr = new JenkinsWriteJsonRule(this)
@Rule
public RuleChain ruleChain = Rules
.getCommonRules(this)
.around(jrjr)
.around(jwjr)
@Test
void testVersioning() {
DlangArtifactVersioning av = new DlangArtifactVersioning(nullScript, [filePath: 'dub.json'])
assertEquals('1.2.3', av.getVersion())
av.setVersion('1.2.3-20180101')
assertTrue(jwjr.files['dub.json'].contains('1.2.3-20180101'))
}
}

View File

@ -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.JenkinsReadFileRule
import util.JenkinsWriteFileRule
import util.Rules
import static org.junit.Assert.assertEquals
class GolangArtifactVersioningTest extends BasePiperTest{
JenkinsReadFileRule jrfr = new JenkinsReadFileRule(this, 'test/resources/versioning/GolangArtifactVersioning/')
JenkinsWriteFileRule jwfr = new JenkinsWriteFileRule(this)
@Rule
public RuleChain ruleChain = Rules
.getCommonRules(this)
.around(jrfr)
.around(jwfr)
@Test
void testVersioning() {
GolangArtifactVersioning av = new GolangArtifactVersioning(nullScript, [filePath: 'VERSION'])
assertEquals('1.2.3', av.getVersion())
av.setVersion('1.2.3-20180101')
assertEquals('1.2.3-20180101', jwfr.files['VERSION'])
}
}

View File

@ -0,0 +1,32 @@
package com.sap.piper.versioning
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import util.BasePiperTest
import util.JenkinsReadJsonRule
import util.JenkinsWriteJsonRule
import util.Rules
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertTrue
class NpmArtifactVersioningTest extends BasePiperTest{
JenkinsReadJsonRule jrjr = new JenkinsReadJsonRule(this, 'test/resources/versioning/NpmArtifactVersioning/')
JenkinsWriteJsonRule jwjr = new JenkinsWriteJsonRule(this)
@Rule
public RuleChain ruleChain = Rules
.getCommonRules(this)
.around(jrjr)
.around(jwjr)
@Test
void testVersioning() {
NpmArtifactVersioning av = new NpmArtifactVersioning(nullScript, [filePath: 'package.json'])
assertEquals('1.2.3', av.getVersion())
av.setVersion('1.2.3-20180101')
assertTrue(jwjr.files['package.json'].contains('1.2.3-20180101'))
}
}

View File

@ -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.JenkinsReadFileRule
import util.JenkinsWriteFileRule
import util.Rules
import static org.junit.Assert.assertEquals
class PipArtifactVersioningTest extends BasePiperTest{
JenkinsReadFileRule jrfr = new JenkinsReadFileRule(this, 'test/resources/versioning/PipArtifactVersioning/')
JenkinsWriteFileRule jwfr = new JenkinsWriteFileRule(this)
@Rule
public RuleChain ruleChain = Rules
.getCommonRules(this)
.around(jrfr)
.around(jwfr)
@Test
void testVersioning() {
PipArtifactVersioning av = new PipArtifactVersioning(nullScript, [filePath: 'version.txt'])
assertEquals('1.2.3', av.getVersion())
av.setVersion('1.2.3-20180101')
assertEquals('1.2.3-20180101', jwfr.files['version.txt'])
}
}

View File

@ -0,0 +1,32 @@
package com.sap.piper.versioning
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import util.BasePiperTest
import util.JenkinsReadJsonRule
import util.JenkinsWriteJsonRule
import util.Rules
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertTrue
class SbtArtifactVersioningTest extends BasePiperTest{
JenkinsReadJsonRule jrjr = new JenkinsReadJsonRule(this, 'test/resources/versioning/SbtArtifactVersioning/')
JenkinsWriteJsonRule jwjr = new JenkinsWriteJsonRule(this)
@Rule
public RuleChain ruleChain = Rules
.getCommonRules(this)
.around(jrjr)
.around(jwjr)
@Test
void testVersioning() {
SbtArtifactVersioning av = new SbtArtifactVersioning(nullScript, [filePath: 'sbtDescriptor.json'])
assertEquals('1.2.3', av.getVersion())
av.setVersion('1.2.3-20180101')
assertTrue(jwjr.files['sbtDescriptor.json'].contains('1.2.3-20180101'))
}
}

View File

@ -0,0 +1,34 @@
package util
import com.lesfurets.jenkins.unit.BasePipelineTest
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
class JenkinsWriteJsonRule implements TestRule {
final BasePipelineTest testInstance
Map files = [:]
JenkinsWriteJsonRule(BasePipelineTest testInstance) {
this.testInstance = testInstance
}
@Override
Statement apply(Statement base, Description description) {
return statement(base)
}
private Statement statement(final Statement base) {
return new Statement() {
@Override
void evaluate() throws Throwable {
testInstance.helper.registerAllowedMethod( 'writeJSON', [Map.class], {m -> files[m.file] = m.json.toString()})
base.evaluate()
}
}
}
}

View File

@ -0,0 +1,5 @@
{
"name": "sap-pipeline-test",
"version": "1.2.3",
"description": "package.json for testing",
}

View File

@ -0,0 +1 @@
1.2.3

View File

@ -0,0 +1,15 @@
{
"name": "sap-pipeline-test",
"version": "1.2.3",
"private": false,
"description": "package.json for testing",
"engines": {
"node": "6.x"
},
"dependencies": {
"apn": "1.7.8"
},
"devDependencies": {
"chai": "^3.4.1"
}
}

View File

@ -0,0 +1 @@
1.2.3

View File

@ -0,0 +1,4 @@
{
"name": "sap-pipeline-test",
"version": "1.2.3",
}

View File

@ -7,13 +7,14 @@ import groovy.transform.Field
import groovy.text.SimpleTemplateEngine
@Field String STEP_NAME = 'artifactSetVersion'
@Field Map CONFIG_KEY_COMPATIBILITY = [gitSshKeyCredentialsId: 'gitCredentialsId']
@Field Set STEP_CONFIG_KEYS = [
'artifactType',
'buildTool',
'commitVersion',
'dockerVersionSource',
'filePath',
'gitCredentialsId',
'gitSshKeyCredentialsId',
'gitUserEMail',
'gitUserName',
'gitSshUrl',
@ -24,14 +25,11 @@ import groovy.text.SimpleTemplateEngine
]
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS.plus('gitCommitId')
def call(Map parameters = [:]) {
def call(Map parameters = [:], Closure body = null) {
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) {
def gitUtils = parameters.juStabGitUtils
if (gitUtils == null) {
gitUtils = new GitUtils()
}
def gitUtils = parameters.juStabGitUtils ?: new GitUtils()
if (fileExists('.git')) {
if (sh(returnStatus: true, script: 'git diff --quiet HEAD') != 0)
@ -43,73 +41,71 @@ def call(Map parameters = [:]) {
script = this
// load default & individual configuration
Map configuration = ConfigurationHelper
Map config = ConfigurationHelper
.loadStepDefaults(this)
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixinGeneralConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS, this, CONFIG_KEY_COMPATIBILITY)
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS, this, CONFIG_KEY_COMPATIBILITY)
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, STEP_CONFIG_KEYS, this, CONFIG_KEY_COMPATIBILITY)
.mixin(gitCommitId: gitUtils.getGitCommitIdOrNull())
.mixin(parameters, PARAMETER_KEYS)
.mixin(parameters, PARAMETER_KEYS, this, CONFIG_KEY_COMPATIBILITY)
.withMandatoryProperty('buildTool')
.dependingOn('buildTool').mixin('filePath')
.dependingOn('buildTool').mixin('versioningTemplate')
.use()
def utils = new Utils()
def buildTool = utils.getMandatoryParameter(configuration, 'buildTool')
config = new ConfigurationHelper(config)
.addIfEmpty('gitSshUrl', (config.buildTool == 'docker' && config.artifactType == 'appContainer')?script.commonPipelineEnvironment.getAppContainerProperty('gitSshUrl'):script.commonPipelineEnvironment.getGitSshUrl())
.addIfEmpty('timestamp', getTimestamp(config.timestampTemplate))
.withMandatoryProperty('gitSshUrl')
.use()
if (!configuration.filePath)
configuration.filePath = configuration[buildTool].filePath //use default configuration
new Utils().pushToSWA([step: STEP_NAME, stepParam1: config.buildTool, stepParam2: config.artifactType], config)
def artifactVersioning = ArtifactVersioning.getArtifactVersioning(config.buildTool, script, config)
def currentVersion = artifactVersioning.getVersion()
def newVersion
def artifactVersioning = ArtifactVersioning.getArtifactVersioning(buildTool, script, configuration)
if(configuration.artifactType == 'appContainer' && configuration.dockerVersionSource == 'appVersion'){
if (script.commonPipelineEnvironment.getArtifactVersion())
//replace + sign if available since + is not allowed in a Docker tag
newVersion = script.commonPipelineEnvironment.getArtifactVersion().replace('+', '_')
else
error ("[${STEP_NAME}] No artifact version available for 'dockerVersionSource: appVersion' -> executeBuild needs to run for the application artifact first to set the artifactVersion for the application artifact.'")
if (config.artifactType == 'appContainer' && config.dockerVersionSource == 'appVersion'){
newVersion = currentVersion
} else {
def currentVersion = artifactVersioning.getVersion()
def timestamp = configuration.timestamp ? configuration.timestamp : getTimestamp(configuration.timestampTemplate)
def versioningTemplate = configuration.versioningTemplate ? configuration.versioningTemplate : configuration[configuration.buildTool].versioningTemplate
//defined in default configuration
def binding = [version: currentVersion, timestamp: timestamp, commitId: configuration.gitCommitId]
def templatingEngine = new SimpleTemplateEngine()
def template = templatingEngine.createTemplate(versioningTemplate).make(binding)
newVersion = template.toString()
def binding = [version: currentVersion, timestamp: config.timestamp, commitId: config.gitCommitId]
newVersion = new SimpleTemplateEngine().createTemplate(config.versioningTemplate).make(binding).toString()
}
artifactVersioning.setVersion(newVersion)
def gitCommitId
if(body != null){
body(newVersion)
}
if (configuration.commitVersion) {
if (config.commitVersion) {
sh 'git add .'
sshagent([configuration.gitCredentialsId]) {
sshagent([config.gitSshKeyCredentialsId]) {
def gitUserMailConfig = ''
if (configuration.gitUserName && configuration.gitUserEMail)
gitUserMailConfig = "-c user.email=\"${configuration.gitUserEMail}\" -c user.name=\"${configuration.gitUserName}\""
if (config.gitUserName && config.gitUserEMail)
gitUserMailConfig = "-c user.email=\"${config.gitUserEMail}\" -c user.name=\"${config.gitUserName}\""
try {
sh "git ${gitUserMailConfig} commit -m 'update version ${newVersion}'"
} catch (e) {
error "[${STEP_NAME}]git commit failed: ${e}"
}
sh "git remote set-url origin ${configuration.gitSshUrl}"
sh "git tag ${configuration.tagPrefix}${newVersion}"
sh "git push origin ${configuration.tagPrefix}${newVersion}"
sh "git remote set-url origin ${config.gitSshUrl}"
sh "git tag ${config.tagPrefix}${newVersion}"
sh "git push origin ${config.tagPrefix}${newVersion}"
gitCommitId = gitUtils.getGitCommitIdOrNull()
config.gitCommitId = gitUtils.getGitCommitIdOrNull()
}
}
if (buildTool == 'docker' && configuration.artifactType == 'appContainer') {
if (config.buildTool == 'docker' && config.artifactType == 'appContainer') {
script.commonPipelineEnvironment.setAppContainerProperty('artifactVersion', newVersion)
script.commonPipelineEnvironment.setAppContainerProperty('gitCommitId', gitCommitId)
script.commonPipelineEnvironment.setAppContainerProperty('gitCommitId', config.gitCommitId)
} else {
//standard case
script.commonPipelineEnvironment.setArtifactVersion(newVersion)
script.commonPipelineEnvironment.setGitCommitId(gitCommitId)
script.commonPipelineEnvironment.setGitCommitId(config.gitCommitId)
}
echo "[${STEP_NAME}]New version: ${newVersion}"

View File

@ -1,4 +1,5 @@
import com.sap.piper.GitUtils
import com.sap.piper.Utils
import groovy.transform.Field
import hudson.AbortException
@ -10,14 +11,8 @@ import com.sap.piper.cm.ChangeManagementException
@Field def STEP_NAME = 'checkChangeInDevelopment'
@Field Set stepConfigurationKeys = [
'cmClientOpts',
'credentialsId',
'endpoint',
'failIfStatusIsNotInDevelopment',
'gitFrom',
'gitTo',
'gitChangeDocumentLabel',
'gitFormat'
'changeManagement',
'failIfStatusIsNotInDevelopment'
]
@Field Set parameterKeys = stepConfigurationKeys.plus('changeDocumentId')
@ -40,63 +35,72 @@ def call(parameters = [:]) {
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, stepConfigurationKeys)
.mixinStepConfig(script.commonPipelineEnvironment, stepConfigurationKeys)
.mixin(parameters, parameterKeys)
// for the following parameters we expect defaults
.withMandatoryProperty('changeManagement/changeDocumentLabel')
.withMandatoryProperty('changeManagement/clientOpts')
.withMandatoryProperty('changeManagement/credentialsId')
.withMandatoryProperty('changeManagement/git/from')
.withMandatoryProperty('changeManagement/git/to')
.withMandatoryProperty('changeManagement/git/format')
.withMandatoryProperty('failIfStatusIsNotInDevelopment')
// for the following parameters we expect a value provided from outside
.withMandatoryProperty('changeManagement/endpoint')
Map configuration = configHelper.use()
new Utils().pushToSWA([step: STEP_NAME], configuration)
def changeId = configuration.changeDocumentId
if(changeId?.trim()) {
echo "[INFO] ChangeDocumentId retrieved from parameters."
echo "[INFO] ChangeDocumentId retrieved from parameters."
} else {
echo "[INFO] Retrieving ChangeDocumentId from commit history [from: ${configuration.gitFrom}, to: ${configuration.gitTo}]." +
"Searching for pattern '${configuration.gitChangeDocumentLabel}'. Searching with format '${configuration.gitFormat}'."
echo "[INFO] Retrieving ChangeDocumentId from commit history [from: ${configuration.changeManagement.git.from}, to: ${configuration.changeManagement.git.to}]." +
"Searching for pattern '${configuration.changeManagement.changeDocumentLabel}'. Searching with format '${configuration.changeManagement.git.format}'."
try {
changeId = cm.getChangeDocumentId(
configuration.gitFrom,
configuration.gitTo,
configuration.gitChangeDocumentLabel,
configuration.gitFormat
configuration.changeManagement.git.from,
configuration.changeManagement.git.to,
configuration.changeManagement.changeDocumentLabel,
configuration.changeManagement.git.format
)
if(changeId?.trim()) {
echo "[INFO] ChangeDocumentId '${changeId}' retrieved from commit history"
}
} catch(ChangeManagementException ex) {
throw new AbortException(ex.getMessage())
echo "[WARN] Cannot retrieve changeDocumentId from commit history: ${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}].")
"nor via label '${configuration.changeManagement.changeDocumentLabel}' in commit range " +
"[from: ${configuration.changeManagement.git.from}, to: ${configuration.changeManagement.git.to}].")
.use()
boolean isInDevelopment
echo "[INFO] Checking if change document '${configuration.changeDocumentId}' is in development."
withCredentials([usernamePassword(
credentialsId: configuration.credentialsId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
try {
try {
isInDevelopment = cm.isChangeInDevelopment(configuration.changeDocumentId,
configuration.endpoint,
username,
password,
configuration.cmClientOpts)
} catch(ChangeManagementException ex) {
throw new AbortException(ex.getMessage())
}
isInDevelopment = cm.isChangeInDevelopment(configuration.changeDocumentId,
configuration.changeManagement.endpoint,
configuration.changeManagement.credentialsId,
configuration.changeManagement.clientOpts)
} catch(ChangeManagementException ex) {
throw new AbortException(ex.getMessage())
}
if(isInDevelopment) {
echo "[INFO] Change '${changeId}' is in status 'in development'."
return true

View File

@ -0,0 +1,169 @@
import com.sap.piper.Utils
import com.sap.piper.ConfigurationHelper
import groovy.transform.Field
@Field String STEP_NAME = 'cloudFoundryDeploy'
@Field Set STEP_CONFIG_KEYS = [
'cloudFoundry',
'deployUser',
'deployTool',
'deployType',
'dockerImage',
'dockerWorkspace',
'mtaDeployParameters',
'mtaExtensionDescriptor',
'mtaPath',
'smokeTestScript',
'smokeTestStatusCode',
'stashContent']
@Field Map CONFIG_KEY_COMPATIBILITY = [cloudFoundry: [apiEndpoint: 'cfApiEndpoint', appName:'cfAppName', credentialsId: 'cfCredentialsId', manifest: 'cfManifest', org: 'cfOrg', space: 'cfSpace']]
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
def call(Map parameters = [:]) {
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) {
def utils = parameters.juStabUtils
if (utils == null) {
utils = new Utils()
}
def script = parameters.script
if (script == null)
script = [commonPipelineEnvironment: commonPipelineEnvironment]
Map config = ConfigurationHelper
.loadStepDefaults(this)
.mixinGeneralConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS, this, CONFIG_KEY_COMPATIBILITY)
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS, this, CONFIG_KEY_COMPATIBILITY)
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, STEP_CONFIG_KEYS, this, CONFIG_KEY_COMPATIBILITY)
.mixin(parameters, PARAMETER_KEYS, this, CONFIG_KEY_COMPATIBILITY)
.dependingOn('deployTool').mixin('dockerImage')
.dependingOn('deployTool').mixin('dockerWorkspace')
.withMandatoryProperty('cloudFoundry/org')
.withMandatoryProperty('cloudFoundry/space')
.withMandatoryProperty('cloudFoundry/credentialsId')
.use()
utils.pushToSWA([step: STEP_NAME, stepParam1: config.deployTool, stepParam2: config.deployType], config)
echo "[${STEP_NAME}] General parameters: deployTool=${config.deployTool}, deployType=${config.deployType}, cfApiEndpoint=${config.cloudFoundry.apiEndpoint}, cfOrg=${config.cloudFoundry.org}, cfSpace=${config.cloudFoundry.space}, cfCredentialsId=${config.cloudFoundry.credentialsId}, deployUser=${config.deployUser}"
utils.unstash 'deployDescriptor'
if (config.deployTool == 'mtaDeployPlugin') {
// set default mtar path
config = new ConfigurationHelper(config)
.addIfEmpty('mtaPath', config.mtaPath?:findMtar())
.use()
dockerExecute(dockerImage: config.dockerImage, dockerWorkspace: config.dockerWorkspace, stashContent: config.stashContent) {
deployMta(config)
}
return
}
if (config.deployTool == 'cf_native') {
config.smokeTest = ''
if (config.smokeTestScript == 'blueGreenCheckScript.sh') {
writeFile file: config.smokeTestScript, text: libraryResource(config.smokeTestScript)
} else {
utils.unstash 'pipelineConfigAndTests'
}
config.smokeTest = '--smoke-test $(pwd)/' + config.smokeTestScript
sh "chmod +x ${config.smokeTestScript}"
echo "[${STEP_NAME}] CF native deployment (${config.deployType}) with cfAppName=${config.cloudFoundry.appName}, cfManifest=${config.cloudFoundry.manifest}, smokeTestScript=${config.smokeTestScript}"
dockerExecute (
dockerImage: config.dockerImage,
dockerWorkspace: config.dockerWorkspace,
stashContent: config.stashContent,
dockerEnvVars: [CF_HOME:"${config.dockerWorkspace}", CF_PLUGIN_HOME:"${config.dockerWorkspace}", STATUS_CODE: "${config.smokeTestStatusCode}"]
) {
deployCfNative(config)
}
return
}
}
}
def findMtar(){
def mtarPath = ''
def mtarFiles = findFiles(glob: '**/target/*.mtar')
if(mtarFiles.length > 1){
error 'Found multiple *.mtar files, please specify file via mtaPath parameter! ${mtarFiles}'
}
if(mtarFiles.length == 1){
return mtarFiles[0].path
}
error 'No *.mtar file found!'
}
def deployCfNative (config) {
withCredentials([usernamePassword(
credentialsId: config.cloudFoundry.credentialsId,
passwordVariable: 'password',
usernameVariable: 'username'
)]) {
def deployCommand = 'push'
if (config.deployType == 'blue-green') {
deployCommand = 'blue-green-deploy'
} else {
config.smokeTest = ''
}
// check if appName is available
if (config.cloudFoundry.appName == null || config.cloudFoundry.appName == '') {
if (fileExists(config.cloudFoundry.manifest)) {
def manifest = readYaml file: config.cloudFoundry.manifest
if (!manifest || !manifest.applications || !manifest.applications[0].name)
error "[${STEP_NAME}] ERROR: No appName available in manifest ${config.cloudFoundry.manifest}."
} else {
error "[${STEP_NAME}] ERROR: No manifest file ${config.cloudFoundry.manifest} found."
}
}
sh """#!/bin/bash
set +x
export HOME=${config.dockerWorkspace}
cf login -u \"${username}\" -p '${password}' -a ${config.cloudFoundry.apiEndpoint} -o \"${config.cloudFoundry.org}\" -s \"${config.cloudFoundry.space}\"
cf plugins
cf ${deployCommand} ${config.cloudFoundry.appName?"\"${config.cloudFoundry.appName}\"":''} -f \"${config.cloudFoundry.manifest}\" ${config.smokeTest}"""
def retVal = sh script: "cf app \"${config.cloudFoundry.appName}-old\"", returnStatus: true
if (retVal == 0) {
sh "cf delete \"${config.cloudFoundry.appName}-old\" -r -f"
}
sh "cf logout"
}
}
def deployMta (config) {
if (config.mtaExtensionDescriptor == null) config.mtaExtensionDescriptor = ''
if (!config.mtaExtensionDescriptor.isEmpty() && !config.mtaExtensionDescriptor.startsWith('-e ')) config.mtaExtensionDescriptor = "-e ${config.mtaExtensionDescriptor}"
def deployCommand = 'deploy'
if (config.deployType == 'blue-green')
deployCommand = 'bg-deploy'
withCredentials([usernamePassword(
credentialsId: config.cloudFoundry.credentialsId,
passwordVariable: 'password',
usernameVariable: 'username'
)]) {
echo "[${STEP_NAME}] Deploying MTA (${config.mtaPath}) with following parameters: ${config.mtaExtensionDescriptor} ${config.mtaDeployParameters}"
sh """#!/bin/bash
export HOME=${config.dockerWorkspace}
set +x
cf api ${config.cloudFoundry.apiEndpoint}
cf login -u ${username} -p '${password}' -a ${config.cloudFoundry.apiEndpoint} -o \"${config.cloudFoundry.org}\" -s \"${config.cloudFoundry.space}\"
cf plugins
cf ${deployCommand} ${config.mtaPath} ${config.mtaDeployParameters} ${config.mtaExtensionDescriptor}"""
sh "cf logout"
}
}

View File

@ -67,7 +67,7 @@ def call(Map parameters = [:]) {
}
// Always use Maven's batch mode
if (!(command.contains('-B') || command.contains('--batch-mode'))){
if (!(command =~ /--batch-mode|-B(?=\s)|-B\\|-B$/)) {
command += ' --batch-mode'
}

View File

@ -1,5 +1,6 @@
import com.sap.piper.Utils
import com.sap.piper.ConfigurationHelper
import com.sap.piper.Utils
import groovy.transform.Field
import groovy.text.SimpleTemplateEngine
@ -7,10 +8,13 @@ import groovy.text.SimpleTemplateEngine
@Field Set STEP_CONFIG_KEYS = [
'dockerImage',
'failOnError',
'gitBranch',
'gitSshKeyCredentialsId',
'newmanCollection',
'newmanEnvironment',
'newmanGlobals',
'newmanRunCommand',
'stashContent',
'testRepository'
]
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
@ -18,36 +22,53 @@ import groovy.text.SimpleTemplateEngine
def call(Map parameters = [:]) {
handlePipelineStepErrors(stepName: STEP_NAME, stepParameters: parameters) {
def script = parameters?.script ?: [commonPipelineEnvironment: commonPipelineEnvironment]
def utils = parameters?.juStabUtils ?: new Utils()
// load default & individual configuration
Map config = ConfigurationHelper
.loadStepDefaults(this)
.mixinGeneralConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, STEP_CONFIG_KEYS)
.mixin(parameters, PARAMETER_KEYS)
.use()
List collectionList = findFiles(glob: config.newmanCollection)?.toList()
new Utils().pushToSWA([step: STEP_NAME], config)
if (!config.dockerImage.isEmpty()) {
if (config.testRepository)
git config.testRepository
dockerExecute(
dockerImage: config.dockerImage
) {
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]),
collectionDisplayName: collectionDisplayName
]).toString()
if(!config.failOnError) command += ' --suppress-exit-code'
sh "newman ${command}"
}
if (config.testRepository) {
def gitParameters = [url: config.testRepository]
if (config.gitSshKeyCredentialsId) gitParameters.credentialsId = config.gitSshKeyCredentialsId
if (config.gitBranch) gitParameters.branch = config.gitBranch
git gitParameters
stash 'newmanContent'
config.stashContent = ['newmanContent']
} else {
config.stashContent = utils.unstashAll(config.stashContent)
}
List collectionList = findFiles(glob: config.newmanCollection)?.toList()
if (collectionList.isEmpty()) {
error "[${STEP_NAME}] No collection found with pattern '${config.newmanCollection}'"
} else {
echo "[${STEP_NAME}] Found files ${collectionList}"
}
dockerExecute(
dockerImage: config.dockerImage,
stashContent: config.stashContent
) {
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]),
collectionDisplayName: collectionDisplayName
]).toString()
if(!config.failOnError) command += ' --suppress-exit-code'
sh "newman ${command}"
}
}
}

View File

@ -31,6 +31,8 @@ def call(Map parameters = [:]) {
.mixin(parameters, PARAMETER_KEYS)
.use()
new Utils().pushToSWA([step: STEP_NAME], config)
// store files to be checked with checkmarx
if (config.runCheckmarx) {
utils.stash(

View File

@ -30,6 +30,8 @@ def call(Map parameters = [:]) {
.mixin(parameters, PARAMETER_KEYS)
.use()
new Utils().pushToSWA([step: STEP_NAME], config)
if (config.runOpaTests){
utils.stash('opa5', config.stashIncludes?.get('opa5')?config.stashIncludes.opa5:'**/*.*', config.stashExcludes?.get('opa5')?config.stashExcludes.opa5:'')
}

View File

@ -1,6 +1,13 @@
import com.sap.piper.ConfigurationHelper
import com.sap.piper.Utils
import groovy.transform.Field
@Field String STEP_NAME = 'setupCommonPipelineEnvironment'
@Field Set GENERAL_CONFIG_KEYS = ['collectTelemetryData']
def call(Map parameters = [:]) {
handlePipelineStepErrors (stepName: 'setupCommonPipelineEnvironment', stepParameters: parameters) {
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) {
def script = parameters.script
@ -9,6 +16,13 @@ def call(Map parameters = [:]) {
String configFile = parameters.get('configFile')
loadConfigurationFromFile(script, configFile)
Map config = ConfigurationHelper
.loadStepDefaults(this)
.mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS)
.use()
new Utils().pushToSWA([step: STEP_NAME, stepParam4: parameters.customDefaults?'true':'false'], config)
}
}

View File

@ -35,6 +35,8 @@ def call(Map parameters = [:]) {
.withMandatoryProperty('snykCredentialsId')
.use()
new Utils().pushToSWA([step: STEP_NAME], config)
utils.unstashAll(config.stashContent)
switch(config.scanType) {

View File

@ -3,7 +3,7 @@ import com.cloudbees.groovy.cps.NonCPS
import com.sap.piper.ConfigurationHelper
import com.sap.piper.ConfigurationMerger
import com.sap.piper.MapUtils
import com.sap.piper.Utils
import groovy.transform.Field
@Field List TOOLS = [
@ -30,10 +30,13 @@ def call(Map parameters = [:]) {
// load default & individual configuration
Map configuration = ConfigurationHelper
.loadStepDefaults(this)
.mixinGeneralConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixin(parameters, PARAMETER_KEYS)
.use()
new Utils().pushToSWA([step: STEP_NAME], configuration)
// UNIT TESTS
publishJUnitReport(configuration.get('junit'))
// CODE COVERAGE

View File

@ -1,4 +1,5 @@
import com.sap.piper.GitUtils
import com.sap.piper.Utils
import groovy.transform.Field
import com.sap.piper.ConfigurationHelper
@ -12,16 +13,11 @@ import hudson.AbortException
@Field def STEP_NAME = 'transportRequestCreate'
@Field Set stepConfigurationKeys = [
'credentialsId',
'clientOpts',
'endpoint',
'gitFrom',
'gitTo',
'gitChangeDocumentLabel',
'gitFormat'
'changeManagement',
'developmentSystemId'
]
@Field Set parameterKeys = stepConfigurationKeys.plus(['changeDocumentId', 'developmentSystemId'])
@Field Set parameterKeys = stepConfigurationKeys.plus(['changeDocumentId'])
@Field generalConfigurationKeys = stepConfigurationKeys
@ -39,11 +35,18 @@ def call(parameters = [:]) {
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, stepConfigurationKeys)
.mixinStepConfig(script.commonPipelineEnvironment, stepConfigurationKeys)
.mixin(parameters, parameterKeys)
.withMandatoryProperty('endpoint')
.withMandatoryProperty('changeManagement/clientOpts')
.withMandatoryProperty('changeManagement/credentialsId')
.withMandatoryProperty('changeManagement/endpoint')
.withMandatoryProperty('changeManagement/git/from')
.withMandatoryProperty('changeManagement/git/to')
.withMandatoryProperty('changeManagement/git/format')
.withMandatoryProperty('developmentSystemId')
Map configuration = configHelper.use()
new Utils().pushToSWA([step: STEP_NAME], configuration)
def changeDocumentId = configuration.changeDocumentId
if(changeDocumentId?.trim()) {
@ -52,15 +55,16 @@ def call(parameters = [:]) {
} else {
echo "[INFO] Retrieving ChangeDocumentId from commit history [from: ${configuration.gitFrom}, to: ${configuration.gitTo}]." +
"Searching for pattern '${configuration.gitChangeDocumentLabel}'. Searching with format '${configuration.gitFormat}'."
echo "[INFO] Retrieving ChangeDocumentId from commit history [from: ${configuration.changeManagement.git.from}, to: ${configuration.changeManagement.git.to}]." +
"Searching for pattern '${configuration.changeDocumentLabel}'. Searching with format '${configuration.changeManagement.git.format}'."
try {
changeDocumentId = cm.getChangeDocumentId(
configuration.gitFrom,
configuration.gitTo,
configuration.gitChangeDocumentLabel,
configuration.gitFormat
configuration.changeManagement.git.from,
configuration.changeManagement.git.to,
configuration.changeManagement.changeDocumentLabel,
configuration.changeManagement.git.format
)
echo "[INFO] ChangeDocumentId '${changeDocumentId}' retrieved from commit history"
@ -78,22 +82,16 @@ def call(parameters = [:]) {
echo "[INFO] Creating transport request for change document '${configuration.changeDocumentId}' and development system '${configuration.developmentSystemId}'."
withCredentials([usernamePassword(
credentialsId: configuration.credentialsId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
try {
transportRequestId = cm.createTransportRequest(configuration.changeDocumentId,
configuration.developmentSystemId,
configuration.endpoint,
username,
password,
configuration.clientOpts)
configuration.changeManagement.endpoint,
configuration.changeManagement.credentialsId,
configuration.changeManagement.clientOpts)
} catch(ChangeManagementException ex) {
throw new AbortException(ex.getMessage())
}
}
echo "[INFO] Transport Request '$transportRequestId' has been successfully created."
return transportRequestId

View File

@ -1,4 +1,5 @@
import com.sap.piper.GitUtils
import com.sap.piper.Utils
import groovy.transform.Field
import com.sap.piper.ConfigurationHelper
@ -12,14 +13,7 @@ import hudson.AbortException
@Field def STEP_NAME = 'transportRequestRelease'
@Field Set stepConfigurationKeys = [
'credentialsId',
'cmClientOpts',
'endpoint',
'gitChangeDocumentLabel',
'gitFrom',
'gitTo',
'gitTransportRequestLabel',
'gitFormat'
'changeManagement'
]
@Field Set parameterKeys = stepConfigurationKeys.plus([
@ -43,11 +37,17 @@ def call(parameters = [:]) {
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, stepConfigurationKeys)
.mixinStepConfig(script.commonPipelineEnvironment, stepConfigurationKeys)
.mixin(parameters, parameterKeys)
.withMandatoryProperty('changeDocumentId')
.withMandatoryProperty('endpoint')
.withMandatoryProperty('changeManagement/clientOpts')
.withMandatoryProperty('changeManagement/credentialsId')
.withMandatoryProperty('changeManagement/endpoint')
.withMandatoryProperty('changeManagement/git/to')
.withMandatoryProperty('changeManagement/git/from')
.withMandatoryProperty('changeManagement/git/format')
Map configuration = configHelper.use()
new Utils().pushToSWA([step: STEP_NAME], configuration)
def transportRequestId = configuration.transportRequestId
if(transportRequestId?.trim()) {
@ -56,15 +56,15 @@ def call(parameters = [:]) {
} else {
echo "[INFO] Retrieving transport request id from commit history [from: ${configuration.gitFrom}, to: ${configuration.gitTo}]." +
" Searching for pattern '${configuration.gitTransportRequestLabel}'. Searching with format '${configuration.gitFormat}'."
echo "[INFO] Retrieving transport request id from commit history [from: ${configuration.changeManagement.git.from}, to: ${configuration.changeManagement.git.to}]." +
" Searching for pattern '${configuration.gitTransportRequestLabel}'. Searching with format '${configuration.changeManagement.git.format}'."
try {
transportRequestId = cm.getTransportRequestId(
configuration.gitFrom,
configuration.gitTo,
configuration.gitTransportRequestLabel,
configuration.gitFormat
configuration.changeManagement.git.from,
configuration.changeManagement.git.to,
configuration.changeManagement.transportRequestLabel,
configuration.changeManagement.git.format
)
echo "[INFO] Transport request id '${transportRequestId}' retrieved from commit history"
@ -82,15 +82,15 @@ def call(parameters = [:]) {
} else {
echo "[INFO] Retrieving ChangeDocumentId from commit history [from: ${configuration.gitFrom}, to: ${configuration.gitTo}]." +
"Searching for pattern '${configuration.gitChangeDocumentLabel}'. Searching with format '${configuration.gitFormat}'."
echo "[INFO] Retrieving ChangeDocumentId from commit history [from: ${configuration.changeManagement.git.from}, to: ${configuration.changeManagement.git.to}]." +
"Searching for pattern '${configuration.changeDocumentLabel}'. Searching with format '${configuration.changeManagement.git.format}'."
try {
changeDocumentId = cm.getChangeDocumentId(
configuration.gitFrom,
configuration.gitTo,
configuration.gitChangeDocumentLabel,
configuration.gitFormat
configuration.changeManagement.git.from,
configuration.changeManagement.git.to,
configuration.changeManagement.changeDocumentLabel,
configuration.changeManagement.gitformat
)
echo "[INFO] ChangeDocumentId '${changeDocumentId}' retrieved from commit history"
@ -111,22 +111,17 @@ def call(parameters = [:]) {
echo "[INFO] Closing transport request '${configuration.transportRequestId}' for change document '${configuration.changeDocumentId}'."
withCredentials([usernamePassword(
credentialsId: configuration.credentialsId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
try {
cm.releaseTransportRequest(configuration.changeDocumentId,
configuration.transportRequestId,
configuration.endpoint,
username,
password,
configuration.cmClientOpts)
configuration.changeManagement.endpoint,
configuration.changeManagement.credentialsId,
configuration.changeManagement.clientOpts)
} catch(ChangeManagementException ex) {
throw new AbortException(ex.getMessage())
}
}
echo "[INFO] Transport Request '${configuration.transportRequestId}' has been successfully closed."
}

View File

@ -1,4 +1,5 @@
import com.sap.piper.GitUtils
import com.sap.piper.Utils
import groovy.transform.Field
import com.sap.piper.ConfigurationHelper
@ -12,14 +13,7 @@ import hudson.AbortException
@Field def STEP_NAME = 'transportRequestUploadFile'
@Field Set generalConfigurationKeys = [
'credentialsId',
'cmClientOpts',
'endpoint',
'gitFrom',
'gitTo',
'gitChangeDocumentLabel',
'gitTransportRequestLabel',
'gitFormat'
'changeManagement',
]
@Field Set parameterKeys = generalConfigurationKeys.plus([
@ -44,12 +38,21 @@ def call(parameters = [:]) {
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, stepConfigurationKeys)
.mixinStepConfig(script.commonPipelineEnvironment, stepConfigurationKeys)
.mixin(parameters, parameterKeys)
.withMandatoryProperty('endpoint')
.addIfEmpty('filePath', script.commonPipelineEnvironment.getMtarFilePath())
.withMandatoryProperty('applicationId')
.withMandatoryProperty('changeManagement/changeDocumentLabel')
.withMandatoryProperty('changeManagement/clientOpts')
.withMandatoryProperty('changeManagement/credentialsId')
.withMandatoryProperty('changeManagement/endpoint')
.withMandatoryProperty('changeManagement/git/from')
.withMandatoryProperty('changeManagement/git/to')
.withMandatoryProperty('changeManagement/git/format')
.withMandatoryProperty('filePath')
Map configuration = configHelper.use()
new Utils().pushToSWA([step: STEP_NAME], configuration)
def changeDocumentId = configuration.changeDocumentId
if(changeDocumentId?.trim()) {
@ -58,15 +61,15 @@ def call(parameters = [:]) {
} else {
echo "[INFO] Retrieving ChangeDocumentId from commit history [from: ${configuration.gitFrom}, to: ${configuration.gitTo}]." +
"Searching for pattern '${configuration.gitChangeDocumentLabel}'. Searching with format '${configuration.gitFormat}'."
echo "[INFO] Retrieving ChangeDocumentId from commit history [from: ${configuration.changeManagement.git.from}, to: ${configuration.changeManagement.git.to}]." +
"Searching for pattern '${configuration.changeManagement.changeDocumentLabel}'. Searching with format '${configuration.changeManagement.git.format}'."
try {
changeDocumentId = cm.getChangeDocumentId(
configuration.gitFrom,
configuration.gitTo,
configuration.gitChangeDocumentLabel,
configuration.gitFormat
configuration.changeManagement.git.from,
configuration.changeManagement.git.to,
configuration.changeManagement.changeDocumentLabel,
configuration.changeManagement.git.format
)
echo "[INFO] ChangeDocumentId '${changeDocumentId}' retrieved from commit history"
@ -84,15 +87,15 @@ def call(parameters = [:]) {
} else {
echo "[INFO] Retrieving transport request id from commit history [from: ${configuration.gitFrom}, to: ${configuration.gitTo}]." +
" Searching for pattern '${configuration.gitTransportRequestLabel}'. Searching with format '${configuration.gitFormat}'."
echo "[INFO] Retrieving transport request id from commit history [from: ${configuration.changeManagement.git.from}, to: ${configuration.changeManagement.git.to}]." +
" Searching for pattern '${configuration.changeManagement.transportRequestLabel}'. Searching with format '${configuration.changeManagement.git.format}'."
try {
transportRequestId = cm.getTransportRequestId(
configuration.gitFrom,
configuration.gitTo,
configuration.gitTransportRequestLabel,
configuration.gitFormat
configuration.changeManagement.git.from,
configuration.changeManagement.git.to,
configuration.changeManagement.transportRequestLabel,
configuration.changeManagement.git.format
)
echo "[INFO] Transport request id '${transportRequestId}' retrieved from commit history"
@ -113,24 +116,21 @@ def call(parameters = [:]) {
echo "[INFO] Uploading file '${configuration.filePath}' to transport request '${configuration.transportRequestId}' of change document '${configuration.changeDocumentId}'."
withCredentials([usernamePassword(
credentialsId: configuration.credentialsId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
try {
cm.uploadFileToTransportRequest(configuration.changeDocumentId,
configuration.transportRequestId,
configuration.applicationId,
configuration.filePath,
configuration.endpoint,
username,
password,
configuration.cmClientOpts)
configuration.changeManagement.endpoint,
configuration.changeManagement.credentialsId,
configuration.changeManagement.clientOpts)
} catch(ChangeManagementException ex) {
throw new AbortException(ex.getMessage())
}
}
echo "[INFO] File '${configuration.filePath}' has been successfully uploaded to transport request '${configuration.transportRequestId}' of change document '${configuration.changeDocumentId}'."
}