Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
After reading Jenkins
tutorial
explaining
Pipeline
plug-in, it seems that plug-in should make it possible to implement
Post-Build
steps. However documentation is rather limited in regard to specific instructions.
For example I wonder how to implement:
Run only if build succeeds
Run only if build succeeds or is unstable
Run regardless of build result
(Or add
-Dmaven.test.failure.ignore=false
to the
MAVEN_OPTS
)
Run only if build succeeds or is unstable
stage 'build'
... build
try {
... tests
} catch {
stage 'post-build'
(Or add -Dmaven.test.failure.ignore=true
to the MAVEN_OPTS
)
Run regardless of build result
- could it be done using
try / catch / finally
?
try {
stage 'build'
} catch {
} finally {
stage 'post-build'
(I've noticed that final build status is set as SUCCESS even though some stages, ie. 'build', have failed as it set based on last stage. Does that mean final build status need to explicitly set, ie.currentBuild.result = 'UNSTABLE'
? )
–
Handling Failures
Declarative Pipeline supports robust failure
handling by default via its post section which allows declaring a
number of different "post conditions" such as: always, unstable,
success, failure, and changed. The Pipeline Syntax section provides
more detail on how to use the various post conditions.
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'make check'
post {
always {
junit '**/target/*.xml'
failure {
mail to: team@example.com, subject: 'The Pipeline failed :('
The documentation is below
https://jenkins.io/doc/book/pipeline/syntax/#post
–
–
–
–
FWIW, if you are using scripted pipelines and not declarative, you should use a try/catch/finally
block as suggested in the other answers. In the finally
block, if you want to mimic what the declarative pipeline does, you can either put the following directly in the block, or make it a function and call that function from your finally
block:
def currResult = currentBuild.result ?: 'SUCCESS'
def prevResult = currentBuild.previousBuild?.result ?: 'NOT_BUILT'
// Identify current result
boolean isAborted = (currResult == 'ABORTED')
boolean isFailure = (currResult == 'FAILURE')
boolean isSuccess = (currResult == 'SUCCESS')
boolean isUnstable = (currResult == 'UNSTABLE')
boolean isChanged = (currResult != prevResult)
boolean isFixed = isChanged && isSuccess && (prevResult != 'ABORTED') && (prevResult != 'NOT_BUILT')
boolean isRegression = isChanged && currentBuild.resultIsWorseOrEqualTo(prevResult)
onAlways()
if (isChanged) {
onChanged()
if (isFixed) {
onFixed()
} else if (isRegression) {
onRegression()
if (isSuccess) {
onSuccess()
} else {
if (isAborted) {
onAborted()
onUnsuccessful()
if (isFailure) {
onFailure()
if (isUnstable) {
onUnstable()
onCleanup()
The various onXYZ()
calls are functions that you would define to handle that particular condition instead of using the nicer syntax of the declarative post
blocks.
–
–
–
If you are using try/catch and you want a build to be marked as unstable or failed then you must use currentBuild.result = 'UNSTABLE' etc. I believe some plugins like the JUnit Report plugin will set this for you if it finds failed tests in the junit results. But in most cases you have to set it your self if you are catching errors.
The second option if you don't want to continue is to rethrow the error.
stage 'build'
... build
try {
... tests
} catch(err) {
//do something then re-throw error if needed.
throw(err)
stage 'post-build'
try-catch
blocks can be set up to handle errors like in real application code.
For example:
try {
node {
sh 'sleep 20' // <<- can abort here
} catch (Exception e) {
println 'catch'
} finally {
println 'finally'
node {
println 'second'
try {
node {
sh 'sleep 20' // <<- can abort here again
} catch (Exception e) {
println 'catch'
} finally {
println 'finally'
And here is an example output with two aborts.
Started by user me
Replayed #3
[Pipeline] node
Running on my-node in /var/lib/jenkins-slave/workspace/my-job
[Pipeline] {
[Pipeline] sh
[my-job] Running shell script
+ sleep 20
Aborted by me
Sending interrupt signal to process
/var/lib/jenkins-slave/workspace/my-job@tmp/durable-9e1a15e6/script.sh: line 2: 10411 Terminated sleep 20
[Pipeline] }
[Pipeline] // node
[Pipeline] echo
catch
[Pipeline] echo
finally
[Pipeline] node
Running on my-node in /var/lib/jenkins-slave/workspace/my-job
[Pipeline] {
[Pipeline] echo
second
[Pipeline] }
[Pipeline] // node
[Pipeline] node
Running on my-node in /var/lib/jenkins-slave/workspace/my-job
[Pipeline] {
[Pipeline] sh
[my-job] Running shell script
+ sleep 20
Aborted by me
Sending interrupt signal to process
/var/lib/jenkins-slave/workspace/my-job@tmp/durable-d711100c/script.sh: line 2: 10416 Terminated sleep 20
[Pipeline] }
[Pipeline] // node
[Pipeline] echo
catch
[Pipeline] echo
finally
[Pipeline] End of Pipeline
Finished: ABORTED
Of course, this works for any exceptions happening during the execution.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.