Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect which parallel stage failed in a Jenkins declarative pipeline?

My Jenkins pipeline runs several tasks in parallel. It appears that if one stage fails, all subsequent stages will run their failure post block (whether they actually failed or not). I don't know if this is by design or if I'm doing something wrong.

Note: This pipeline runs on a Windows node, hence the bat('exit /b 1')

pipeline {
    agent any

    stages {
        stage('Parallel steps') {
            parallel {
                stage('Successful stage') {
                    steps {
                        script { sleep 10 }
                    }
                    post {
                        failure {
                            echo('detected failure: Successful stage')
                        }
                    }
                }
                stage('Failure stage') {
                    steps {
                        script { bat('exit /b 1') }
                    }
                    post {
                        failure { 
                            echo('detected failure: Failure stage')
                        }
                    }
                }
            }
        }
    }
}

In the above pipeline, only 'Failure stage' fails, yet in the output I see this, indicating the failure conditional executed for both steps!

Started by user Doe, John
Running on WINDOWS_NODE in D:\workspace
[Successful stage] Sleeping for 10 sec
[Failure stage] [test] Running batch script
[Failure stage] D:\workspace>exit /b 1 
Post stage
[Pipeline] [Failure stage] echo
[Failure stage] detected failure: Failure stage
[Failure stage] Failed in branch Failure stage
Post stage
[Pipeline] [Successful stage] echo
[Successful stage] detected failure: Successful stage
ERROR: script returned exit code 1
Finished: FAILURE

What's the best way for me to detect which parallel stage failed and report it to the overall pipeline?

like image 912
Jay Spang Avatar asked Mar 19 '18 18:03

Jay Spang


People also ask

How do I stop Jenkins pipeline if stage fails?

Alternatively you can call error(String message) step to stop the pipeline and set its status to FAILED . For example, if your stage 1 calls error(msg) step like: stage("Stage 1") { steps { script { error "This pipeline stops here!" } } }

Do Jenkins stages run in parallel?

So the code presented above locates all of the project directories, creates an array of stages where each stage builds a different project, and then runs all stages in parallel. This means that without updating the Jenkinsfile each time we have a new project, all projects will be built in parallel.

How does parallel work in Jenkins?

This plugin adds a tool that lets you easily execute tests in parallel. This is achieved by having Jenkins look at the test execution time of the last run, split tests into multiple units of roughly equal size, then execute them in parallel.

What is fail fast in Jenkins pipeline?

On Semaphore, a fail-fast strategy means that you get instant feedback when a job fails. All the jobs running in a pipeline can be stopped (and subsequent jobs canceled) when a job fails. You don't need to wait for all the other jobs to complete to get feedback.


1 Answers

It looks like this is a known bug with Declarative Pipelines. I had to give up using the built-in post->failure block and use try/catch instead, which has its own problems:

  1. You have to catch and then re-throw the error in order to make the stage fail appropriately.
  2. The UI can get a little confusing, as the step that failed is no longer highlighted in red (but the error message is still in the log).
  3. The code is slightly less readable.

This code works correctly. Only the failing stage echoes "detected failure" instead of both.

pipeline {
    agent any

    stages {
        stage('Parallel steps') {
            parallel {
                stage('Successful stage') {
                    steps {
                        script {
                            try {
                                sleep 10 
                            } catch (e) {
                                echo('detected failure: Successful stage')
                                throw(e)
                            }
                        }
                    }
                }
                stage('Failure stage') {
                    steps {
                        script {
                            try {
                                bat('exit /b 1')
                            } catch (e) {
                                echo('detected failure: Failure stage')
                                throw(e)
                            }
                        }
                    }
                }
            }
        }
    }
}
like image 73
Jay Spang Avatar answered Oct 29 '22 16:10

Jay Spang