Skip to content

Commit 7d02674

Browse files
use ABORTED icon color for interrupted steps
parallel() aborts branch execution when failFast == true and another branch failed. In this case RED color is used in 'Pipeline Steps' view. It makes more difficult to find real reason of failure because some of red dots are misleading. With this change we use BallColor.ABORTED when FlowInterruptedException is the reason of step failure. Thanks to this user can easier find root cause of build failure. Signed-off-by: Artur Harasimiuk <artur.harasimiuk@intel.com>
1 parent c3f9c01 commit 7d02674

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

src/main/java/org/jenkinsci/plugins/workflow/graph/FlowNode.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.jenkinsci.plugins.workflow.flow.FlowExecution;
5252
import org.jenkinsci.plugins.workflow.graphanalysis.FlowScanningUtils;
5353
import org.jenkinsci.plugins.workflow.graphanalysis.NodeStepTypePredicate;
54+
import org.jenkinsci.plugins.workflow.steps.FlowInterruptedException;
5455
import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
5556
import org.kohsuke.accmod.Restricted;
5657
import org.kohsuke.accmod.restrictions.DoNotUse;
@@ -279,7 +280,17 @@ public String getDisplayFunctionName() {
279280
*/
280281
@Exported
281282
public BallColor getIconColor() {
282-
BallColor c = getError()!=null ? BallColor.RED : BallColor.BLUE;
283+
ErrorAction error = getError();
284+
BallColor c = null;
285+
if(error != null) {
286+
if(error.getError() instanceof FlowInterruptedException) {
287+
c = BallColor.ABORTED;
288+
} else {
289+
c = BallColor.RED;
290+
}
291+
} else {
292+
c = BallColor.BLUE;
293+
}
283294
if (isActive()) {
284295
c = c.anime();
285296
}

src/test/java/org/jenkinsci/plugins/workflow/graph/FlowNodeTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424

2525
package org.jenkinsci.plugins.workflow.graph;
2626

27+
import hudson.model.BallColor;
28+
import hudson.model.Result;
29+
2730
import java.lang.reflect.Method;
2831
import java.text.MessageFormat;
2932
import java.util.ArrayList;
@@ -38,22 +41,26 @@
3841
import org.jenkinsci.plugins.workflow.flow.FlowExecution;
3942
import org.jenkinsci.plugins.workflow.graphanalysis.DepthFirstScanner;
4043
import org.jenkinsci.plugins.workflow.graphanalysis.FlowScanningUtils;
44+
import org.jenkinsci.plugins.workflow.graphanalysis.NodeStepTypePredicate;
4145
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
4246
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
4347
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
4448
import org.junit.Ignore;
4549
import org.junit.Test;
4650

51+
import static org.hamcrest.Matchers.hasSize;
4752
import static org.junit.Assert.*;
4853
import org.junit.Rule;
4954
import org.junit.runners.model.Statement;
5055
import org.jvnet.hudson.test.Issue;
5156
import org.jvnet.hudson.test.LoggerRule;
57+
import org.jvnet.hudson.test.JenkinsRule;
5258
import org.jvnet.hudson.test.RestartableJenkinsRule;
5359

5460
public class FlowNodeTest {
5561

5662
@Rule public RestartableJenkinsRule rr = new RestartableJenkinsRule();
63+
@Rule public JenkinsRule r = new JenkinsRule();
5764
@Rule public LoggerRule logging = new LoggerRule().record(FlowNode.class, Level.FINER);
5865

5966
@Issue("JENKINS-38223")
@@ -408,6 +415,27 @@ public void evaluate() throws Throwable {
408415
});
409416
}
410417

418+
@Test public void useAbortedStatusWhenFailFast() throws Exception {
419+
WorkflowJob job = r.jenkins.createProject(WorkflowJob.class, "p");
420+
job.setDefinition(new CpsFlowDefinition(
421+
"jobs = [failFast:true]\n" +
422+
"jobs['one'] = {\n" +
423+
" sleep 5\n" +
424+
"}\n" +
425+
"jobs['two'] = {\n" +
426+
" error 'failing'\n" +
427+
"}\n" +
428+
"parallel jobs", true));
429+
WorkflowRun b = r.assertBuildStatus(Result.FAILURE, job.scheduleBuild2(0).get());
430+
431+
List<FlowNode> coreStepNodes = new DepthFirstScanner().filteredNodes(b.getExecution(), new NodeStepTypePredicate("sleep"));
432+
assertThat(coreStepNodes, hasSize(1));
433+
assertEquals("sleep", coreStepNodes.get(0).getDisplayFunctionName());
434+
assertNotNull(coreStepNodes.get(0).getError());
435+
assertNotNull(coreStepNodes.get(0).getError().getError());
436+
assertEquals(BallColor.ABORTED, coreStepNodes.get(0).getIconColor());
437+
}
438+
411439
private void assertExpectedEnclosing(FlowExecution execution, String nodeId, String enclosingId) throws Exception {
412440
FlowNode node = execution.getNode(nodeId);
413441
assertNotNull(node);

0 commit comments

Comments
 (0)