Skip to content

Commit de72dc2

Browse files
authored
Consider findWorstWarningBetween for branches of running builds (jenkinsci#806)
1 parent 8602de6 commit de72dc2

File tree

2 files changed

+207
-1
lines changed

2 files changed

+207
-1
lines changed

src/main/java/io/jenkins/plugins/pipelinegraphview/analysis/StatusAndTiming.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,12 @@ public static GenericStatus computeChunkStatus2(
282282
&& lastNode instanceof BlockEndNode) { // Check to see if all the action is on other branches
283283
BlockStartNode start = ((BlockEndNode) lastNode).getStartNode();
284284
if (start.getAction(ThreadNameAction.class) != null) {
285-
return (lastNode.getError() == null) ? GenericStatus.SUCCESS : GenericStatus.FAILURE;
285+
GenericStatus status = GenericStatus.SUCCESS;
286+
WarningAction warningAction = findWorstWarningBetween(start, lastNode);
287+
if (warningAction != null) {
288+
status = GenericStatus.fromResult(warningAction.getResult());
289+
}
290+
return (lastNode.getError() != null) ? GenericStatus.FAILURE : status;
286291
}
287292
}
288293

src/test/java/io/jenkins/plugins/pipelinegraphview/analysis/StatusAndTimingTest.java

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import static org.junit.jupiter.api.Assertions.assertTrue;
3636
import static org.junit.jupiter.api.Assertions.fail;
3737

38+
import hudson.AbortException;
3839
import hudson.model.Queue;
3940
import hudson.model.Result;
4041
import hudson.model.queue.QueueTaskFuture;
@@ -364,6 +365,206 @@ void testBasicParallelFail() throws Exception {
364365
assertEquals(totalBranchTiming, finalTiming.getTotalDurationMillis());
365366
}
366367

368+
@Issue("GH#794")
369+
@Test
370+
void testParallelFailInProgress() throws Exception {
371+
WorkflowJob job = j.jenkins.createProject(WorkflowJob.class, "ParallelFailsInProgress");
372+
job.setDefinition(new CpsFlowDefinition(
373+
"""
374+
pipeline {
375+
agent any
376+
stages {
377+
stage('Tests') {
378+
parallel {
379+
stage('Failure caught') {
380+
steps {
381+
catchError(buildResult: 'SUCCESS', catchInterruptions: false, stageResult: 'FAILURE') {
382+
semaphore 'catchError'
383+
}
384+
}
385+
}
386+
stage('Fails') {
387+
steps {
388+
semaphore 'error'
389+
}
390+
}
391+
stage('Passes') {
392+
steps {
393+
semaphore 'prewait'
394+
sleep 1
395+
semaphore 'wait'
396+
}
397+
}
398+
}
399+
}
400+
}
401+
}
402+
""",
403+
true));
404+
405+
/*
406+
Node dump follows, format:
407+
[ID]{parent,ids}(millisSinceStartOfRun) flowNodeClassName stepDisplayName [st=startId if a block end node]
408+
Action format:
409+
- actionClassName actionDisplayName
410+
------------------------------------------------------------------------------------------
411+
[2]{}FlowStartNode Start of Pipeline
412+
[3]{2}StepStartNode Allocate node : Start
413+
-LogStorageAction Console Output
414+
-QueueItemActionImpl null
415+
-WorkspaceActionImpl Workspace
416+
[4]{3}StepStartNode Allocate node : Body : Start
417+
-BodyInvocationAction null
418+
[5]{4}StepStartNode Stage : Start
419+
-LogStorageAction Console Output
420+
-ArgumentsActionImpl null
421+
[6]{5}StepStartNode Tests
422+
-BodyInvocationAction null
423+
-LabelAction Tests
424+
-TagsAction Tags
425+
[7]{6}StepStartNode Execute in parallel : Start
426+
-LogStorageAction Console Output
427+
[10]{7}StepStartNode Branch: Failure caught
428+
-BodyInvocationAction null
429+
-ParallelLabelAction Branch: Failure caught
430+
[11]{7}StepStartNode Branch: Fails
431+
-BodyInvocationAction null
432+
-ParallelLabelAction Branch: Fails
433+
-TagsAction Tags
434+
[12]{7}StepStartNode Branch: Passes
435+
-BodyInvocationAction null
436+
-ParallelLabelAction Branch: Passes
437+
[13]{10}StepStartNode Stage : Start
438+
-LogStorageAction Console Output
439+
-ArgumentsActionImpl null
440+
[14]{13}StepStartNode Failure caught
441+
-BodyInvocationAction null
442+
-LabelAction Failure caught
443+
[15]{11}StepStartNode Stage : Start
444+
-LogStorageAction Console Output
445+
-ArgumentsActionImpl null
446+
[16]{15}StepStartNode Fails
447+
-BodyInvocationAction null
448+
-LabelAction Fails
449+
-TagsAction Tags
450+
[17]{12}StepStartNode Stage : Start
451+
-LogStorageAction Console Output
452+
-ArgumentsActionImpl null
453+
[18]{17}StepStartNode Passes
454+
-BodyInvocationAction null
455+
-LabelAction Passes
456+
[19]{14}StepStartNode Catch error and set build result to failure : Start
457+
-LogStorageAction Console Output
458+
-ArgumentsActionImpl null
459+
[20]{19}StepStartNode Catch error and set build result to failure : Body : Start
460+
-BodyInvocationAction null
461+
[21]{16}StepAtomNode Test step
462+
-ArgumentsActionImpl null
463+
-LogStorageAction Console Output
464+
-ErrorAction failure
465+
[22]{18}StepAtomNode Test step
466+
-ArgumentsActionImpl null
467+
-LogStorageAction Console Output
468+
[23]{20}StepAtomNode Test step
469+
-ArgumentsActionImpl null
470+
-LogStorageAction Console Output
471+
-ErrorAction failure
472+
[24]{21}StepEndNode Stage : Body : End [st=16]
473+
-BodyInvocationAction null
474+
-ErrorAction failure
475+
[25]{22}StepAtomNode Sleep
476+
-ArgumentsActionImpl null
477+
-LogStorageAction Console Output
478+
[26]{23}StepEndNode Catch error and set build result to failure : Body : End [st=20]
479+
-BodyInvocationAction null
480+
-ErrorAction failure
481+
-LogStorageAction Console Output
482+
-WarningAction Warning
483+
[27]{24}StepEndNode Stage : End [st=15]
484+
-ErrorAction failure
485+
[28]{26}StepEndNode Catch error and set build result to failure : End [st=19]
486+
[29]{27}StepEndNode Execute in parallel : Body : End [st=11]
487+
-BodyInvocationAction null
488+
-ErrorAction failure
489+
-LogStorageAction Console Output
490+
[30]{28}StepEndNode Stage : Body : End [st=14]
491+
-BodyInvocationAction null
492+
[31]{30}StepEndNode Stage : End [st=13]
493+
[32]{31}StepEndNode Execute in parallel : Body : End [st=10]
494+
-BodyInvocationAction null
495+
[33]{25}StepAtomNode Test step
496+
-ArgumentsActionImpl null
497+
-LogStorageAction Console Output
498+
[34]{33}StepEndNode Stage : Body : End [st=18]
499+
-BodyInvocationAction null
500+
[35]{34}StepEndNode Stage : End [st=17]
501+
[36]{35}StepEndNode Execute in parallel : Body : End [st=12]
502+
-BodyInvocationAction null
503+
[37]{32,29,36}StepEndNode Execute in parallel : End [st=7]
504+
-ErrorAction failure
505+
[38]{37}StepEndNode Stage : Body : End [st=6]
506+
-BodyInvocationAction null
507+
-ErrorAction failure
508+
[39]{38}StepEndNode Stage : End [st=5]
509+
-ErrorAction failure
510+
[40]{39}StepEndNode Allocate node : Body : End [st=4]
511+
-BodyInvocationAction null
512+
-ErrorAction failure
513+
[41]{40}StepEndNode Allocate node : End [st=3]
514+
-ErrorAction failure
515+
-ErrorAction failure
516+
[42]{41}FlowEndNode End of Pipeline [st=2]
517+
-ErrorAction failure
518+
*/
519+
520+
WorkflowRun run = job.scheduleBuild2(0).waitForStart();
521+
SemaphoreStep.waitForStart("catchError/1", run);
522+
SemaphoreStep.failure("catchError/1", new AbortException("failure"));
523+
SemaphoreStep.waitForStart("error/1", run);
524+
SemaphoreStep.failure("error/1", new AbortException("failure"));
525+
SemaphoreStep.waitForStart("prewait/1", run);
526+
SemaphoreStep.success("prewait/1", null);
527+
SemaphoreStep.waitForStart("wait/1", run);
528+
529+
FlowExecution exec = run.getExecution();
530+
531+
// Failure Caught branch
532+
assertEquals(
533+
GenericStatus.FAILURE,
534+
StatusAndTiming.computeChunkStatus2(
535+
run, exec.getNode("7"), exec.getNode("10"), exec.getNode("32"), null));
536+
537+
// Failing branch
538+
assertEquals(
539+
GenericStatus.FAILURE,
540+
StatusAndTiming.computeChunkStatus2(
541+
run, exec.getNode("7"), exec.getNode("11"), exec.getNode("29"), null));
542+
543+
// In-progress Passing branch
544+
assertEquals(
545+
GenericStatus.IN_PROGRESS,
546+
StatusAndTiming.computeChunkStatus2(
547+
run, exec.getNode("7"), exec.getNode("12"), exec.getNode("33"), null));
548+
549+
// Check that branch statuses match
550+
List<BlockStartNode> parallelStarts =
551+
Arrays.asList((BlockStartNode) exec.getNode("10"), (BlockStartNode) exec.getNode("11"));
552+
List<FlowNode> parallelEnds = Arrays.asList(exec.getNode("32"), exec.getNode("29"));
553+
Map<String, GenericStatus> branchStatuses =
554+
StatusAndTiming.computeBranchStatuses2(run, exec.getNode("7"), parallelStarts, parallelEnds, null);
555+
556+
assertEquals(2, branchStatuses.size());
557+
String[] branches = {"Fails", "Failure caught"};
558+
List<String> outputBranchList = new ArrayList<>(branchStatuses.keySet());
559+
Collections.sort(outputBranchList);
560+
assertArrayEquals(branches, outputBranchList.toArray());
561+
assertEquals(GenericStatus.FAILURE, branchStatuses.get("Fails"));
562+
assertEquals(GenericStatus.FAILURE, branchStatuses.get("Failure caught"));
563+
564+
SemaphoreStep.success("wait/1", null);
565+
j.assertBuildStatus(Result.FAILURE, j.waitForCompletion(run));
566+
}
567+
367568
@Test
368569
void testInProgress() throws Exception {
369570
WorkflowJob job = j.jenkins.createProject(WorkflowJob.class, "Fails");

0 commit comments

Comments
 (0)