Skip to content

Commit e986853

Browse files
committed
fix JENKINS-68775 keep it simple, just use StageChunkFinder to dump a linear stages list
1 parent 6097257 commit e986853

File tree

4 files changed

+56
-82
lines changed

4 files changed

+56
-82
lines changed

splunk-devops-extend/pom.xml

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,6 @@
4141
<artifactId>pipeline-rest-api</artifactId>
4242
<version>2.8</version>
4343
</dependency>
44-
<dependency>
45-
<groupId>org.jenkins-ci.main</groupId>
46-
<artifactId>jenkins-test-harness</artifactId>
47-
<scope>test</scope>
48-
</dependency>
4944
<dependency>
5045
<groupId>${project.groupId}</groupId>
5146
<artifactId>splunk-devops</artifactId>
@@ -88,7 +83,7 @@
8883
<dependency>
8984
<groupId>org.jenkins-ci.plugins.workflow</groupId>
9085
<artifactId>workflow-basic-steps</artifactId>
91-
<version>2.4</version>
86+
<version>2.24</version>
9287
<scope>test</scope>
9388
</dependency>
9489
<dependency>
@@ -104,6 +99,17 @@
10499
<version>1.2.1</version>
105100
<scope>test</scope>
106101
</dependency>
107-
102+
<dependency>
103+
<groupId>org.jenkins-ci.plugins</groupId>
104+
<artifactId>junit</artifactId>
105+
<version>1.47</version>
106+
<scope>test</scope>
107+
</dependency>
108+
<dependency>
109+
<groupId>javax.mail</groupId>
110+
<artifactId>mail</artifactId>
111+
<version>1.4.4</version>
112+
<scope>test</scope>
113+
</dependency>
108114
</dependencies>
109115
</project>

splunk-devops-extend/src/main/java/com/splunk/splunkjenkins/PipelineRunSupport.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,21 @@
88
import org.apache.commons.lang.StringUtils;
99
import org.jenkinsci.plugins.workflow.flow.FlowExecution;
1010
import org.jenkinsci.plugins.workflow.graphanalysis.ForkScanner;
11-
import org.jenkinsci.plugins.workflow.graphanalysis.LabelledChunkFinder;
1211
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
12+
import org.jenkinsci.plugins.workflow.pipelinegraphanalysis.StageChunkFinder;
1313

1414
import java.util.ArrayList;
1515
import java.util.Collection;
1616
import java.util.HashMap;
1717
import java.util.List;
1818
import java.util.Map;
19+
import java.util.logging.Level;
20+
import java.util.logging.Logger;
1921

2022
@SuppressWarnings("unused")
2123
@Extension
2224
public class PipelineRunSupport extends LoggingJobExtractor<WorkflowRun> {
25+
private static final Logger LOG = Logger.getLogger(PipelineRunSupport.class.getName());
2326

2427
@Override
2528
public Map<String, Object> extract(WorkflowRun workflowRun, boolean jobCompleted) {
@@ -28,28 +31,24 @@ public Map<String, Object> extract(WorkflowRun workflowRun, boolean jobCompleted
2831
FlowExecution execution = workflowRun.getExecution();
2932
if (execution != null) {
3033
WorkspaceChunkVisitor visitor = new WorkspaceChunkVisitor(workflowRun);
31-
//LabelledChunkFinder to find stages and parallel branches
32-
ForkScanner.visitSimpleChunks(execution.getCurrentHeads(), visitor, new LabelledChunkFinder());
33-
Collection<StageNodeExt> nodes = visitor.getStages();
34+
ForkScanner.visitSimpleChunks(execution.getCurrentHeads(), visitor, new StageChunkFinder());
35+
Collection<StageNodeExt> stages = visitor.getStages();
36+
LOG.log(Level.FINE, "found stages count", stages.size());
3437
Map<String, String> execNodes = visitor.getWorkspaceNodes();
35-
Map<String, String> parallelNodeStages = visitor.getParallelNodes();
36-
if (!nodes.isEmpty()) {
37-
List<Map> labeledChunks = new ArrayList<Map>(nodes.size());
38-
for (StageNodeExt stageNodeExt : nodes) {
38+
if (!stages.isEmpty()) {
39+
List<Map> labeledStages = new ArrayList<Map>(stages.size());
40+
for (StageNodeExt stageNodeExt : stages) {
3941
Map<String, Object> stage = flowNodeToMap(stageNodeExt, execNodes);
4042
List<Map<String, Object>> children = new ArrayList<>();
4143
for (FlowNodeExt childNode : stageNodeExt.getStageFlowNodes()) {
4244
children.add(flowNodeToMap(childNode, execNodes));
4345
}
4446
if (!children.isEmpty()) {
4547
stage.put("children", children);
46-
if (parallelNodeStages.containsKey(stageNodeExt.getId())) {
47-
stage.put("enclosing_stage", parallelNodeStages.get(stageNodeExt.getId()));
48-
}
4948
}
50-
labeledChunks.add(stage);
49+
labeledStages.add(stage);
5150
}
52-
info.put("stages", labeledChunks);
51+
info.put("stages", labeledStages);
5352
}
5453
}
5554
SplunkTaskListenerFactory.removeCache(workflowRun);
@@ -77,7 +76,7 @@ private Map<String, Object> flowNodeToMap(FlowNodeExt node, Map<String, String>
7776
result.put("arguments", node.getParameterDescription());
7877
String execNodeName = node.getExecNode();
7978
if (StringUtils.isEmpty(execNodeName)) {
80-
//lockup the workspace nodes
79+
//lookup the workspace nodes
8180
execNodeName = execNodes.get(node.getId());
8281
}
8382
result.put("exec_node", execNodeName);

splunk-devops-extend/src/main/java/com/splunk/splunkjenkins/WorkspaceChunkVisitor.java

Lines changed: 1 addition & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.cloudbees.workflow.rest.external.ChunkVisitor;
44
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
55
import org.apache.commons.lang.StringUtils;
6-
import org.jenkinsci.plugins.workflow.actions.ArgumentsAction;
76
import org.jenkinsci.plugins.workflow.actions.WorkspaceAction;
87
import org.jenkinsci.plugins.workflow.cps.nodes.StepEndNode;
98
import org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode;
@@ -27,13 +26,8 @@ public class WorkspaceChunkVisitor extends ChunkVisitor {
2726
private static final Logger LOG = Logger.getLogger(WorkspaceChunkVisitor.class.getName());
2827
// key is node id, value is jenkins worker node name
2928
Map<String, String> workspaceNodes = new HashMap<>();
30-
// key is flowode id, value is parent stage id
31-
Map<String, String> parallelNodes = new HashMap<>();
3229
String execNodeName = null;
3330
String execNodeStartId = null;
34-
String enclosingStageName = null;
35-
String enclosingStageId = null;
36-
String currentParallelNodeStartId = "";
3731

3832
public WorkspaceChunkVisitor(@NonNull WorkflowRun run) {
3933
super(run);
@@ -44,38 +38,12 @@ public void atomNode(@CheckForNull FlowNode before, @NonNull FlowNode atomNode,
4438
//reverse-order, traverse from end node to start node
4539
try {
4640
recordExecNode(atomNode);
47-
recordStageNode(atomNode);
48-
recordParallelNode(scan);
4941
} catch (Exception ex) {
5042
LOG.log(Level.WARNING, "failed to extract pipeline info", ex);
5143
}
5244
super.atomNode(before, atomNode, after, scan);
5345
}
5446

55-
/**
56-
* store stage node info
57-
*
58-
* @param atomNode flow node
59-
*/
60-
private void recordStageNode(FlowNode atomNode) {
61-
// record stage name for parallel run inside stage
62-
if (enclosingStageName == null) {
63-
StepStartNode stageNode = getPipelineBlockBoundaryStartNode(atomNode, "stage");
64-
if (stageNode != null) {
65-
ArgumentsAction argumentsAction = stageNode.getAction(ArgumentsAction.class);
66-
if (argumentsAction != null) {
67-
enclosingStageName = "" + argumentsAction.getArgumentValue("name");
68-
} else {
69-
enclosingStageName = "";
70-
}
71-
enclosingStageId = stageNode.getId();
72-
LOG.log(Level.FINE, "found stage node id={0}, name={1}", new String[]{enclosingStageId, enclosingStageName});
73-
}
74-
} else if (atomNode instanceof StepStartNode && atomNode.getId().equals(enclosingStageId)) {
75-
enclosingStageName = null;
76-
}
77-
}
78-
7947
/**
8048
* store the jenkins node name where pipeline ran
8149
*
@@ -106,30 +74,7 @@ private void recordExecNode(FlowNode atomNode) {
10674
}
10775

10876
/**
109-
* store parallel node info
110-
*
111-
* @param scan Scanner
112-
*/
113-
@SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE")
114-
private void recordParallelNode(@NonNull ForkScanner scan) {
115-
if (scan.getCurrentParallelStartNode() != null) {
116-
//store parallel node start id
117-
String nodeId = scan.getCurrentParallelStartNode().getId();
118-
if (nodeId != null && !nodeId.equals(currentParallelNodeStartId)) {
119-
currentParallelNodeStartId = nodeId;
120-
//hacky way to calc the parallelBlockNodeId
121-
try {
122-
String parallelBlockId = "" + (1 + Integer.parseInt(nodeId));
123-
parallelNodes.put(parallelBlockId, enclosingStageName);
124-
} catch (NumberFormatException ex) {
125-
//ignore
126-
}
127-
}
128-
}
129-
}
130-
131-
/**
132-
* Check whether it is an enclose functional node (with BodyInvocationAction)
77+
* Check whether it is an enclosed functional node (with BodyInvocationAction)
13378
*
13479
* @param atomNode
13580
* @param functionName
@@ -161,8 +106,4 @@ private StepStartNode getPipelineBlockBoundaryStartNode(FlowNode atomNode, Strin
161106
public Map<String, String> getWorkspaceNodes() {
162107
return workspaceNodes;
163108
}
164-
165-
public Map<String, String> getParallelNodes() {
166-
return parallelNodes;
167-
}
168109
}

splunk-devops-extend/src/test/java/com/splunk/splunkjenkins/StageStepNodesTest.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ public class StageStepNodesTest {
3131
" echo \"hello\"\n" +
3232
" }\n" +
3333
"}";
34+
private String nestedStage = "node{\n" +
35+
" stage('build') {\n" +
36+
" stage('linux'){\n" +
37+
" echo \"hello\"\n" +
38+
" }\n" +
39+
" stage('windows'){\n" +
40+
" echo \"hello\"\n" +
41+
" stage('build c'){\n" +
42+
" echo \"hello\"\n" +
43+
" }\n" +
44+
" }\n" +
45+
" }\n" +
46+
"}";
3447

3548
@Before
3649
public void setUp() throws Exception {
@@ -43,7 +56,7 @@ public void testStageNodes() throws Exception {
4356
DumbSlave node = r.createOnlineSlave(new LabelAtom("ci-1"));
4457
DumbSlave node1 = r.createOnlineSlave(new LabelAtom("ci-2"));
4558
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "stage-node-job");
46-
p.setDefinition(new CpsFlowDefinition(jobScript,true));
59+
p.setDefinition(new CpsFlowDefinition(jobScript, true));
4760
WorkflowRun b1 = r.assertBuildStatusSuccess(p.scheduleBuild2(0));
4861
assertFalse(b1.isBuilding());
4962
r.assertLogContains("hello", b1);
@@ -52,4 +65,19 @@ public void testStageNodes() throws Exception {
5265
verifySplunkSearchResult("\"stages{}.children{}.exec_node\"=\"" + node.getNodeName() + "\"", startTime, 1);
5366
verifySplunkSearchResult("\"stages{}.children{}.exec_node\"=\"" + node1.getNodeName() + "\"", startTime, 1);
5467
}
68+
69+
@Test
70+
public void testFlattenStageResult() throws Exception {
71+
long startTime = System.currentTimeMillis();
72+
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "nested-stage-job");
73+
p.setDefinition(new CpsFlowDefinition(nestedStage, true));
74+
WorkflowRun b1 = r.assertBuildStatusSuccess(p.scheduleBuild2(0));
75+
assertFalse(b1.isBuilding());
76+
r.assertLogContains("hello", b1);
77+
assertTrue(b1.getDuration() > 0);
78+
//check stage count
79+
verifySplunkSearchResult("type=completed build_url=" + b1.getUrl() + "|spath output=stages path=\"stages{}\"" +
80+
"| mvexpand stages" +
81+
"| table stages", startTime, 4);
82+
}
5583
}

0 commit comments

Comments
 (0)