mirror of
https://github.com/SAP/jenkins-library.git
synced 2026-06-19 22:58:55 +02:00
Merge remote-tracking branch 'github/master' into HEAD
This commit is contained in:
@@ -1,37 +1,10 @@
|
||||
# durationMeasure
|
||||
# ${docGenStepName}
|
||||
|
||||
## Description
|
||||
## ${docGenDescription}
|
||||
|
||||
This step is used to measure the duration of a set of steps, e.g. a certain stage.
|
||||
The duration is stored in a Map. The measurement data can then be written to an Influx database using step [influxWriteData](influxWriteData.md).
|
||||
## ${docGenParameters}
|
||||
|
||||
!!! tip
|
||||
Measuring for example the duration of pipeline stages helps to identify potential bottlenecks within the deployment pipeline.
|
||||
This then helps to counter identified issues with respective optimization measures, e.g parallelization of tests.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
none
|
||||
|
||||
## Pipeline configuration
|
||||
|
||||
none
|
||||
|
||||
## Parameters
|
||||
|
||||
| parameter | mandatory | default | possible values |
|
||||
| ----------|-----------|---------|-----------------|
|
||||
| script | yes | | |
|
||||
| measurementName | no | test_duration | |
|
||||
|
||||
Details:
|
||||
|
||||
* `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 storing the measured duration.
|
||||
* `measurementName` defines the name of the measurement which is written to the Influx database.
|
||||
|
||||
## Step configuration
|
||||
|
||||
none
|
||||
## ${docGenConfiguration}
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
@@ -1,58 +1,14 @@
|
||||
# handlePipelineStepErrors
|
||||
# ${docGenStepName}
|
||||
|
||||
## Description
|
||||
|
||||
Used by other steps to make error analysis easier. Lists parameters and other data available to the step in which the error occurs.
|
||||
## ${docGenDescription}
|
||||
|
||||
## Prerequisites
|
||||
|
||||
none
|
||||
|
||||
## Parameters
|
||||
## ${docGenParameters}
|
||||
|
||||
| parameter | mandatory | default | possible values |
|
||||
| -----------------|-----------|---------|-----------------|
|
||||
| `stepParameters` | yes | | |
|
||||
| `stepName` | yes | | |
|
||||
| `echoDetails` | yes | true | true, false |
|
||||
|
||||
* `stepParameters` - The parameters from the step to be executed. The list of parameters is then shown in the console output.
|
||||
* `stepName` - The name of the step executed to be shown in the console output.
|
||||
* `echoDetails` - If set to true the following will be output to the console:
|
||||
1. Step beginning: `--- Begin library step: ${stepName}.groovy ---`
|
||||
2. Step end: `--- End library step: ${stepName}.groovy ---`
|
||||
3. Step errors:
|
||||
|
||||
```log
|
||||
----------------------------------------------------------
|
||||
--- An error occurred in the library step: ${stepName}
|
||||
----------------------------------------------------------
|
||||
The following parameters were available to the step:
|
||||
***
|
||||
${stepParameters}
|
||||
***
|
||||
The error was:
|
||||
***
|
||||
${err}
|
||||
***
|
||||
Further information:
|
||||
* Documentation of step ${stepName}: .../${stepName}/
|
||||
* Pipeline documentation: https://...
|
||||
* GitHub repository for pipeline steps: https://...
|
||||
----------------------------------------------------------
|
||||
```
|
||||
|
||||
## Step configuration
|
||||
|
||||
none
|
||||
|
||||
## Side effects
|
||||
|
||||
none
|
||||
|
||||
## Exceptions
|
||||
|
||||
none
|
||||
## ${docGenConfiguration}
|
||||
|
||||
## Example
|
||||
|
||||
@@ -61,6 +17,33 @@ handlePipelineStepErrors (stepName: 'executeHealthCheck', stepParameters: parame
|
||||
def url = new Utils().getMandatoryParameter(parameters, 'url', null)
|
||||
def statusCode = curl(url)
|
||||
if (statusCode != '200')
|
||||
error "Health Check failed: ${statusCode}"
|
||||
error "Health Check failed: \${statusCode}"
|
||||
}
|
||||
```
|
||||
|
||||
## Example console output
|
||||
|
||||
If `echoDetails` is set to true the following information will be output to the console:
|
||||
|
||||
1. Step beginning: `--- Begin library step: ${stepName}.groovy ---`
|
||||
1. Step end: `--- End library step: ${stepName}.groovy ---`
|
||||
1. Step errors:
|
||||
|
||||
```log
|
||||
----------------------------------------------------------
|
||||
--- An error occurred in the library step: ${stepName}
|
||||
----------------------------------------------------------
|
||||
The following parameters were available to the step:
|
||||
***
|
||||
\${stepParameters}
|
||||
***
|
||||
The error was:
|
||||
***
|
||||
\${err}
|
||||
***
|
||||
Further information:
|
||||
* Documentation of step \${stepName}: .../\${stepName}/
|
||||
* Pipeline documentation: https://...
|
||||
* GitHub repository for pipeline steps: https://...
|
||||
----------------------------------------------------------
|
||||
```
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
# healthExecuteCheck
|
||||
# ${docGenStepName}
|
||||
|
||||
## Description
|
||||
|
||||
Calls the health endpoint url of the application.
|
||||
|
||||
The intention of the check is to verify that a suitable health endpoint is available. Such a health endpoint is required for operation purposes.
|
||||
|
||||
This check is used as a real-life test for your productive health endpoints.
|
||||
|
||||
!!! note "Check Depth"
|
||||
Typically, tools performing simple health checks are not too smart. Therefore it is important to choose an endpoint for checking wisely.
|
||||
|
||||
This check therefore only checks if the application/service url returns `HTTP 200`.
|
||||
|
||||
This is in line with health check capabilities of platforms which are used for example in load balancing scenarios. Here you can find an [example for Amazon AWS](http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-healthchecks.html).
|
||||
## ${docGenDescription}
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -25,6 +12,10 @@ Endpoint for health check is configured.
|
||||
!!! tip
|
||||
If using Spring Boot framework, ideally the provided `/health` endpoint is used and extended by development. Further information can be found in the [Spring Boot documenation for Endpoints](http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html)
|
||||
|
||||
## ${docGenParameters}
|
||||
|
||||
## ${docGenConfiguration}
|
||||
|
||||
## Example
|
||||
|
||||
Pipeline step:
|
||||
@@ -32,29 +23,3 @@ Pipeline step:
|
||||
```groovy
|
||||
healthExecuteCheck testServerUrl: 'https://testserver.com'
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| parameter | mandatory | default | possible values |
|
||||
| ----------|-----------|---------|-----------------|
|
||||
|script|yes|||
|
||||
|healthEndpoint|no|``||
|
||||
|testServerUrl|no|||
|
||||
|
||||
Details:
|
||||
|
||||
* `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 storing the measured duration.
|
||||
* Health check function is called providing full qualified `testServerUrl` (and optionally with `healthEndpoint` if endpoint is not the standard url) to the health check.
|
||||
* In case response of the call is different than `HTTP 200 OK` the **health check fails and the pipeline stops**.
|
||||
|
||||
## Step configuration
|
||||
|
||||
We recommend to define values of step parameters via [config.yml file](../configuration.md).
|
||||
|
||||
In following sections the configuration is possible:
|
||||
|
||||
| parameter | general | step | stage |
|
||||
| ----------|-----------|---------|-----------------|
|
||||
|script||||
|
||||
|healthEndpoint|X|X|X|
|
||||
|testServerUrl|X|X|X|
|
||||
|
||||
@@ -1,47 +1,10 @@
|
||||
# mavenExecute
|
||||
# ${docGenStepName}
|
||||
|
||||
## Description
|
||||
## ${docGenDescription}
|
||||
|
||||
Executes a maven command inside a Docker container.
|
||||
## ${docGenParameters}
|
||||
|
||||
## Parameters
|
||||
|
||||
| parameter | mandatory | default | example values |
|
||||
| -------------------------------|-----------|-------------------|----------------------------|
|
||||
| `script` | yes | | |
|
||||
| `dockerImage` | no | 'maven:3.5-jdk-7' | |
|
||||
| `globalSettingsFile` | no | | 'local_folder/settings.xml'|
|
||||
| `projectSettingsFile` | no | | |
|
||||
| `pomPath` | no | | 'local_folder/m2' |
|
||||
| `flags` | no | | '-o' |
|
||||
| `goals` | no | | 'clean install' |
|
||||
| `m2Path` | no | | 'local_folder/m2' |
|
||||
| `defines` | no | | '-Dmaven.tests.skip=true' |
|
||||
| `logSuccessfulMavenTransfers` | no | `false` | 'true' |
|
||||
|
||||
* `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 for retrieving, for example,
|
||||
configuration parameters.
|
||||
* `dockerImage` Name of the docker image that should be used.
|
||||
* `globalSettingsFile` Path or url to the mvn settings file that should be used as global settings file.
|
||||
* `projectSettingsFile` Path or url to the mvn settings file that should be used as project settings file.
|
||||
* `pomPath` Path to the pom file that should be used.
|
||||
* `flags` Flags to provide when running mvn.
|
||||
* `goals` Maven goals that should be executed.
|
||||
* `m2Path` Path to the location of the local repository that should be used.
|
||||
* `defines` Additional properties.
|
||||
* `logSuccessfulMavenTransfers` configures maven to log successful downloads. This is set to `false` by default to reduce the noise in build logs.
|
||||
|
||||
## Step configuration
|
||||
|
||||
The following parameters can also be specified as step parameters using the global configuration file:
|
||||
|
||||
* `dockerImage`
|
||||
* `globalSettingsFile`
|
||||
* `projectSettingsFile`
|
||||
* `pomPath`
|
||||
* `m2Path`
|
||||
## ${docGenConfiguration}
|
||||
|
||||
## Exceptions
|
||||
|
||||
|
||||
@@ -1,44 +1,18 @@
|
||||
# mtaBuild
|
||||
# ${docGenStepName}
|
||||
|
||||
## Description
|
||||
## ${docGenDescription}
|
||||
|
||||
Executes the SAP Multitarget Application Archive Builder to create an mtar archive of the application.
|
||||
## Prerequisites
|
||||
|
||||
Before doing this, validates that SAP Multitarget Application Archive Builder exists and the version is compatible.
|
||||
While using a custom docker file, ensure that the following tools are installed:
|
||||
|
||||
Note that a version is formed by `major.minor.patch`, and a version is compatible to another version if the minor and patch versions are higher, but the major version is not, e.g. if 3.39.10 is the expected version, 3.39.11 and 3.40.1 would be compatible versions, but 4.0.1 would not be a compatible version.
|
||||
* **SAP MTA Archive Builder 1.0.6 or compatible version** - can be downloaded from [SAP Development Tools](https://tools.hana.ondemand.com/#cloud).
|
||||
* **Java 8 or compatible version** - necessary to run the *MTA Archive Builder* itself and to build Java modules.
|
||||
* **NodeJS installed** - the MTA Builder uses `npm` to download node module dependencies such as `grunt`.
|
||||
|
||||
## Parameters
|
||||
## ${docGenParameters}
|
||||
|
||||
| parameter | mandatory | default | possible values |
|
||||
| -----------------|-----------|--------------------------------------------------------|--------------------|
|
||||
| `script` | yes | | |
|
||||
| `dockerImage` | no | `ppiper/mta-archive-builder` | |
|
||||
| `dockerOptions` | no | '' | |
|
||||
| `buildTarget` | yes | `'NEO'` | 'CF', 'NEO', 'XSA' |
|
||||
| `extension` | no | | |
|
||||
| `mtaJarLocation` | no | `'/opt/sap/mta/lib/mta.jar'` | |
|
||||
| `applicationName`| no | | |
|
||||
|
||||
* `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.
|
||||
* `dockerImage` - The Docker image to execute the MTA build.
|
||||
Note that you can provide your own image if required, but for most cases, the default should be fine.
|
||||
* `dockerOptions` Docker options to be set when starting the container. It can be a list or a string.
|
||||
* `buildTarget` - The target platform to which the mtar can be deployed.
|
||||
* `extension` - The path to the extension descriptor file.
|
||||
* `mtaJarLocation` - The location of the SAP Multitarget Application Archive Builder jar file, including file name and extension. First, the location is retrieved from the environment variables using the environment variable `MTA_JAR_LOCATION`. If no environment variable is provided, the location is retrieved from the parameters, or the step configuration using the key `mtaJarLocation`. If SAP Multitarget Application Archive Builder is not found on one of the previous locations an AbortException is thrown.
|
||||
Note that the environment variable `MTA_JAR_LOCATION` has priority. In case that the script runs on multiple nodes, SAP Multitarget Application Archive Builder must be located on all the nodes, therefore the environment variable must be also configured on all the nodes.
|
||||
* `applicationName` - The name of the application which is being built. If the parameter has been provided and no `mta.yaml` exists, the `mta.yaml` will be automatically generated using this parameter and the information (`name` and `version`) from `package.json` before the actual build starts.
|
||||
|
||||
## Step configuration
|
||||
|
||||
The following parameters can also be specified as step parameters using the global configuration file:
|
||||
|
||||
* `dockerImage`
|
||||
* `buildTarget`
|
||||
* `extension`
|
||||
* `mtaJarLocation`
|
||||
* `applicationName`
|
||||
## ${docGenConfiguration}
|
||||
|
||||
## Side effects
|
||||
|
||||
@@ -47,7 +21,6 @@ The following parameters can also be specified as step parameters using the glob
|
||||
## Exceptions
|
||||
|
||||
* `AbortException`:
|
||||
* If SAP Multitarget Application Archive Builder is not found.
|
||||
* If there is an invalid `buildTarget`.
|
||||
* If there is no key `ID` inside the `mta.yaml` file.
|
||||
|
||||
|
||||
@@ -1,34 +1,14 @@
|
||||
# pipelineExecute
|
||||
# ${docGenStepName}
|
||||
|
||||
## Description
|
||||
|
||||
Loads a pipeline from a git repository. The idea is to set up a pipeline job in Jenkins that loads a minimal pipeline, which in turn loads the shared library and then uses this step to load the actual pipeline.
|
||||
|
||||
A centrally maintained pipeline script (Jenkinsfile) can be re-used by
|
||||
several projects using `pipelineExecute` as outlined in the example
|
||||
below.
|
||||
## ${docGenDescription}
|
||||
|
||||
## Prerequisites
|
||||
|
||||
none
|
||||
|
||||
## Parameters
|
||||
## ${docGenParameters}
|
||||
|
||||
| parameter | mandatory | default | possible values |
|
||||
| -------------------|-----------|-----------------|-----------------|
|
||||
| `repoUrl` | yes | | |
|
||||
| `branch` | no | 'master' | |
|
||||
| `path` | no | 'Jenkinsfile' | |
|
||||
| `credentialsId` | no | An empty String | |
|
||||
|
||||
* `repoUrl` The url to the git repository of the pipeline to be loaded.
|
||||
* `branch` The branch of the git repository from which the pipeline should be checked out.
|
||||
* `path` The path to the Jenkinsfile, inside the repository, to be loaded.
|
||||
* `credentialsId` The Jenkins credentials containing user and password needed to access a private git repository.
|
||||
|
||||
## Step configuration
|
||||
|
||||
none
|
||||
## ${docGenConfiguration}
|
||||
|
||||
## Side effects
|
||||
|
||||
|
||||
@@ -14,3 +14,75 @@ If you see an error like `fatal: Not a git repository (or any parent up to mount
|
||||
Please make sure to point parameter `testOptions` to your `conf.js` file like `testOptions: './path/to/my/tests/conf.js'`
|
||||
|
||||
## Examples
|
||||
|
||||
### Passing credentials from Jenkins
|
||||
|
||||
When running acceptance tests in a real environment, authentication will be enabled in most cases. UIVeri5 includes [features to automatically perform the login](https://github.com/SAP/ui5-uiveri5/blob/master/docs/config/authentication.md) with credentials in the `conf.js`. However, having credentials to the acceptance system stored in plain text is not an optimal solution.
|
||||
|
||||
Therefore, UIVeri5 allows templating to set parameters at runtime, as shown in the following example `conf.js`:
|
||||
|
||||
```js
|
||||
// Read environment variables
|
||||
const defaultParams = {
|
||||
url: process.env.TARGET_SERVER_URL,
|
||||
user: process.env.TEST_USER,
|
||||
pass: process.env.TEST_PASS
|
||||
};
|
||||
|
||||
// Resolve path to specs relative to the working directory
|
||||
const path = require('path');
|
||||
const specs = path.relative(process.cwd(), path.join(__dirname, '*.spec.js'));
|
||||
|
||||
// export UIVeri5 config
|
||||
exports.config = {
|
||||
profile: 'integration',
|
||||
baseUrl: '${params.url}',
|
||||
specs: specs,
|
||||
params: defaultParams, // can be overridden via cli `--params.<key>=<value>`
|
||||
auth: {
|
||||
// set up authorization for CF XSUAA
|
||||
'sapcloud-form': {
|
||||
user: '${params.user}',
|
||||
pass: '${params.pass}',
|
||||
userFieldSelector: 'input[name="username"]',
|
||||
passFieldSelector: 'input[name="password"]',
|
||||
logonButtonSelector: 'input[type="submit"]',
|
||||
redirectUrl: /cp.portal\/site/
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
While default values for `baseUrl`, `user` and `pass` are read from the environment, they can also be overridden when calling the CLI.
|
||||
|
||||
In a custom Pipeline, this is very simple: Just wrap the call to `uiVeri5ExecuteTests` in `withCredentials` (`TARGET_SERVER_URL` is read from `config.yml`):
|
||||
|
||||
```groovy
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: 'MY_ACCEPTANCE_CREDENTIALS',
|
||||
passwordVariable: 'password',
|
||||
usernameVariable: 'username'
|
||||
)]) {
|
||||
uiVeri5ExecuteTests script: this, testOptions: "./uiveri5/conf.js --params.user=${username} --params.pass=${password}"
|
||||
}
|
||||
```
|
||||
|
||||
In a Pipeline Template, a [Stage Exit](#) can be used to fetch the credentials and store them in the environment. As the environment is passed down to uiVeri5ExecuteTests, the variables will be present there. This is an example for the stage exit `.pipeline/extensions/Acceptance.groovy` where the `credentialsId` is read from the `config.yml`:
|
||||
|
||||
```groovy
|
||||
void call(Map params) {
|
||||
// read username and password from the credential store
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: params.config.acceptanceCredentialsId,
|
||||
passwordVariable: 'password',
|
||||
usernameVariable: 'username'
|
||||
)]) {
|
||||
// store the result in the environment variables for executeUIVeri5Test
|
||||
withEnv(["TEST_USER=${username}", "TEST_PASS=${password}"]) {
|
||||
//execute original stage as defined in the template
|
||||
params.originalStage()
|
||||
}
|
||||
}
|
||||
}
|
||||
return this
|
||||
```
|
||||
|
||||
@@ -221,8 +221,10 @@ steps:
|
||||
testOptions: 'specs'
|
||||
handlePipelineStepErrors:
|
||||
echoDetails: true
|
||||
failOnError: true
|
||||
libraryDocumentationUrl: 'https://sap.github.io/jenkins-library/'
|
||||
libraryRepositoryUrl: 'https://github.com/SAP/jenkins-library/'
|
||||
mandatorySteps: []
|
||||
healthExecuteCheck:
|
||||
healthEndpoint: ''
|
||||
influxWriteData:
|
||||
|
||||
@@ -26,7 +26,11 @@ class ConfigurationLoader implements Serializable {
|
||||
|
||||
@NonCPS
|
||||
static Map generalConfiguration(script){
|
||||
return script?.commonPipelineEnvironment?.configuration?.general ?: [:]
|
||||
try {
|
||||
return script?.commonPipelineEnvironment?.configuration?.general ?: [:]
|
||||
} catch (groovy.lang.MissingPropertyException mpe) {
|
||||
return [:]
|
||||
}
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
@@ -43,7 +47,12 @@ class ConfigurationLoader implements Serializable {
|
||||
private static Map loadConfiguration(script, String type, String entryName, ConfigurationType configType){
|
||||
switch (configType) {
|
||||
case ConfigurationType.CUSTOM_CONFIGURATION:
|
||||
return script?.commonPipelineEnvironment?.configuration?.get(type)?.get(entryName) ?: [:]
|
||||
try {
|
||||
return script?.commonPipelineEnvironment?.configuration?.get(type)?.get(entryName) ?: [:]
|
||||
} catch (groovy.lang.MissingPropertyException mpe) {
|
||||
return [:]
|
||||
}
|
||||
|
||||
case ConfigurationType.DEFAULT_CONFIGURATION:
|
||||
return DefaultValueCache.getInstance()?.getDefaultValues()?.get(type)?.get(entryName) ?: [:]
|
||||
default:
|
||||
|
||||
@@ -78,7 +78,7 @@ class ArtifactSetVersionTest extends BasePiperTest {
|
||||
return closure()
|
||||
})
|
||||
|
||||
shellRule.setReturnValue("date --universal +'%Y%m%d%H%M%S'", '20180101010203')
|
||||
shellRule.setReturnValue("date --utc +'%Y%m%d%H%M%S'", '20180101010203')
|
||||
shellRule.setReturnValue('git diff --quiet HEAD', 0)
|
||||
|
||||
helper.registerAllowedMethod('fileExists', [String.class], {true})
|
||||
|
||||
@@ -240,7 +240,7 @@ class DockerExecuteOnKubernetesTest extends BasePiperTest {
|
||||
],
|
||||
containerName: 'mavenexecute',
|
||||
containerPortMappings: [
|
||||
'selenium/standalone-chrome': [[containerPort: 4444, hostPort: 4444]]
|
||||
'selenium/standalone-chrome': [[containerPort: 4444]]
|
||||
],
|
||||
containerWorkspaces: [
|
||||
'selenium/standalone-chrome': ''
|
||||
@@ -263,8 +263,7 @@ class DockerExecuteOnKubernetesTest extends BasePiperTest {
|
||||
hasItem('maven:3.5-jdk-8-alpine'),
|
||||
hasItem('selenium/standalone-chrome'),
|
||||
))
|
||||
// assertThat(portList, is(null))
|
||||
assertThat(portList, hasItem([[name: 'selenium0', containerPort: 4444, hostPort: 4444]]))
|
||||
assertThat(portList, hasItem([[name: 'selenium0', containerPort: 4444]]))
|
||||
assertThat(containerCommands.size(), is(1))
|
||||
assertThat(envList, hasItem(hasItem(allOf(hasEntry('name', 'customEnvKey'), hasEntry ('value','customEnvValue')))))
|
||||
}
|
||||
|
||||
+60
@@ -1,4 +1,6 @@
|
||||
#!groovy
|
||||
import hudson.AbortException
|
||||
|
||||
import static org.hamcrest.Matchers.is
|
||||
import static org.hamcrest.Matchers.not
|
||||
import static org.hamcrest.Matchers.containsString
|
||||
@@ -81,4 +83,62 @@ class HandlePipelineStepErrorsTest extends BasePiperTest {
|
||||
assertThat(loggingRule.log, containsString('[something:anything]'))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHandleErrorsIgnoreFailure() {
|
||||
def errorOccured = false
|
||||
try {
|
||||
stepRule.step.handlePipelineStepErrors([
|
||||
stepName: 'test',
|
||||
stepParameters: [jenkinsUtilsStub: jenkinsUtils, script: nullScript],
|
||||
failOnError: false
|
||||
]) {
|
||||
throw new AbortException('TestError')
|
||||
}
|
||||
} catch (err) {
|
||||
errorOccured = true
|
||||
}
|
||||
assertThat(errorOccured, is(false))
|
||||
assertThat(nullScript.currentBuild.result, is('UNSTABLE'))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHandleErrorsIgnoreFailureBlacklist() {
|
||||
def errorOccured = false
|
||||
|
||||
//define blacklist in defaults
|
||||
helper.registerAllowedMethod("readYaml", [Map], { Map m ->
|
||||
return [steps: [handlePipelineStepErrors: [mandatorySteps: ['step1', 'test']]]]
|
||||
})
|
||||
|
||||
try {
|
||||
stepRule.step.handlePipelineStepErrors([
|
||||
stepName: 'test',
|
||||
stepParameters: [jenkinsUtilsStub: jenkinsUtils, script: nullScript],
|
||||
failOnError: false
|
||||
]) {
|
||||
throw new AbortException('TestError')
|
||||
}
|
||||
} catch (err) {
|
||||
errorOccured = true
|
||||
}
|
||||
assertThat(errorOccured, is(true))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHandleErrorsIgnoreFailureNoScript() {
|
||||
def errorOccured = false
|
||||
try {
|
||||
stepRule.step.handlePipelineStepErrors([
|
||||
stepName: 'test',
|
||||
stepParameters: [jenkinsUtilsStub: jenkinsUtils],
|
||||
failOnError: false
|
||||
]) {
|
||||
throw new AbortException('TestError')
|
||||
}
|
||||
} catch (err) {
|
||||
errorOccured = true
|
||||
}
|
||||
assertThat(errorOccured, is(false))
|
||||
}
|
||||
}
|
||||
@@ -135,5 +135,5 @@ def isAppContainer(config){
|
||||
}
|
||||
|
||||
def getTimestamp(pattern){
|
||||
return sh(returnStdout: true, script: "date --universal +'${pattern}'").trim()
|
||||
return sh(returnStdout: true, script: "date --utc +'${pattern}'").trim()
|
||||
}
|
||||
|
||||
@@ -72,6 +72,12 @@ import hudson.AbortException
|
||||
* Specifies a dedicated user home directory for the container which will be passed as value for environment variable `HOME`.
|
||||
*/
|
||||
'dockerWorkspace',
|
||||
/**
|
||||
* Kubernetes Security Context used for the pod.
|
||||
* Can be used to specify uid and fsGroup.
|
||||
* See: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
|
||||
*/
|
||||
'securityContext',
|
||||
/**
|
||||
* Specific stashes that should be considered for the step execution.
|
||||
*/
|
||||
@@ -83,13 +89,7 @@ import hudson.AbortException
|
||||
/**
|
||||
*
|
||||
*/
|
||||
'stashIncludes',
|
||||
/**
|
||||
* Kubernetes Security Context used for the pod.
|
||||
* Can be used to specify uid and fsGroup.
|
||||
* See: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
|
||||
*/
|
||||
'securityContext'
|
||||
'stashIncludes'
|
||||
])
|
||||
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS.minus([
|
||||
'stashIncludes',
|
||||
@@ -277,19 +277,15 @@ private List getContainerList(config) {
|
||||
}
|
||||
|
||||
if (config.containerPortMappings?.get(imageName)) {
|
||||
def portMapping = { m ->
|
||||
[
|
||||
name: m.name,
|
||||
containerPort: m.containerPort,
|
||||
hostPort: m.hostPort
|
||||
]
|
||||
}
|
||||
|
||||
def ports = []
|
||||
def portCounter = 0
|
||||
config.containerPortMappings.get(imageName).each {mapping ->
|
||||
mapping.name = "${containerName}${portCounter}".toString()
|
||||
ports.add(portMapping(mapping))
|
||||
def name = "${containerName}${portCounter}".toString()
|
||||
if(mapping.containerPort != mapping.hostPort) {
|
||||
echo ("[WARNING][${STEP_NAME}]: containerPort and hostPort are different for container '${containerName}'. "
|
||||
+ "The hostPort will be ignored.")
|
||||
}
|
||||
ports.add([name: name, containerPort: mapping.containerPort])
|
||||
portCounter ++
|
||||
}
|
||||
containerSpec.ports = ports
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
import com.sap.piper.GenerateDocumentation
|
||||
import static com.sap.piper.Prerequisites.checkScript
|
||||
import groovy.transform.Field
|
||||
|
||||
@Field STEP_NAME = getClass().getName()
|
||||
|
||||
@Field Set PARAMETER_KEYS = [
|
||||
/** Defines the name of the measurement which is written to the Influx database.*/
|
||||
'measurementName'
|
||||
]
|
||||
|
||||
/**
|
||||
* This step is used to measure the duration of a set of steps, e.g. a certain stage.
|
||||
* The duration is stored in a Map. The measurement data can then be written to an Influx database using step [influxWriteData](influxWriteData.md).
|
||||
*
|
||||
* !!! tip
|
||||
* Measuring for example the duration of pipeline stages helps to identify potential bottlenecks within the deployment pipeline.
|
||||
* This then helps to counter identified issues with respective optimization measures, e.g parallelization of tests.
|
||||
*/
|
||||
@GenerateDocumentation
|
||||
def call(Map parameters = [:], body) {
|
||||
|
||||
def script = checkScript(this, parameters)
|
||||
|
||||
@@ -1,27 +1,54 @@
|
||||
import com.cloudbees.groovy.cps.NonCPS
|
||||
|
||||
import com.sap.piper.GenerateDocumentation
|
||||
import com.sap.piper.ConfigurationHelper
|
||||
|
||||
import groovy.text.SimpleTemplateEngine
|
||||
import groovy.transform.Field
|
||||
import hudson.AbortException
|
||||
|
||||
@Field STEP_NAME = getClass().getName()
|
||||
|
||||
@Field Set GENERAL_CONFIG_KEYS = []
|
||||
@Field Set STEP_CONFIG_KEYS = []
|
||||
@Field Set PARAMETER_KEYS = [
|
||||
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus([
|
||||
/**
|
||||
* Defines the behavior, in case an error occurs which is handled by this step. When set to `false` an error results in an "UNSTABLE" build result and the pipeline can continue.
|
||||
* @possibleValues `true`, `false`
|
||||
*/
|
||||
'failOnError',
|
||||
/** Defines a list of mandatory steps (step names) which have to be successful (=stop the pipeline), even if `failOnError: false` */
|
||||
'mandatorySteps'
|
||||
])
|
||||
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS.plus([
|
||||
/**
|
||||
* If it is set to true details will be output to the console. See example below.
|
||||
* @possibleValues `true`, `false`
|
||||
*/
|
||||
'echoDetails',
|
||||
/** Defines the url of the library's documentation that will be used to generate the corresponding links to the step documentation.*/
|
||||
'libraryDocumentationUrl',
|
||||
/** Defines the url of the library's repository that will be used to generate the corresponding links to the step implementation.*/
|
||||
'libraryRepositoryUrl',
|
||||
/** Defines the name of the step for which the error handling is active. It will be shown in the console log.*/
|
||||
'stepName',
|
||||
/** Defines the documented step, in case the documentation reference should point to a different step. */
|
||||
'stepNameDoc',
|
||||
/** Passes the parameters of the step which uses the error handling onto the error handling. The list of parameters is then shown in the console output.*/
|
||||
'stepParameters'
|
||||
]
|
||||
])
|
||||
|
||||
/**
|
||||
* Used by other steps to make error analysis easier. Lists parameters and other data available to the step in which the error occurs.
|
||||
*/
|
||||
@GenerateDocumentation
|
||||
void call(Map parameters = [:], body) {
|
||||
// load default & individual configuration
|
||||
def cpe = parameters.stepParameters?.script?.commonPipelineEnvironment ?: commonPipelineEnvironment
|
||||
Map config = ConfigurationHelper.newInstance(this)
|
||||
.loadStepDefaults()
|
||||
.mixinGeneralConfig(cpe, GENERAL_CONFIG_KEYS)
|
||||
.mixinStepConfig(cpe, STEP_CONFIG_KEYS)
|
||||
.mixinStageConfig(cpe, parameters.stepParameters?.stageName?:env.STAGE_NAME, STEP_CONFIG_KEYS)
|
||||
.mixin(parameters, PARAMETER_KEYS)
|
||||
.withMandatoryProperty('stepParameters')
|
||||
.withMandatoryProperty('stepName')
|
||||
@@ -34,6 +61,19 @@ void call(Map parameters = [:], body) {
|
||||
echo "--- Begin library step of: ${config.stepName} ---"
|
||||
|
||||
body()
|
||||
} catch (AbortException ae) {
|
||||
if (config.echoDetails)
|
||||
message += formatErrorMessage(config, ae)
|
||||
writeErrorToInfluxData(config, ae)
|
||||
if (config.failOnError || config.stepName in config.mandatorySteps) {
|
||||
throw ae
|
||||
}
|
||||
if (config.stepParameters?.script) {
|
||||
config.stepParameters?.script.currentBuild.result = 'UNSTABLE'
|
||||
} else {
|
||||
currentBuild.result = 'UNSTABLE'
|
||||
}
|
||||
|
||||
} catch (Throwable error) {
|
||||
if (config.echoDetails)
|
||||
message += formatErrorMessage(config, error)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import static com.sap.piper.Prerequisites.checkScript
|
||||
|
||||
import com.sap.piper.GenerateDocumentation
|
||||
import com.sap.piper.ConfigurationHelper
|
||||
import com.sap.piper.Utils
|
||||
import groovy.transform.Field
|
||||
@@ -9,12 +10,32 @@ import groovy.transform.Field
|
||||
@Field Set GENERAL_CONFIG_KEYS = STEP_CONFIG_KEYS
|
||||
|
||||
@Field Set STEP_CONFIG_KEYS = [
|
||||
/** Optionally with `healthEndpoint` the health function is called if endpoint is not the standard url.*/
|
||||
'healthEndpoint',
|
||||
/**
|
||||
* Health check function is called providing full qualified `testServerUrl` to the health check.
|
||||
*
|
||||
*/
|
||||
'testServerUrl'
|
||||
]
|
||||
|
||||
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
|
||||
|
||||
/**
|
||||
* Calls the health endpoint url of the application.
|
||||
*
|
||||
* The intention of the check is to verify that a suitable health endpoint is available. Such a health endpoint is required for operation purposes.
|
||||
*
|
||||
* This check is used as a real-life test for your productive health endpoints.
|
||||
*
|
||||
* !!! note "Check Depth"
|
||||
* Typically, tools performing simple health checks are not too smart. Therefore it is important to choose an endpoint for checking wisely.
|
||||
*
|
||||
* This check therefore only checks if the application/service url returns `HTTP 200`.
|
||||
*
|
||||
* This is in line with health check capabilities of platforms which are used for example in load balancing scenarios. Here you can find an [example for Amazon AWS](http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-healthchecks.html).
|
||||
*/
|
||||
@GenerateDocumentation
|
||||
void call(Map parameters = [:]) {
|
||||
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) {
|
||||
def script = checkScript(this, parameters) ?: this
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import static com.sap.piper.Prerequisites.checkScript
|
||||
|
||||
import com.sap.piper.GenerateDocumentation
|
||||
import com.sap.piper.ConfigurationHelper
|
||||
import com.sap.piper.Utils
|
||||
|
||||
@@ -9,20 +10,37 @@ import groovy.transform.Field
|
||||
|
||||
@Field Set GENERAL_CONFIG_KEYS = []
|
||||
@Field Set STEP_CONFIG_KEYS = [
|
||||
/** @see dockerExecute */
|
||||
'dockerImage',
|
||||
/** Path or url to the mvn settings file that should be used as global settings file.*/
|
||||
'globalSettingsFile',
|
||||
/** Path or url to the mvn settings file that should be used as project settings file.*/
|
||||
'projectSettingsFile',
|
||||
/** Path to the pom file that should be used.*/
|
||||
'pomPath',
|
||||
/** Path to the location of the local repository that should be used.*/
|
||||
'm2Path'
|
||||
]
|
||||
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS.plus([
|
||||
/** @see dockerExecute */
|
||||
'dockerOptions',
|
||||
/** Flags to provide when running mvn.*/
|
||||
'flags',
|
||||
/** Maven goals that should be executed.*/
|
||||
'goals',
|
||||
/** Additional properties.*/
|
||||
'defines',
|
||||
/**
|
||||
* Configures maven to log successful downloads. This is set to `false` by default to reduce the noise in build logs.
|
||||
* @possibleValues `true`, `false`
|
||||
*/
|
||||
'logSuccessfulMavenTransfers'
|
||||
])
|
||||
|
||||
/**
|
||||
* Executes a maven command inside a Docker container.
|
||||
*/
|
||||
@GenerateDocumentation
|
||||
void call(Map parameters = [:]) {
|
||||
handlePipelineStepErrors(stepName: STEP_NAME, stepParameters: parameters) {
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import static com.sap.piper.Prerequisites.checkScript
|
||||
|
||||
import com.sap.piper.GenerateDocumentation
|
||||
import com.sap.piper.ConfigurationHelper
|
||||
import com.sap.piper.MtaUtils
|
||||
import com.sap.piper.Utils
|
||||
@@ -10,16 +11,32 @@ import groovy.transform.Field
|
||||
|
||||
@Field Set GENERAL_CONFIG_KEYS = []
|
||||
@Field Set STEP_CONFIG_KEYS = [
|
||||
/** The name of the application which is being built. If the parameter has been provided and no `mta.yaml` exists, the `mta.yaml` will be automatically generated using this parameter and the information (`name` and `version`) from `package.json` before the actual build starts.*/
|
||||
'applicationName',
|
||||
/**
|
||||
* The target platform to which the mtar can be deployed.
|
||||
* @possibleValues 'CF', 'NEO', 'XSA'
|
||||
*/
|
||||
'buildTarget',
|
||||
/** @see dockerExecute */
|
||||
'dockerImage',
|
||||
/** The path to the extension descriptor file.*/
|
||||
'extension',
|
||||
/**
|
||||
* The location of the SAP Multitarget Application Archive Builder jar file, including file name and extension.
|
||||
* If it is not provided, the SAP Multitarget Application Archive Builder is expected on PATH.
|
||||
*/
|
||||
'mtaJarLocation'
|
||||
]
|
||||
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS.plus([
|
||||
/** @see dockerExecute */
|
||||
'dockerOptions'
|
||||
])
|
||||
|
||||
/**
|
||||
* Executes the SAP Multitarget Application Archive Builder to create an mtar archive of the application.
|
||||
*/
|
||||
@GenerateDocumentation
|
||||
void call(Map parameters = [:]) {
|
||||
handlePipelineStepErrors(stepName: STEP_NAME, stepParameters: parameters) {
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import com.sap.piper.GenerateDocumentation
|
||||
import com.sap.piper.Utils
|
||||
|
||||
import groovy.transform.Field
|
||||
@@ -5,12 +6,26 @@ import groovy.transform.Field
|
||||
|
||||
@Field STEP_NAME = getClass().getName()
|
||||
|
||||
@Field Set PARAMETER_KEYS = [
|
||||
/** The url to the git repository of the pipeline to be loaded.*/
|
||||
'repoUrl',
|
||||
/** The branch of the git repository from which the pipeline should be checked out.*/
|
||||
'branch',
|
||||
/** The path to the Jenkinsfile, inside the repository, to be loaded.*/
|
||||
'path',
|
||||
/** The Jenkins credentials containing user and password needed to access a private git repository.*/
|
||||
'credentialsId'
|
||||
]
|
||||
|
||||
/**
|
||||
* pipelineExecute
|
||||
* Load and executes a pipeline from another git repository.
|
||||
* Loads and executes a pipeline from another git repository.
|
||||
* The idea is to set up a pipeline job in Jenkins that loads a minimal pipeline, which
|
||||
* in turn loads the shared library and then uses this step to load the actual pipeline.
|
||||
*
|
||||
* A centrally maintained pipeline script (Jenkinsfile) can be re-used by
|
||||
* several projects using `pipelineExecute` as outlined in the example below.
|
||||
*/
|
||||
@GenerateDocumentation
|
||||
void call(Map parameters = [:]) {
|
||||
|
||||
node() {
|
||||
|
||||
Reference in New Issue
Block a user