Issue
I have a simple scripted pipeline as follows -
import hudson.model.*
import groovy.json.*
def map = [:]
map['second'] = {
build job: "childPipeline1", propagate: true, wait: true
}
map['third'] = {
build job: "childPipeline2", propagate: true, wait: true
}
try {
parallel map
}catch(Exception e) {
e.getCauses().each {
echo "${it.getShortDescription()}"
}
}
Actual map creation code is dynamic and looks something like this -
map["${substage}_${subdir}"] = {build job: "ci_pipeline_${substage}${jobSuffix}", parameters: downstreamParams[subdir], propagate: true}
When I execute this, I expect that stages 2 and 3 will fail (simulated) and when I catch the Exception, I get a org.jenkinsci.plugins.workflow.steps.FlowInterruptedException
with just one cause element in the cause list -
[Pipeline] Start of Pipeline
[Pipeline] parallel
[Pipeline] { (Branch: second)
[Pipeline] { (Branch: third)
[Pipeline] build (Building childPipeline1)
Scheduling project: childPipeline1
[Pipeline] build (Building childPipeline2)
Scheduling project: childPipeline2
Starting building: childPipeline1 #1333
Starting building: childPipeline2 #148
[Pipeline] }
Failed in branch third
[Pipeline] }
Failed in branch second
[Pipeline] // parallel
[Pipeline] echo
childPipeline2 #148 completed with status FAILURE (propagate: false to ignore)
[Pipeline] End of Pipeline
Finished: SUCCESS
However, when I throw the exception i.e., throw e
, I can see all the failure parallel jobs in the Jenkins web console log as below -
[Pipeline] Start of Pipeline
[Pipeline] parallel
[Pipeline] { (Branch: second)
[Pipeline] { (Branch: third)
[Pipeline] build (Building childPipeline1)
Scheduling project: childPipeline1
[Pipeline] build (Building childPipeline2)
Scheduling project: childPipeline2
Starting building: childPipeline1 #1296
Starting building: childPipeline2 #126
[Pipeline] }
Failed in branch third
[Pipeline] }
Failed in branch second
[Pipeline] // parallel
[Pipeline] End of Pipeline
childPipeline2 #126 completed with status FAILURE (propagate: false to ignore)
childPipeline1 #1296 completed with status FAILURE (propagate: false to ignore)
Finished: FAILURE
I am trying to get the result -
childPipeline2 #126 completed with status FAILURE (propagate: false to ignore)
childPipeline1 #1296 completed with status FAILURE (propagate: false to ignore)
and extract just the failed pipeline(s) name and the respective build numbers e.g., childPipeline1: 126
and childPipeline2: 1296
as in the Jenkins web console log (i.e., with all causes; 2 in this example) into a variable in my scripted pipeline.
Please help/guide me with this.
TIA.
Dynamic parallel map runner impl (based on @Yuri G's answer) is as follows -
map["${substage}_${subdir}"] = { try { build job: "ci_pipeline_${substage}${jobSuffix}", parameters: downstreamParams[subdir], propagate: true }catch(Exception e) { e.getCauses().each {echo "${it.getShortDescription()}"}}
Solution
You can catch the error in every branch of parallel execution:
import hudson.model.*
import groovy.json.*
def map = [:]
map['second'] = {
try {
build job: "childPipeline1", propagate: true, wait: true
}catch(Exception e) {
e.getCauses().each {
echo "${it.getShortDescription()}"
}
throw e
}
}
map['third'] = {
try{
build job: "childPipeline2", propagate: true, wait: true
}catch(Exception e) {
e.getCauses().each {
echo "${it.getShortDescription()}"
}
throw e
}
}
try {
parallel map
}catch(Exception e) {
e.getCauses().each {
echo "${it.getShortDescription()}"
}
}
Answered By - Yuri G.