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

Merge branch 'master' into CAP_Scenario

This commit is contained in:
Christoph Szymanski 2019-02-08 14:23:36 +01:00 committed by GitHub
commit 0402811f2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 140 additions and 81 deletions

View File

@ -72,7 +72,7 @@ class TemplateHelper {
parameters.keySet().toSorted().each { parameters.keySet().toSorted().each {
def props = parameters.get(it) def props = parameters.get(it)
t += "| `${it}` | ${props.GENERAL_CONFIG ? 'X' : ''} | ${props.STEP_CONFIG ? 'X' : ''} | ${props.STAGE_CONFIG ? 'X' : ''} |\n" t += "| `${it}` | ${props.GENERAL_CONFIG ? 'X' : ''} | ${props.STEP_CONFIG ? 'X' : ''} | ${props.STAGE_CONFIG ? 'X' : ''} |\n"
} }
t.trim() t.trim()

View File

@ -2,7 +2,7 @@
## Description ## Description
Executes a closure inside a container in a kubernetes pod. Proxy environment variables defined on the Jenkins machine are also available in the container. Content here is generated from corresponnding step, see `vars`.
## Prerequisites ## Prerequisites
@ -13,65 +13,11 @@ Executes a closure inside a container in a kubernetes pod. Proxy environment var
## Parameters ## Parameters
| parameter | mandatory | default | possible values | Content here is generated from corresponnding step, see `vars`.
| ----------|-----------|---------|-----------------|
|script|yes|||
|containerCommand|no|||
|containerCommands|no|||
|containerEnvVars|no|||
|containerPullImageFlags|no|true|boolean value: `true`, `false` |
|containerMap|no|`[:]`||
|containerName|no|||
|containerPortMappings|no|||
|containerShell|no|||
|containerWorkspaces|no|||
|dockerEnvVars|no|`[:]`||
|dockerImage|yes|||
|dockerPullImage|no|true|boolean value: `true`, `false` |
|dockerWorkspace|no|`''`||
|jenkinsKubernetes|no|`[jnlpAgent:s4sdk/jenkins-agent-k8s:latest]`||
|stashExcludes|no|`[workspace:nohup.out]`||
|stashIncludes|no|`[workspace:**/*.*]`||
* `script` defines the global script environment of the Jenkins file run. Typically `this` is passed to this parameter. This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md) for storing the measured duration.
* `containerCommand`: allows to specify start command for container created with dockerImage parameter to overwrite Piper default (`/usr/bin/tail -f /dev/null`).
* `containerCommands` specifies start command for containers to overwrite Piper default (`/usr/bin/tail -f /dev/null`). If container's defaultstart command should be used provide empty string like: `['selenium/standalone-chrome': '']`.
* `containerEnvVars` specifies environment variables per container. If not provided `dockerEnvVars` will be used.
* `containerPullImageFlags` specifies the pullImage flag per container.
* `containerMap` A map of docker image to the name of the container. The pod will be created with all the images from this map and they are labled based on the value field of each map entry.
Example: `['maven:3.5-jdk-8-alpine': 'mavenExecute', 'selenium/standalone-chrome': 'selenium', 'famiko/jmeter-base': 'checkJMeter', 's4sdk/docker-cf-cli': 'cloudfoundry']`
* `containerName`: optional configuration in combination with containerMap to define the container where the commands should be executed in
* `containerPortMappings`: Map which defines per docker image the port mappings, like `containerPortMappings: ['selenium/standalone-chrome': [[name: 'selPort', containerPort: 4444, hostPort: 4444]]]`
* `containerShell` allows to specify the shell to be executed for container with containerName
* `containerWorkspaces` specifies workspace (=home directory of user) per container. If not provided `dockerWorkspace` will be used. If empty, home directory will not be set.
* `dockerImage` Name of the docker image that should be used. If empty, Docker is not used.
* `dockerEnvVars` Environment variables to set in the container, e.g. [http_proxy:'proxy:8080']
* `dockerPullImage`: Set this to 'false' to bypass a docker image pull. Usefull during development process. Allows testing of images which are available in the local registry only.
* `dockerWorkspace` Docker options to be set when starting the container. It can be a list or a string.
## Step configuration ## Step configuration
We recommend to define values of step parameters via [config.yml file](../configuration.md). Content here is generated from corresponnding step, see `vars`.
In following sections the configuration is possible:
| parameter | general | step | stage |
| ----------|-----------|---------|-----------------|
|script||||
|containerCommands||X|X|
|containerEnvVars||X|X|
|containerPullImageFlags||X|X|
|containerMap||X|X|
|containerName||X|X|
|containerPortMappings||X|X|
|containerWorkspaces||X|X|
|dockerEnvVars||X|X|
|dockerImage||X|X|
|dockerPullImage||X|X|
|dockerWorkspace||X|X|
|jenkinsKubernetes|X|||
|stashExcludes||X|X|
|stashIncludes||X|X|
## Side effects ## Side effects

View File

@ -55,7 +55,9 @@ testsPublishResults script: this, junit: [pattern: '**/newman/TEST-*.xml']
We recommend to define values of step parameters via [config.yml file](../configuration.md). 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 | In following sections the configuration is possible:
| parameter | general | step | stage |
|-----------|---------|------|-------| |-----------|---------|------|-------|
| `dockerImage` |  | X | X | | `dockerImage` |  | X | X |
| `failOnError` |  | X | X | | `failOnError` |  | X | X |

View File

@ -33,6 +33,7 @@ Available parameters:
| parameter | mandatory | default | possible values | | parameter | mandatory | default | possible values |
| ----------|-----------|---------|-----------------| | ----------|-----------|---------|-----------------|
| script | yes | | | | script | yes | | |
| `failOnError` | no | `false` | `true`, `false` |
| junit | no | `false` | true, false | | junit | no | `false` | true, false |
| jacoco | no | `false` | true, false | | jacoco | no | `false` | true, false |
| cobertura | no | `false` | true, false | | cobertura | no | `false` | true, false |
@ -43,6 +44,7 @@ Available parameters:
with the `this` parameter, as in `script: this`. with the `this` parameter, as in `script: this`.
This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md) This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md)
for retrieving, for example, configuration parameters. for retrieving, for example, configuration parameters.
* `failOnError` - If `failOnError` it set to `true` the step will fail the build if JUnit detected any failing tests.
* `junit` - Publishes test results files in JUnit format with the [JUnit Plugin](https://plugins.jenkins.io/junit). * `junit` - Publishes test results files in JUnit format with the [JUnit Plugin](https://plugins.jenkins.io/junit).
* `jacoco` - Publishes code coverage with the [JaCoCo plugin](https://plugins.jenkins.io/jacoco) . * `jacoco` - Publishes code coverage with the [JaCoCo plugin](https://plugins.jenkins.io/jacoco) .
* `cobertura` - Publishes code coverage with the [Cobertura plugin](https://plugins.jenkins.io/cobertura). * `cobertura` - Publishes code coverage with the [Cobertura plugin](https://plugins.jenkins.io/cobertura).

View File

@ -35,6 +35,7 @@ nav:
- transportRequestCreate: steps/transportRequestCreate.md - transportRequestCreate: steps/transportRequestCreate.md
- transportRequestRelease: steps/transportRequestRelease.md - transportRequestRelease: steps/transportRequestRelease.md
- transportRequestUploadFile: steps/transportRequestUploadFile.md - transportRequestUploadFile: steps/transportRequestUploadFile.md
- uiVeri5ExecuteTests: steps/uiVeri5ExecuteTests.md
- 'Scenarios': - 'Scenarios':
- 'Build and Deploy Hybrid Applications with Jenkins and SAP Solution Manager': scenarios/changeManagement.md - 'Build and Deploy Hybrid Applications with Jenkins and SAP Solution Manager': scenarios/changeManagement.md
- 'Create a Pipeline for SAP UI5 or SAP Fiori on SAP Cloud Platform': scenarios/ui5-sap-cp/Readme.md - 'Create a Pipeline for SAP UI5 or SAP Fiori on SAP Cloud Platform': scenarios/ui5-sap-cp/Readme.md

View File

@ -317,6 +317,7 @@ steps:
toJson: false toJson: false
toHtml: false toHtml: false
testsPublishResults: testsPublishResults:
failOnError: false
junit: junit:
pattern: '**/TEST-*.xml' pattern: '**/TEST-*.xml'
updateResults: false updateResults: false

View File

@ -3,6 +3,7 @@ package com.sap.piper
import com.cloudbees.groovy.cps.NonCPS import com.cloudbees.groovy.cps.NonCPS
import jenkins.model.Jenkins import jenkins.model.Jenkins
import org.jenkinsci.plugins.workflow.steps.MissingContextVariableException import org.jenkinsci.plugins.workflow.steps.MissingContextVariableException
import hudson.tasks.junit.TestResultAction
@API @API
@NonCPS @NonCPS
@ -10,6 +11,14 @@ static def isPluginActive(pluginId) {
return Jenkins.instance.pluginManager.plugins.find { p -> p.isActive() && p.getShortName() == pluginId } return Jenkins.instance.pluginManager.plugins.find { p -> p.isActive() && p.getShortName() == pluginId }
} }
static boolean hasTestFailures(build){
//build: https://javadoc.jenkins.io/plugin/workflow-support/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapper.html
//getRawBuild: https://javadoc.jenkins.io/plugin/workflow-job/org/jenkinsci/plugins/workflow/job/WorkflowRun.html
//getAction: http://www.hudson-ci.org/javadoc/hudson/tasks/junit/TestResultAction.html
def action = build?.getRawBuild()?.getAction(TestResultAction.class)
return action && action.getFailCount() != 0
}
def nodeAvailable() { def nodeAvailable() {
try { try {
sh "echo 'Node is available!'" sh "echo 'Node is available!'"

View File

@ -3,6 +3,7 @@ import org.junit.Ignore
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.rules.RuleChain import org.junit.rules.RuleChain
import org.junit.rules.ExpectedException
import util.BasePiperTest import util.BasePiperTest
import util.JenkinsReadYamlRule import util.JenkinsReadYamlRule
@ -16,12 +17,14 @@ class TestsPublishResultsTest extends BasePiperTest {
Map publisherStepOptions Map publisherStepOptions
List archiveStepPatterns List archiveStepPatterns
private ExpectedException thrown = ExpectedException.none()
private JenkinsStepRule stepRule = new JenkinsStepRule(this) private JenkinsStepRule stepRule = new JenkinsStepRule(this)
@Rule @Rule
public RuleChain ruleChain = Rules public RuleChain ruleChain = Rules
.getCommonRules(this) .getCommonRules(this)
.around(new JenkinsReadYamlRule(this)) .around(new JenkinsReadYamlRule(this))
.around(thrown)
.around(stepRule) .around(stepRule)
@Before @Before
@ -126,4 +129,40 @@ class TestsPublishResultsTest extends BasePiperTest {
assertTrue('Cobertura options are not empty', publisherStepOptions.cobertura == null) assertTrue('Cobertura options are not empty', publisherStepOptions.cobertura == null)
assertTrue('JMeter options are not empty', publisherStepOptions.jmeter == null) assertTrue('JMeter options are not empty', publisherStepOptions.jmeter == null)
} }
@Test
void testBuildResultStatus() throws Exception {
stepRule.step.testsPublishResults(script: nullScript)
assertJobStatusSuccess()
}
@Test
void testBuildWithTestFailuresAndWithoutFailOnError() throws Exception {
nullScript.currentBuild.getRawBuild = {
return [getAction: { type ->
return [getFailCount: {
return 6
}]
}]
}
stepRule.step.testsPublishResults(script: nullScript)
assertJobStatusSuccess()
}
@Test
void testBuildWithTestFailuresAndWithFailOnError() throws Exception {
nullScript.currentBuild.getRawBuild = {
return [getAction: { type ->
return [getFailCount: {
return 6
}]
}]
}
thrown.expect(hudson.AbortException)
thrown.expectMessage('[testsPublishResults] Some tests failed!')
stepRule.step.testsPublishResults(script: nullScript, failOnError: true)
}
} }

View File

@ -1,5 +1,4 @@
#!groovy #!groovy
package steps
import static org.hamcrest.Matchers.* import static org.hamcrest.Matchers.*

View File

@ -1,6 +1,7 @@
import static com.sap.piper.Prerequisites.checkScript import static com.sap.piper.Prerequisites.checkScript
import com.sap.piper.ConfigurationHelper import com.sap.piper.ConfigurationHelper
import com.sap.piper.GenerateDocumentation
import com.sap.piper.JenkinsUtils import com.sap.piper.JenkinsUtils
import com.sap.piper.Utils import com.sap.piper.Utils
import com.sap.piper.k8s.SystemEnv import com.sap.piper.k8s.SystemEnv
@ -9,25 +10,77 @@ import hudson.AbortException
@Field def STEP_NAME = getClass().getName() @Field def STEP_NAME = getClass().getName()
@Field def PLUGIN_ID_KUBERNETES = 'kubernetes' @Field def PLUGIN_ID_KUBERNETES = 'kubernetes'
@Field Set GENERAL_CONFIG_KEYS = [ @Field Set GENERAL_CONFIG_KEYS = [
'jenkinsKubernetes' 'jenkinsKubernetes'
] ]
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus([ @Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus([
'containerCommand', // specify start command for container created with dockerImage parameter to overwrite Piper default (`/usr/bin/tail -f /dev/null`). /**
'containerCommands', //specify start command for containers to overwrite Piper default (`/usr/bin/tail -f /dev/null`). If container's default start command should be used provide empty string like: `['selenium/standalone-chrome': '']` * Allows to specify start command for container created with dockerImage parameter to overwrite Piper default (`/usr/bin/tail -f /dev/null`).
'containerEnvVars', //specify environment variables per container. If not provided dockerEnvVars will be used */
'containerPullImageFlags', // specifies the pullImage flag per container. 'containerCommand',
'containerMap', //specify multiple images which then form a kubernetes pod, example: containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute','selenium/standalone-chrome': 'selenium'] /**
'containerName', //optional configuration in combination with containerMap to define the container where the commands should be executed in * Specifies start command for containers to overwrite Piper default (`/usr/bin/tail -f /dev/null`).
'containerPortMappings', //map which defines per docker image the port mappings, like containerPortMappings: ['selenium/standalone-chrome': [[name: 'selPort', containerPort: 4444, hostPort: 4444]]] * If container's defaultstart command should be used provide empty string like: `['selenium/standalone-chrome': '']`.
'containerShell', // allows to specify the shell to be executed for container with containerName */
'containerWorkspaces', //specify workspace (=home directory of user) per container. If not provided dockerWorkspace will be used. If empty, home directory will not be set. 'containerCommands',
'dockerImage', /**
'dockerPullImage', * Specifies environment variables per container. If not provided `dockerEnvVars` will be used.
'dockerWorkspace', */
'containerEnvVars',
/**
* A map of docker image to the name of the container. The pod will be created with all the images from this map and they are labled based on the value field of each map entry.
* Example: `['maven:3.5-jdk-8-alpine': 'mavenExecute', 'selenium/standalone-chrome': 'selenium', 'famiko/jmeter-base': 'checkJMeter', 's4sdk/docker-cf-cli': 'cloudfoundry']`
*/
'containerMap',
/**
* Optional configuration in combination with containerMap to define the container where the commands should be executed in.
*/
'containerName',
/**
* Map which defines per docker image the port mappings, e.g. `containerPortMappings: ['selenium/standalone-chrome': [[name: 'selPort', containerPort: 4444, hostPort: 4444]]]`.
*/
'containerPortMappings',
/**
* Specifies the pullImage flag per container.
*/
'containerPullImageFlags',
/**
* Allows to specify the shell to be executed for container with containerName.
*/
'containerShell',
/**
* Specifies a dedicated user home directory per container which will be passed as value for environment variable `HOME`. If not provided `dockerWorkspace` will be used.
*/
'containerWorkspaces',
/**
* Environment variables to set in the container, e.g. [http_proxy:'proxy:8080'].
*/
'dockerEnvVars', 'dockerEnvVars',
/**
* Name of the docker image that should be used. If empty, Docker is not used.
*/
'dockerImage',
/**
* Set this to 'false' to bypass a docker image pull.
* Usefull during development process. Allows testing of images which are available in the local registry only.
*/
'dockerPullImage',
/**
* Specifies a dedicated user home directory for the container which will be passed as value for environment variable `HOME`.
*/
'dockerWorkspace',
/**
* Specific stashes that should be considered for the step execution.
*/
'stashContent', 'stashContent',
/**
*
*/
'stashExcludes', 'stashExcludes',
/**
*
*/
'stashIncludes' 'stashIncludes'
]) ])
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS.minus([ @Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS.minus([
@ -35,6 +88,11 @@ import hudson.AbortException
'stashExcludes' 'stashExcludes'
]) ])
/**
* Executes a closure inside a container in a kubernetes pod.
* Proxy environment variables defined on the Jenkins machine are also available in the container.
*/
@GenerateDocumentation
void call(Map parameters = [:], body) { void call(Map parameters = [:], body) {
handlePipelineStepErrors(stepName: STEP_NAME, stepParameters: parameters) { handlePipelineStepErrors(stepName: STEP_NAME, stepParameters: parameters) {
@ -175,7 +233,7 @@ private List getContainerList(config) {
return result return result
} }
/** /*
* Returns a list of envVar object consisting of set * Returns a list of envVar object consisting of set
* environment variables, params (Parametrized Build) and working directory. * environment variables, params (Parametrized Build) and working directory.
* (Kubernetes-Plugin only!) * (Kubernetes-Plugin only!)

View File

@ -3,6 +3,7 @@ import static com.sap.piper.Prerequisites.checkScript
import com.cloudbees.groovy.cps.NonCPS import com.cloudbees.groovy.cps.NonCPS
import com.sap.piper.ConfigurationHelper import com.sap.piper.ConfigurationHelper
import com.sap.piper.JenkinsUtils
import com.sap.piper.MapUtils import com.sap.piper.MapUtils
import com.sap.piper.Utils import com.sap.piper.Utils
import groovy.transform.Field import groovy.transform.Field
@ -13,7 +14,9 @@ import groovy.transform.Field
@Field def STEP_NAME = getClass().getName() @Field def STEP_NAME = getClass().getName()
@Field Set GENERAL_CONFIG_KEYS = TOOLS @Field Set GENERAL_CONFIG_KEYS = TOOLS
@Field Set STEP_CONFIG_KEYS = TOOLS @Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus([
'failOnError'
])
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS @Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
/** /**
@ -24,10 +27,7 @@ import groovy.transform.Field
*/ */
void call(Map parameters = [:]) { void call(Map parameters = [:]) {
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) { handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) {
def script = checkScript(this, parameters) ?: this
def script = checkScript(this, parameters)
if (script == null)
script = this
prepare(parameters) prepare(parameters)
@ -46,13 +46,15 @@ void call(Map parameters = [:]) {
stepParam1: parameters?.script == null stepParam1: parameters?.script == null
], configuration) ], configuration)
// UNIT TESTS
publishJUnitReport(configuration.get('junit')) publishJUnitReport(configuration.get('junit'))
// CODE COVERAGE
publishJacocoReport(configuration.get('jacoco')) publishJacocoReport(configuration.get('jacoco'))
publishCoberturaReport(configuration.get('cobertura')) publishCoberturaReport(configuration.get('cobertura'))
// PERFORMANCE
publishJMeterReport(configuration.get('jmeter')) publishJMeterReport(configuration.get('jmeter'))
if (configuration.failOnError && JenkinsUtils.hasTestFailures(script.currentBuild)) {
script.currentBuild.result = 'FAILURE'
error "[${STEP_NAME}] Some tests failed!"
}
} }
} }