Skip to content

Commit 5904b09

Browse files
authored
Fix nested layout for parallel block with only skipped children (#1314)
1 parent 50d41d7 commit 5904b09

6 files changed

Lines changed: 2128 additions & 534 deletions

File tree

src/main/frontend/pipeline-graph-view/pipeline-graph/main/NestedPipelineGraphLayout.spec.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,18 @@ describe("NestedPipelineGraphLayout", () => {
131131
});
132132
});
133133

134+
describe("gh1286_wrapped_two_parallel_last_all_skipped.jenkinsfile", () => {
135+
const raw =
136+
'[{"name":"Wrapper","state":"success","id":"4","type":"STAGE","children":[{"name":"one","state":"success","id":"6","type":"STAGE","children":[{"name":"nested 1","state":"success","id":"9","type":"PARALLEL","children":[]},{"name":"nested 2","state":"success","id":"10","type":"PARALLEL","children":[]}]},{"name":"two","state":"success","id":"17","type":"STAGE","children":[{"name":"Skipped 1","state":"skipped","id":"20","type":"PARALLEL","children":[]},{"name":"Skipped 2","state":"skipped","id":"21","type":"PARALLEL","children":[]}]}]},{"name":"Next","state":"success","id":"38","type":"STAGE","children":[]}]';
137+
138+
it("should render layout", () => {
139+
shouldMatchSnapshot(raw, false);
140+
});
141+
it("should render collapsed layout", () => {
142+
shouldMatchSnapshot(raw, true);
143+
});
144+
});
145+
134146
describe("selective collapse", () => {
135147
const raw =
136148
'[{"name":"Non-Parallel Stage","state":"success","id":"6","type":"STAGE","children":[]},{"name":"Parallel Stage","state":"success","id":"12","type":"STAGE","children":[{"name":"Branch A","state":"success","id":"16","type":"PARALLEL","children":[]},{"name":"Branch B","state":"success","id":"17","type":"PARALLEL","children":[]},{"name":"Branch C","state":"success","id":"18","type":"PARALLEL","children":[{"name":"Nested 1","state":"success","id":"26","type":"STAGE","children":[]},{"name":"Nested 2","state":"success","id":"42","type":"STAGE","children":[]}]}]},{"name":"Skipped stage","state":"skipped","id":"54","type":"STAGE","children":[]}]';
@@ -155,12 +167,10 @@ function leanEdge(full: ConnectionEdge): ConnectionEdge {
155167
x: full.x,
156168
y: full.y,
157169
key: full.key,
158-
type: full.type,
159170
};
160171
// Cherry-pick truthy fields that are relevant for connections.
161172
if (full.firstChildIsSkipped) lean.firstChildIsSkipped = true;
162173
if (full.isHidden) lean.isHidden = true;
163-
if (full.isParallel) lean.isParallel = true;
164174
if (full.isPlaceholder) lean.isPlaceholder = true;
165175
if (full.isSkipped) lean.isSkipped = true;
166176
return lean;

src/main/frontend/pipeline-graph-view/pipeline-graph/main/NestedPipelineGraphLayout.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ function buildGraphNested(
263263
childNode.shiftX += layout.nodeSpacingH;
264264
childNode.width += layout.nodeSpacingH;
265265
}
266+
childNode.allChildrenSkipped =
267+
childNode.hasParallel && !childNode.children.some((c) => !c.isSkipped);
266268
node.children.push(childNode);
267269
}
268270
if (node.hasParallel) {
@@ -375,6 +377,15 @@ function computeTailNodes(
375377
return [node];
376378
}
377379
if (node.hasParallel) {
380+
if (node.allChildrenSkipped) {
381+
// Special case: a regular connection will be added around all the children.
382+
connections.push({
383+
sourceNodes: [node],
384+
destinationNodes: [],
385+
skippedNodes: [],
386+
hasBranchLabels: false,
387+
});
388+
}
378389
return node.children.flatMap((child) =>
379390
computeTailNodes(connections, child),
380391
);
@@ -388,7 +399,7 @@ function computeTailNodes(
388399
ignoreSkipped?: boolean,
389400
) => {
390401
for (const node of tailNodes) {
391-
if (ignoreSkipped || !node.isSkipped) {
402+
if (ignoreSkipped || !node.isSkipped || node.isParallel) {
392403
sourceNodes.add(node);
393404
} else {
394405
skippedNodes.add(node);
@@ -398,7 +409,7 @@ function computeTailNodes(
398409
const destinationNodes = destination.hasParallel
399410
? destination.children
400411
: [destination];
401-
if (!destinationNodes.some((n) => !n.isSkipped)) {
412+
if (!destinationNodes.some((n) => !n.isSkipped || n.isParallel)) {
402413
for (const node of destinationNodes) skippedNodes.add(node);
403414
return;
404415
}
@@ -583,6 +594,7 @@ function printDebugInfo(
583594
}
584595

585596
export function removeFalseOptionalGraphNodeFlags(node: GraphNode) {
597+
if (!node.allChildrenSkipped) delete node.allChildrenSkipped;
586598
if (!node.firstChildIsSkipped) delete node.firstChildIsSkipped;
587599
if (!node.hasBigLabel) delete node.hasBigLabel;
588600
if (!node.hasBranchLabel) delete node.hasBranchLabel;

src/main/frontend/pipeline-graph-view/pipeline-graph/main/PipelineGraphModel.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ export type GraphNode = {
107107
width: number;
108108
shiftY: number;
109109
height: number;
110+
allChildrenSkipped?: boolean;
110111
isHidden?: boolean;
111112
isParallel?: boolean;
112113
isSkipped?: boolean;
@@ -131,12 +132,14 @@ export interface ConnectionEdge {
131132
x: number;
132133
y: number;
133134
key: string;
134-
type: NodeInfo["type"];
135135
firstChildIsSkipped?: boolean;
136136
isHidden?: boolean;
137-
isParallel?: boolean;
138137
isPlaceholder?: boolean;
139138
isSkipped?: boolean;
139+
140+
allChildrenSkipped?: boolean;
141+
height?: number;
142+
width?: number;
140143
}
141144

142145
export interface CompositeConnection {

0 commit comments

Comments
 (0)