katch
katch

Reputation: 930

How to execute next stage in sequential stages inspite of previous stage failure in Jenkins pipeline

At the moment I have two stages defined in Jenkins because they both need different agents.

Here is my Proof of concept code

stages {
    stage("Run Tests"){
        agent docker
        stage("Do setup"){}
        stage("Testing") {}
        post{
            always{
                echo "always"
            }
            failure {
                echo "failure"
            }
        }
    }
    stage("Generate Reports"){
        agent node-label
        stage("Generate"){

        }
    }
}

I need "Generate reports" on different agent since certain binaries are on the node and not inside docker container. Tests run inside docker share volume on node so I get all artifacts that are needed to generate report on the node

(I have tried to run "Generate reports" in post stage, but it seems to run inside docker container somehow.)

Now if "Run Tests" fails, "Generate reports" is skipped due to previous stage failure. Any idea how I can force "Generate reports" stage to be run even on failure of previous stage.

Upvotes: 0

Views: 3518

Answers (2)

Altaf
Altaf

Reputation: 3086

If you want to run "Generate Reports" stage always then you could mark your earlier stages as unstable if there are failures.
By this way Jenkins will execute all stages and will not stop on errors at a particular stage.
Example:

stages {
    stage("Run Tests"){
        agent docker
        stage("Do setup"){}
        stage("Testing") {
          steps {
                script {
            // To show an example, Execute "set 1" which will return failure 
            def result = bat label: 'Check bat......', returnStatus: true, script: "set 1"
                   if (result !=0) {
                   // If the result status is not 0 then mark this stage as unstable to continue ahead 
                   // and all later stages will be executed 
                   unstable ('Testing failed')
                   }
                }
            }
         }
    }
}
    stage("Generate Reports"){
        agent node-label
        stage("Generate"){

        }
    }
}

Option 2 , if you dont want to handle via return status , you can use try and catch block

stage("Testing") {
          steps {
                script {
                 try {
                        // To show an example, Execute "set 1" which will return failure 
                         bat "set 1"
                   }
                   catch (e){
                   unstable('Testing failed!')
                   }
                }
            }
         }

Option 3: You can change the return status as success of complete build irrespective of stage failure.

stage("Testing") {
          steps {
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE'){
                script {
                         // To show an example, Execute "set 1" which will return failure 
                         bat "set 1"
                   }
                }
            }
         

NOTE: Option 3 has a drawback it will not execute further steps in the same stage if at all there were any errors.
Example:
In this example, the print message "Testing stage" will not be executed as there were issues in bat set 1 command

stage("Testing") {
          steps {
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE'){
                script {
                         // To show an example, Execute "set 1" which will return failure 
                         bat "set 1"
                         // Note : Below step will not be executed since there was failure in prev step
                         println "Testing stage"
                   }
                }
            }

Option 4 : which you already tried out to keep Generate Reports stage in the Post always
section of the build so that is executed always irrespective of any failure.

Upvotes: 1

alpha89
alpha89

Reputation: 316

Below is the pipeline.

pipeline {
agent none
stages {
    stage("Run Tests"){
    agent { label "agent1" }
        stages  {           
            stage("Do setup"){
                steps{
                    sh 'exit 0'
                    }
                }
            stage("Testing") {
                steps {
                    catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    sh "exit 1"
                        } //catchError
                    } //steps
                post{
                    always{
                        echo "always"
                        }
                    failure {
                        echo "failure"
                        }
                    } // post
                } // Testing
            } // stages
        } // Run Test

    stage("Generate Reports"){
        agent { label "agent2" }
            steps {
                sh 'exit 0'
            }
        } // Reports
    }    
}

The pipeline is successful, but stage Testing is showed as failed, you can choose the status of buildResult and stageResult in case you want it to be unstable or fail:

enter image description here

Upvotes: 2

Related Questions