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'? )

    Possible duplicate of How do I assure that a Jenkins pipeline stage is always executed, even if a previous one failed? – Amedee Van Gasse May 27, 2016 at 13:48

    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

    @Mohamed, as Subrat said, this doesn't work outside of the jenkins file. Is there another way to do it? – Jason Jul 18, 2017 at 20:11 It could be due to the jenkins version or plugin version however I am not sure. The other way to do it is put the changes in a try catch and finally block. – Mohamed Thoufeeque Jul 19, 2017 at 9:02 @MohamedThoufeeque do you know if you can make the posy steps conditional? I would like to only send an email if the build fails for certain branches. – thecoshman Nov 14, 2017 at 17:27 how do you get the stage where the failure happened in the post directive? is that an environment variable? – red888 Jan 18, 2018 at 20:02

    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.

    I just tried this and found cases where some stage errors (error added on purpose to test the post build step) can't be detected... currResult == SUCCESS when the job is clearly failing (Jenkins literally write in the console Finished: FAILURE). in my finally block, both currentBuild.result & currentBuild.currentResult are SUCCESS. Any idea why? – MoOx Apr 8, 2020 at 14:43 @MoOx sorry I'm just seeing this now ... it has been ages since I looked at this, and perhaps something has changed internally with how the current result of the build is handled. Would have to test it, but you may need to use def currResult = currentBuild.currentResult ?: 'SUCCESS' instead in the first line. I forget which is set by Jenkins and which is set from your Groovy code, but if memory serves, currentResult may be what is required here. It may not have been set, so you can assume SUCCESS in that case. If there was a failure, it would be set to UNSTABLE or FAILURE already. – Will Dec 9, 2021 at 3:45 @MoOx also, I would have to see specifically how your code is written, where the try/catch/finally is placed, and where the error condition is coming into play. Debugging pipelines, in my experience, is far from fun, but not impossible. Just takes being able to see the code as a whole and being able to run it on my Jenkins instance. – Will Dec 9, 2021 at 3:49

    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.

  •