As designed,
I have an upstream job that runs three downstream jobs in parallel to perform various types of testing (unit tests, integration tests, functional tests, etc). The behavior of the parallel step is currently problematic when combined with the default behavior of the build step (propagate: true). Suppose the following scenario occurs:
- The unit test job finishes first with a Result of SUCCESS.
- The integration test job finishes second with a Result of UNSTABLE.
- The functional test job finishes last with a Result of FAILURE.
With the current behavior as of workflow-cps 2.74 and (the as-yet-unreleased) pipeline-build-step 2.10, the upstream job's Result will be UNSTABLE, because the integration test job (which finishes before the functional test job) has a Result of UNSTABLE, even though the functional test job has a Result of FAILURE. While I understand that this is behaving as designed/documented, the current behavior isn't very conducive to my use case. In my use case, I want to report to the end user the "worst" of the downstream results in the result of the upstream job; i.e., given a set of downstream results of SUCCESS, UNSTABLE, and FAILURE, I want the upstream job to report FAILURE since it is the most serious of the three. Reporting UNSTABLE gives a false impression to the user because it hides the fact that a more serious failure occurred in one of the downstream jobs, simply because that failure occurred after a less serious failure in a different downstream job (which is irrelevant to the end user).
So far, I've been able to work around this by setting propagate: false and adding some hacky logic like this to my pipeline:
parallel buildSteps
def allNotBuilt = true
def seenUnstable = false
def seenFailure = false
buildResults.each { jobName, jobResult ->
if (jobResult.result != 'NOT_BUILT') {
allNotBuilt = false
if (jobResult.result == 'UNSTABLE') {
seenUnstable = true
}
if (jobResult.result == 'FAILURE' || jobResult.result == 'ABORTED') {
seenFailure = true
}
}
}
if (!allNotBuilt) {
if (seenUnstable && !seenFailure) {
currentBuild.result = 'UNSTABLE'
} else if (seenFailure) {
currentBuild.result = 'FAILURE'
}
} else {
currentBuild.result = 'NOT_BUILT'
}
This type of logic is gross. Ideally, I think Pipeline would natively support this use case, perhaps through some new type of functionality in the parallel step that examines the result in each branch and propagates the "worst" one to the overall build result of the upstream job. What do you think? (Note that I'm interested in helping to implement this, if we want to go in this direction.)
As designed, except that the main build should be set to UNSTABLE as well.