3
votes

I am looking for a generic way to determine the name of the failed stage at the end of a Jenkins scripted Pipeline.

Please note that this is different than Determine Failed Stage in Jenkins Declaritive Pipeline which is about declarative pipeline.

Also note that use of try/catch inside each stage is out of question because it would make the pipeline script impossible to read. This is because we have like 10-15 stages which are stored in multiple files and they are compiled using JJB to create the final pipeline script. They are already complex so I need a clean approach on finding which stage failed.

2
Try/catch blocks are the only way I've found to do this. I've been looking for the answer too.Jay Spang
Did you try env.STAGE_NAME?MyName
@MyName Make it an anwer. At the time I wrote the question this feature didn't reach production. By now the use of STAGE_NAME is the correct answer.sorin

2 Answers

1
votes

U could also create a custom step in a shared library, a super_stage

Quick example:

 // vars/super_stage.groovy
 def call(name, body) {
     try {
         stage(name) {
             body()
         }   
     } catch(e) {
         register_failed_stage(name, e)       
         throw e                                                                                            
     }   
 }

In that way you can 'reuse' the same exception handler.

In your scripted pipeline you would then use it like:

super_stage("mystage01") {
    //do stuff
}

Source

0
votes

Use a GraphListener:

def listener = new GraphListener.Synchronous(){
    @NonCPS
    void onNewHead(FlowNode node){
        if (node instanceof StepStartNode){
            // before steps execution
        }else if (node instanceof StepEndNode){
            // after steps execution
        }
}

def execution = (FlowExecution) currentBuild.getRawBuild().getExecution()
execution.addListener(listener)

You are going to need a few helper functions in order to make it work, for example StepStartNode and StepEndNode gets called twice so you have to filter the one with the label. Also variables like env are available inside the listener so you can store anything in there to be picked up later.

This answer is pretty generic but I've found that is useful in many of the stackoverflow questions regarding doing something before/after some stage (or in all).

You cannot try/catch exceptions inside the pipeline as this approach is not a wrapper for the stage but just a listener that gets executed once per each line instruction but you can just record the stage at the begining and at the end check currentBuild.result to see if the stage failed. You can do pretty much anything at this point.

At some point with the FlowExecution you have access to the pipeline script, I don't know if it's writtable at that point but it would be awesome to rewrite the pipeline to actually try/catch the stages. If you do something in this line please let me know ;)