问题
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.
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.
回答1:
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)
回答2:
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 ]
]
)
}
}
}
}
}
来源:https://stackoverflow.com/questions/51490771/access-which-stage-failed-in-previous-jenkins-build