How to continue the last stage of failure in Jenkins declaration syntax

I want to identify several steps in the syntax of the Jenkins declarative pipeline, which may fail after any of them. I cannot find any existing questions that are true duplicates because they all assume or allow script syntax.

pipeline { agent any stages { stage('stage 1') { steps { echo "I need to run every time" } } stage('stage 2') { steps { echo "I need to run every time, even if stage 1 fails" } } stage('stage 3') { steps { echo "Bonus points if the solution is robust enough to allow me to continue *or* be halted based on previous stage status" } } } } 

To clarify, I'm not looking for how to do this in a syntax script. I am trying to understand whether this kind of flow control is really supported and formalized in declarative syntax. To this end, I will try to determine exactly what I am looking for:

Required

  • No attempt / catch. I do not want to go into the script or "wrap" my declarative pipeline in another shared library or script.
  • No post step shenanigans. I want the true few steps, not one step with the post always step, which contains all my other logic.

Additionally

  • The unsuccessful stage must be recognized as unsuccessful; I do not want the failed step to display as green because it was "skipped" or "continued."
  • A line with any unsuccessful stage should be marked as red (or yellow, or nothing that is not green).

Bound but not sufficient

+11
source share
4 answers

Maybe something is missing for me, but the idea of ​​a declarative, stubborn conveyor should provide coverage for the simplest use cases. The moment you need something about doesn’t apply, you need to resort to a script related to the script, this applies only to the “requirement” of the “declarative pipeline”: now this will not happen.

As for your other “requirements,” they make little sense, since the whole idea is to wrap low-level ugliness in shared libraries, providing users with constructs such as:

  mylib.failable_stages({ stages { stage('stage 1') { steps { echo "I need to run every time" } } stage('stage 2') { steps { echo "I need to run every time, even if stage 1 fails" } } stage('stage 3') { steps { echo "Bonus points if the solution is robust enough to allow me to continue *or* be halted based on previous stage status" } } } }) 

Naturally, you would need to find or implement such a mylib class, and failable_stages will get a closure and wrap it in various pieces of the plumbing / template.

Hope this will be helpful.

+4
source

I think it depends on how much jobs depend on each other. Based on your example, I would suggest that

  • Stage 1 does not depend on all other stages, because this is the first
  • Stage 2 does not depend on all other stages, since stage 1 can immediately fail, and stage 2 will still be required to run
  • stage 3 depends on the result of stage 1 and stage 2

Thus, the corresponding conveyor can be

 pipeline { stages { stage('Independent tasks') { parallel { stage('stage 1') { steps { sh 'exit 1' // failure } } stage('stage 2') { steps { echo 'Happens even so stage 1 fails' sh 'exit 0' // success } } } post { // 'stage 3' failure { echo "... at least one failed" } success { echo "Success!" } } } stage ('stage 4') { steps { echo 'Happens only if all previous succeed' } } } } 

Stage 1 and stage 2 are always performed, stage 3 responds to their combined success / failure.


Additional thought: this concept only works "at the end" of your pipeline. If you need it somewhere in the middle, and the assembly should continue, you can move it to your own task and use the build job plugin.

 pipeline { stages { stage('Start own job for stage 1, 2, 3') { steps { build job: 'stageOneTwoThree', propagate: false, wait: true } } stage ('stage 4') { steps { echo 'Happens always, because "propagate: false"' } } } 
0
source

Now it is possible:

 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 above example, all steps will be completed, the pipeline will succeed, but step 2 will be shown as unsuccessful:

Pipeline example

As you might have guessed, you can freely choose buildResult and stageResult if you want it to be unstable or something else. You can even fail to build and continue executing the pipeline.

Just make sure your Jenkins is up to date as this is a pretty new feature.

0
source

Now it is possible:

 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 above example, all steps will be completed, the pipeline will succeed, but step 2 will be shown as unsuccessful:

Pipeline example

As you might have guessed, you can freely choose buildResult and stageResult if you want it to be unstable or something else. You can even fail to build and continue executing the pipeline.

Just make sure your Jenkins is up to date as this is a pretty new feature.

EDIT: This is a question for which this answer was originally written. This is also the correct answer to several other questions, so I also posted this answer there. This is the right solution for many similar problems. I developed my other answers to their specific questions in order to clarify this. I just copied the answer to save time. This does not mean that this is not a very correct answer.

0
source

Source: https://habr.com/ru/post/1269686/


All Articles