I want to set a build's result to UNSTABLE
when a maven build step exits because of test failures.
I'm using the withMaven build step which provides special treatment of maven test results:
In case of failing tests, it sets the build result to UNSTABLE
before failing the step.
This works perfectly when using a scripted pipeline.
In case of a declarative pipeline, however, the build result is set to FAILURE
.
This is illustrated by the following code samples.
Edit: Please note that the the try/catch and post blocks are not required for the example to work. They are only present so that the value of currentBuild.result
can be examined right after the invocation of withMaven
.
Declarative
pipeline {
agent any
stages {
stage('Build') {
steps {
withMaven() {
sh 'mvn clean verify' // -> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
}
}
post {
always {
echo "CurrentResult: $currentBuild.currentResult" // -> FAILURE
echo "Result: $currentBuild.result" // -> FAILURE
// overall build result -> FAILURE
}
}
}
}
}
Scripted
node() {
stage('Build') {
try {
withMaven() {
sh 'mvn clean verify' // -> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
}
} catch (e) {
echo "CurrentResult: $currentBuild.currentResult" // -> UNSTABLE
echo "Result: $currentBuild.result" // -> UNSTABLE
// overall build result -> UNSTABLE
}
}
}
How can i preserve the build result of UNSTABLE
from a maven build step in a declarative pipeline?
Versions used: Jenkins 2.204.1, Pipeline Maven Integration Plugin 3.8.2, Maven 3.6.3 (installed on the build agent), AdoptOpenJDK 1.8.0_222.
As fredericrous pointed out, the difference is the caught exception. If the exception is not caught in the Jenkinsfile, then the result will be set to FAILED.
I am not an expert, but i came up with a pure declarative approach which solve this problem in exchange of a more cluttered Jenkinsfile.
pipeline {
agent any
stages {
stage('Build') {
steps {
catchError(buildResult: null, catchInterruptions: false) {
withMaven() {
sh 'mvn clean verify' // -> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
}
}
}
post {
always {
echo "CurrentResult: $currentBuild.currentResult" // -> UNSTABLE
echo "Result: $currentBuild.result" // -> UNSTABLE
}
}
}
stage('Deploy') {
when {
expression {
currentBuild.result == "SUCCESS"
}
}
steps {
echo 'Deploy'
}
}
}
}
catchError(buildResult: null, catchInterruptions: false)
buildResult: null
which is equivalent to buildResult: 'SUCCESS'
, prevents catchError
to set the buildResult to FAILURE, regardless of the value before.
catchInterruptions: false
tells catchError to not catch, respectively rethrow, certain types of exceptions that are used to interrupt the flow of execution for Pipelines.
The "drawback" of catching the exception is that the current, and all following, stages
are executed.
To skip a stage in regard of the result, a when
declarative can be added to the stages.
This is how it looks from the stage view