Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access which stage failed in previous Jenkins build

I have written a Jenkinsfile script which gets whether documents are updated or code is updated in the current Github commit and starts all the stages accordingly. If only documents are updated I don't run the code testing stage again.

So now if the previous build failed and now in the current Git commit only documents are updated then it will not run the code testing stage. So I want a method/way to know which stage failed during the last Jenkins build and if needed run the current Jenkins build.

enter image description here

For example if the code testing stage failed in the previous build, I'll need to run the code testing stage for this build, otherwise I can just run the documents zipping stage.

like image 888
Pranav Bhagwat Avatar asked Jul 24 '18 05:07

Pranav Bhagwat


People also ask

How do I know which stage of Jenkins pipeline has failed?

An extension to the above requirement will be to provide the user with the actual error log (of the stage that has failed) also as a part of the failure notification email. Idea is, when a user receives a failure notification from jenkins, he should know which stage of the pipeline has failed along with the error log.

How do I see why a Jenkins build failed?

In Jenkins, in the pipeline where failure occurred, in the pane, select the latest build, and click Console Output. On the Console Output page, check the logs to find the reason for the failure.

What are the three fundamental stage of Jenkins pipeline?

Defines the "Build" stage. Perform some steps related to the "Build" stage. Defines the "Test" stage. Perform some steps related to the "Test" stage.


2 Answers

As a workaround to get failed stages from Jenkins build such function can be used. I could not find a simpler way to do it. But this code requires to run without Groovy sandbox or you need to whitelist a lot of Jenkins method signatures (which is not recommeded). Also blueocean plugin has to be installed.

import io.jenkins.blueocean.rest.impl.pipeline.PipelineNodeGraphVisitor                                                                                                                                            
import io.jenkins.blueocean.rest.impl.pipeline.FlowNodeWrapper                                                                                                                                                     
import org.jenkinsci.plugins.workflow.flow.FlowExecution                                                                                                                                                           
import org.jenkinsci.plugins.workflow.graph.FlowNode                                                                                                                                                               
import org.jenkinsci.plugins.workflow.job.WorkflowRun                                                                                                                                                              

@NonCPS                                                                                                                                                                                                            
List getFailedStages(WorkflowRun run) {                                                                                                                                                                            
    List failedStages = []                                                                                                                                                                                         
    FlowExecution exec = run.getExecution()                                                                                                                                                                        
    PipelineNodeGraphVisitor visitor = new PipelineNodeGraphVisitor(run)                                                                                                                                           
    def flowNodes = visitor.getPipelineNodes()                                                                                                                                                                     

    for (node in flowNodes) {                                                                                                                                                                                      
        if (node.getType() != FlowNodeWrapper.NodeType.STAGE ) { continue; }                                                                                                                                       
        String nodeName = node.getDisplayName()                                                                                                                                                                    
        def nodeResult = node.getStatus().getResult()                                                                                                                                                              
        println String.format('{"displayName": "%s", "result": "%s"}',                                                                                                                                             
                              nodeName, nodeResult)                                                                                                                                                                
        def resultSuccess = io.jenkins.blueocean.rest.model.BlueRun$BlueRunResult.SUCCESS                                                                                                                          
        if (nodeResult != resultSuccess) {                                                                                                                                                                         
            failedStages.add(nodeName)                                                                                                                                                                             
        }                                                                                                                                                                                                          
    }                                                                                                                                                                                                              
    return failedStages                                                                                                                                                                                            
}                                                                                                                                                                                                                  

// Ex. Get last build of "test_job"                                                                                                                                                                                
WorkflowRun run = Jenkins.instance.getItemByFullName("test_job")._getRuns()[0]                                                                                                                                     
failedStages = getFailedStages(run) 

like image 187
Gnat Avatar answered Sep 30 '22 18:09

Gnat


I thing it could fit. Use buildVariables from previous build, timeout \ input in case You need to change something, try \ catch for setup stages status. Code example:

// yourJob
// with try/catch block

def stageOneStatus;
def stageTwoStatus;
def stageThreeStatus;

pipeline {
    agent any
    stages {
        stage("STAGE 1") {
            // For initial run every stage
            when { expression { params.stageOne == "FAILURE" } }
            steps {
                script {
                    try {
                        // make thing
                    } catch (Exception e) {
                        stageOneStatus = "FAILURE";
                    }
                }
            }
        }

        stage("STAGE 2") {
            when { expression { params.stageTwo == "FAILURE" } }
            steps {
                script {
                    try {
                        // make thing
                    } catch (Exception e) {
                        stageTwoStatus = "FAILURE";
                    }
                }
            }
        }

        stage("STAGE 3") {
            when { expression { params.stageThree == "FAILURE" } }
            steps {
                script {
                    try {
                        // make thing
                    } catch (Exception e) {
                        stageThreeStatus = "FAILURE";
                    }
                }
            }
        }
    }
}

// Checking JOB

def pJob;

pipeline {
    agent any
    stages {
        // Run job with inheriting variable from build
        stage("Inheriting job") {
            steps {
                script {
                    pJob = build(job: "yourJob", parameters: [
                            [$class: 'StringParameterValue', name: 'stageOne', value: 'FAILURE'],
                            [$class: 'StringParameterValue', name: 'stageTwo', value: 'FAILURE'],
                            [$class: 'StringParameterValue', name: 'stageThree', value: 'FAILURE']
                            ], propagate: false)
                    if (pJob.result == 'FAILURE') {
                    error("${pJob.projectName} FAILED")
                    }
                }
            }
        }
        // Wait for fix, and re run job 
        stage ('Wait for fix') {
            timeout(time: 24, unit: 'HOURS') {
            input "Ready to rerun?"
            }
        }
        // Re run job after changes in code
        stage("Re-run Job") {
            steps {
                script {
                    build(
                        job: "yourJob",
                        parameters: [
                            [$class: 'StringParameterValue',name: 'stageOne',value: pJob.buildVariables.stageOneStatus ],
                            [$class: 'StringParameterValue',name: 'stageTwo',value: pJob.buildVariables.stageTwoStatus ],
                            [$class: 'StringParameterValue',name: 'stageThree',value: pJob.buildVariables.stageThreeStatus ]

                        ]
                    )
                }
            }
        }
    }
}
like image 39
3sky Avatar answered Sep 30 '22 19:09

3sky