104

I have a series of stages that perform quick checks. I want to perform them all, even if there are failures. For example:

stage('one') {
    node {
        sh 'exit 0'
    }
}
stage('two') {
    node {
        sh 'exit 1'   // failure
    }
}
stage('three') {
    node {
        sh 'exit 0'
    }
}

Stage two fails, so by default stage three is not executed.

Ordinarily this would be a job for parallel, but I want to display them in the stage view. In the mock up below:

  • Build #4 shows what normally happens. Job two fails so three does not run.
  • I Photoshopped Build #6 to show what I would like to see. Job two fails and is displayed as such, but three still runs. The real Jenkins would probably display the entire Build #6 tinged slightly red, which is of course fine.

Mock up of desired Stage View result

John McGehee
  • 9,117
  • 9
  • 42
  • 50
  • 10
    Use try/catch around stage 2 – Software Engineer Nov 15 '16 at 01:32
  • 5
    or built-in `catchError` which also will mark the build red in case of exception. – izzekil Nov 15 '16 at 03:49
  • 3
    Thank you for the excellent comments @EngineerDollery and @izzekil. I can indeed use try/catch to prevent stage `two` from stopping the pipeline, but now stage `two` is marked as successful--it is green even though it actually failed. – John McGehee Nov 15 '16 at 22:50
  • 1
    The closest I could get is to catch the failure, save the failed stage, then after the last stage finishes, set the failed stages as "FAILURE". However, this requires something like `currentStage` as requested in [JENKINS-36087](https://issues.jenkins-ci.org/browse/JENKINS-36087) (superseded by [JENKINS-26522](https://issues.jenkins-ci.org/browse/JENKINS-26522)). – John McGehee Nov 16 '16 at 23:17
  • 1
    Possible duplicate of [Show a Jenkins pipeline stage as failed without failing the whole job](https://stackoverflow.com/questions/36852310/show-a-jenkins-pipeline-stage-as-failed-without-failing-the-whole-job) – vaza Feb 23 '18 at 10:18
  • @JohnMcGehee...I was also having same issue and solved it using try catch. But i also want to show Red color for my failed stages and green for success one but it is not working. have you found out any solution? – Radiant Jul 18 '19 at 12:08
  • For completion if someone is looking for the "unstable" state: you can set `currentBuild.result='UNSTABLE'` to make the build "yellow". And you can call `unstable(message: "foobar")` to set one single stage unstable. – Datz Aug 24 '20 at 09:11
  • For more completion: If you not only want your job to show the failure but also want your stage to be marked as "FAILURE" just use `catchError(stageResult: 'FAILURE') { ... }` – dnl.re Oct 19 '21 at 09:59
  • My simple suggestion, make use of shell script : $ cmd1 || cmd2: This will run cmd1, and in case of failure it will run cmd2. In your case cmd2 is simple "echo "cmd1 failed, proceeding" Thats all. – Krishna Feb 17 '22 at 19:24

8 Answers8

124

This is now possible. Below is an example of a declarative pipeline, but catchError works for scripted pipelines as well.

pipeline {
    agent any
    stages {
        stage('1') {
            steps {
                sh 'exit 0'
            }
        }
        stage('2') {
            steps {
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    sh "exit 1"
                }
            }
        }
        stage('3') {
            steps {
                sh 'exit 0'
            }
        }
    }
}

In the example above, all stages will execute, the pipeline will be successful, but stage 2 will show as failed:

Pipeline Example

As you might have guessed, you can freely choose the buildResult and stageResult, in case you want it to be unstable or anything else. You can even fail the build and continue the execution of the pipeline.

Just make sure your Jenkins is up to date, since this is a fairly new feature.

EDIT: You need "Pipeline: Basic Steps" 2.16 (May 14, 2019)

Erik B
  • 40,889
  • 25
  • 119
  • 135
  • 2
    I guess we could base ourselves by the date the answer has been given, but would you mind, for all clarity, add the date when this has been introduced please and maybe the version ? – Yassin Hajaj Aug 27 '19 at 16:32
  • Great info. Very useful – RamPrakash Aug 14 '20 at 16:08
  • Can catchError has finally block? – Turcia Aug 29 '20 at 21:01
  • @Turcia, a stage can have a “finally” block, `post { always {}}` independently of `catchError`. – Jan Hudec Oct 13 '20 at 13:01
  • 1
    Doesn't this end up making the overall job look successful though? If the goal was to just continue running stages after a stage had test failures, the whole job would end up being a false positive and look like it passed even though there were failures in a stage, wouldn't it? – Brian Oct 25 '22 at 15:11
  • What about when you have multiple commands in a step, and one of them fails, can you continue executing others? – shadowfire Jan 17 '23 at 13:50
19

I had the same concern. I was able to resolve it doing this.

Second stage will show in red and be marked as failed while the rest of the stages will keep running. You can set a flag and at the end of the stages check the flag and inform the status of the whole build.

node {

    def build_ok = true

    stage('one') {
        sh 'exit 0'
    }

    try{
        stage('two') {
            sh 'exit 1'   // failure
        }
    } catch(e) {
        build_ok = false
        echo e.toString()  
    }

    stage('three') {
        sh 'exit 0'
    }

    ....

    if(build_ok) {
        currentBuild.result = "SUCCESS"
    } else {
        currentBuild.result = "FAILURE"
    }
}
Paulo Merson
  • 13,270
  • 8
  • 79
  • 72
Pablo DC
  • 317
  • 2
  • 4
  • You might to give more detail how this solves OP's question. – CodeF0x Jun 15 '18 at 21:25
  • 5
    While this code snippet may be the solution, [including an explanation](https://meta.stackexchange.com/questions/114762/explaining-entirely-%E2%80%8C%E2%80%8Bcode-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – Narendra Jadhav Jun 16 '18 at 06:47
  • In this script what causes `stage('two)` to be marked failed? – handras Feb 21 '19 at 08:29
  • @handras `sh 'exit 1'` causes that, this is just an example to see what happen in each case – Pablo DC Feb 22 '19 at 13:48
  • 1
    @handras note that the try catch is outside of `stage('two')` and the stage will still fail – D-rk Jun 24 '19 at 06:32
  • The OP is using a declarative pipeline. This answer is scripted pipeline. Not sure it provides what the OP was looking for. – drhender Oct 07 '20 at 16:31
12

It depends whether you are using declarative pipeline syntax or scripted pipeline syntax.

declarative pipeline syntax:

pipeline {
    agent any
    stages {
        stage('one') {
            steps {
                sh 'exit 0'
            }
        }
        stage('two') {
            steps {
                sh 'exit 1'   // failure
            }
        }
    }
    post {
        always {
            sh 'exit 0'
        }
    }
}

Post-condition blocks contain steps the same as the steps section.

scripted pipeline syntax:

node {

    def build_ok = true

    stage('one') {
        sh 'exit 0'
    }

    try{
        stage('two') {
            sh 'exit 1'   // failure
        }
    } catch(e) {
        build_ok = false
        echo e.toString()  
    }

    stage('three') {
        sh 'exit 0'
    }

    if(build_ok) {
        currentBuild.result = "SUCCESS"
    } else {
        currentBuild.result = "FAILURE"
    }
}
D-rk
  • 5,513
  • 1
  • 37
  • 55
  • 1
    The declarative answer won't accomplish what the OP was looking for. If there were a stage three, the 'exit 1' in stage two would prevent stage three from executing. – drhender Oct 07 '20 at 16:48
  • @drhender, the declarative syntax does accomplish it. The stage 3 is moved in post-build actions as an always action and that runs even if the build failed. What is correct solution depends on what is needed—catch lets the build continue after failure in specific stage while post-build action is done even if any stage failed. – Jan Hudec Oct 13 '20 at 12:36
  • 1
    @JanHudec, IF there were changes to the declarative answer presented above, it could be made to work. However, what I said is correct. As presented above, the declarative answer doesn't address the OP's need. – drhender Oct 14 '20 at 14:37
  • where does this currentBuild come from? is this a local variable or something exposed by jenkins? thanks – Bijay Timilsina Mar 26 '21 at 15:07
6

Solution: In order to always continue failed steps in your jenkins pipeline:

Option 1. wrap you function in try/catch or in bash script <someOpertation> || true

try/catch:

script {
  try {
      sh 'do your stuff'
  } catch (Exception e) {
      sh 'Handle the exception!'
  }
}

bash always true:

script {
  sh 'cp ~/someFile.txt ~/dev || true'
}

Option 2. run your jenkins pipeline in parallel and set failFast false configuration property in your step.

    pipeline {
    agent any
    stages {
        stage('Parallel Stage') {
            when {
                branch 'master'
            }
            failFast false
            parallel {
                stage('Branch A') {
                    agent {
                        label "for-branch-a"
                    }
                    steps {
                        echo "On Branch A"
                    }
                }
                stage('Branch B') {
                    agent {
                        label "for-branch-b"
                    }
                    steps {
                        echo "On Branch B"
                    }
                }
            }
        }
    }
}
avivamg
  • 12,197
  • 3
  • 67
  • 61
4

This should work. However all boxes are red if even only one fails, but you can see boxes with error marked, so you will easily distinguish failed jobs.

def indexes = ['one', 'two', 'three']

node() {
    for (index in indexes) {
        catchError {
            stage(index) {
                println index
                sh '''echo "123"'''
            }
        }
    }
}
Pavol Travnik
  • 853
  • 3
  • 14
  • 32
2

I resolved that, using post actions: https://jenkins.io/doc/pipeline/tour/post/

           post {
            always {
                ...
            }
           }
Frank Escobar
  • 648
  • 5
  • 15
2

My simple suggestion, make use of shell scripts beauty like, $ cmd1 || cmd2: This will run cmd1, and in case of failure it will run cmd2. In your case cmd2 is simple "echo "cmd1 failed, proceeding next step" Thats all. It works like a charm :-)

Krishna
  • 501
  • 1
  • 8
  • 17
1

Try this example:

stage('StageName1')
{
    steps
    {
        catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE')
        {
            SomeCodeThatCanBeErrored
        }
    }
}
stage('StageName2')
{
    steps
    {
        ContinueOtherCode
    }
}
3Dark Unicorn
  • 195
  • 2
  • 2
  • This idea was already mentioned in [the most rated](https://stackoverflow.com/a/56976943/13988450) answer. – Foxy Fox May 12 '22 at 10:02