Skip to content

Commit e7d9055

Browse files
authored
feat: non-destructive updates to PR body (#51)
* Fixes the action deleting parts of the description when there is another list in the body * all fixes * update editorconfig checker config to keep up with current version * dist * update readme * README again * use graph depth when generating output instead of branch type * cleanup and renaming
1 parent 746f7a5 commit e7d9055

File tree

7 files changed

+3560
-251
lines changed

7 files changed

+3560
-251
lines changed

.editorconfig-checker

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
{
2-
"Version": "v3.0.3",
2+
"Version": "v3.1.2",
33
"Verbose": false,
4-
"Format": "",
54
"Debug": false,
65
"IgnoreDefaults": false,
7-
"SpacesAftertabs": false,
6+
"SpacesAfterTabs": false,
87
"NoColor": false,
98
"Exclude": [],
109
"AllowedContentTypes": [],

README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,20 @@ that contains `branch-stack` inside of it:
7777
```
7878

7979
The action will look for this comment and insert the visualization underneath the comment
80-
when it runs. It will also leave behind the comment, so that the next time it runs, it will
80+
when it runs.
81+
82+
> [!WARNING]
83+
> Any checklist or list directly after the comment will have it's syntax changed to
84+
> the asterisk list format (`*`), rather than the dash list format (`-`). This should
85+
> not affect the readme in any other way.
86+
87+
It will also leave behind the comment, so that the next time it runs, it will
8188
be able to use it again to update the visualization:
8289

8390
```md
8491
## Stack
8592
86-
<!-- branch-stack --> 👈 Still there!
87-
88-
- `main`
93+
- `main` <!-- branch-stack --> 👈 Still there!
8994
- \#1 :point_left:
9095
- \#2
9196

dist/index.js

Lines changed: 101 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -43035,6 +43035,7 @@ var remark2 = remark().use(remarkGfm).data("settings", {
4303543035
});
4303643036

4303743037
// src/main.ts
43038+
var ANCHOR = "<!-- branch-stack -->";
4303843039
async function main({
4303943040
octokit,
4304043041
currentPullRequest,
@@ -43087,64 +43088,7 @@ async function main({
4308743088
repoGraph.mergeDirectedEdge(openPullRequest.base.ref, openPullRequest.head.ref);
4308843089
});
4308943090
const terminatingRefs = [mainBranch, ...perennialBranches];
43090-
const getStackGraph = (pullRequest) => {
43091-
const stackGraph2 = repoGraph.copy();
43092-
stackGraph2.setNodeAttribute(pullRequest.head.ref, "isCurrent", true);
43093-
(0, import_graphology_traversal.bfsFromNode)(
43094-
stackGraph2,
43095-
pullRequest.head.ref,
43096-
(ref, attributes) => {
43097-
stackGraph2.setNodeAttribute(ref, "shouldPrint", true);
43098-
return attributes.type === "perennial" || attributes.type === "orphan-branch";
43099-
},
43100-
{ mode: "inbound" }
43101-
);
43102-
(0, import_graphology_traversal.dfsFromNode)(
43103-
stackGraph2,
43104-
pullRequest.head.ref,
43105-
(ref) => {
43106-
stackGraph2.setNodeAttribute(ref, "shouldPrint", true);
43107-
},
43108-
{ mode: "outbound" }
43109-
);
43110-
stackGraph2.forEachNode((ref, stackNode) => {
43111-
if (!stackNode.shouldPrint) {
43112-
stackGraph2.dropNode(ref);
43113-
}
43114-
});
43115-
return stackGraph2;
43116-
};
43117-
const getOutput = (graph) => {
43118-
const lines = [];
43119-
const rootRef = (0, import_graphology_dag.topologicalSort)(graph)[0];
43120-
(0, import_graphology_traversal.dfsFromNode)(
43121-
graph,
43122-
rootRef,
43123-
(_, stackNode, depth) => {
43124-
if (!stackNode.shouldPrint)
43125-
return;
43126-
const tabSize = depth * 2;
43127-
const indentation = new Array(tabSize).fill(" ").join("");
43128-
let line = indentation;
43129-
if (stackNode.type === "orphan-branch") {
43130-
line += `- \`${stackNode.ref}\` - :warning: No PR associated with branch`;
43131-
}
43132-
if (stackNode.type === "perennial" && terminatingRefs.includes(stackNode.ref)) {
43133-
line += `- \`${stackNode.ref}\``;
43134-
}
43135-
if (stackNode.type === "pull-request") {
43136-
line += `- #${stackNode.number}`;
43137-
}
43138-
if (stackNode.isCurrent) {
43139-
line += " :point_left:";
43140-
}
43141-
lines.push(line);
43142-
},
43143-
{ mode: "directed" }
43144-
);
43145-
return lines.join("\n");
43146-
};
43147-
const stackGraph = getStackGraph(currentPullRequest);
43091+
const stackGraph = getStackGraph(currentPullRequest, repoGraph);
4314843092
const shouldSkip = () => {
4314943093
const neighbors = stackGraph.neighbors(currentPullRequest.head.ref);
4315043094
const allPerennialBranches = stackGraph.filterNodes(
@@ -43162,8 +43106,8 @@ async function main({
4316243106
}
4316343107
jobs.push(async () => {
4316443108
core.info(`Updating stack details for PR #${stackNode.number}`);
43165-
const stackGraph2 = getStackGraph(stackNode);
43166-
const output = getOutput(stackGraph2);
43109+
const stackGraph2 = getStackGraph(stackNode, repoGraph);
43110+
const output = getOutput(stackGraph2, terminatingRefs);
4316743111
let description = stackNode.body ?? "";
4316843112
description = updateDescription({
4316943113
description,
@@ -43178,14 +43122,106 @@ async function main({
4317843122
});
4317943123
await Promise.allSettled(jobs.map((job) => job()));
4318043124
}
43125+
function getStackGraph(pullRequest, repoGraph) {
43126+
const stackGraph = repoGraph.copy();
43127+
stackGraph.setNodeAttribute(pullRequest.head.ref, "isCurrent", true);
43128+
(0, import_graphology_traversal.bfsFromNode)(
43129+
stackGraph,
43130+
pullRequest.head.ref,
43131+
(ref, attributes) => {
43132+
stackGraph.setNodeAttribute(ref, "shouldPrint", true);
43133+
return attributes.type === "perennial" || attributes.type === "orphan-branch";
43134+
},
43135+
{ mode: "inbound" }
43136+
);
43137+
(0, import_graphology_traversal.dfsFromNode)(
43138+
stackGraph,
43139+
pullRequest.head.ref,
43140+
(ref) => {
43141+
stackGraph.setNodeAttribute(ref, "shouldPrint", true);
43142+
},
43143+
{ mode: "outbound" }
43144+
);
43145+
stackGraph.forEachNode((ref, stackNode) => {
43146+
if (!stackNode.shouldPrint) {
43147+
stackGraph.dropNode(ref);
43148+
}
43149+
});
43150+
return stackGraph;
43151+
}
43152+
function getOutput(graph, terminatingRefs) {
43153+
const lines = [];
43154+
const rootRef = (0, import_graphology_dag.topologicalSort)(graph)[0];
43155+
(0, import_graphology_traversal.dfsFromNode)(
43156+
graph,
43157+
rootRef,
43158+
(_, stackNode, depth) => {
43159+
if (!stackNode.shouldPrint)
43160+
return;
43161+
const tabSize = depth * 2;
43162+
const indentation = new Array(tabSize).fill(" ").join("");
43163+
let line = indentation;
43164+
if (stackNode.type === "orphan-branch") {
43165+
line += `- \`${stackNode.ref}\` - :warning: No PR associated with branch`;
43166+
}
43167+
if (stackNode.type === "perennial" && terminatingRefs.includes(stackNode.ref)) {
43168+
line += `- \`${stackNode.ref}\``;
43169+
}
43170+
if (stackNode.type === "pull-request") {
43171+
line += `- #${stackNode.number}`;
43172+
}
43173+
if (stackNode.isCurrent) {
43174+
line += " :point_left:";
43175+
}
43176+
if (depth === 0) {
43177+
line += ` ${ANCHOR}`;
43178+
}
43179+
lines.push(line);
43180+
},
43181+
{ mode: "directed" }
43182+
);
43183+
return lines.join("\n");
43184+
}
43185+
var findInlineAnchorIndex = (descriptionAst) => {
43186+
const listChildren = descriptionAst.children.map((node2, originalIndex) => [node2, originalIndex]).filter(([node2]) => node2.type === "list");
43187+
const [, listChildWithAnchorIdx] = listChildren.find(([node2]) => {
43188+
const listItems = node2.children;
43189+
const maybeFirstListItemParagraph = listItems[0]?.children[0];
43190+
return maybeFirstListItemParagraph?.children.some(
43191+
(node3) => node3.type === "html" && node3.value === ANCHOR
43192+
);
43193+
}) ?? [];
43194+
return listChildWithAnchorIdx;
43195+
};
43196+
var isListType = (listAstNode) => listAstNode?.type === "list";
43197+
var nextChildIsListAndContainsPrs = (listAst) => {
43198+
if (!listAst || !isListType(listAst))
43199+
return false;
43200+
if (listAst.children.length > 1) {
43201+
return false;
43202+
}
43203+
const subList = listAst.children[0]?.children[1];
43204+
if (!isListType(subList))
43205+
return false;
43206+
const firstItemParagraphNode = subList.children[0]?.children[0];
43207+
if (firstItemParagraphNode?.type !== "paragraph")
43208+
return false;
43209+
const sublistFirstItemParagraphText = firstItemParagraphNode.children[0];
43210+
if (sublistFirstItemParagraphText?.type !== "text")
43211+
return false;
43212+
return /^#\d+/.test(sublistFirstItemParagraphText.value);
43213+
};
4318143214
function updateDescription({
4318243215
description,
4318343216
output
4318443217
}) {
43185-
const ANCHOR = "<!-- branch-stack -->";
4318643218
const descriptionAst = remark2.parse(description);
43187-
const outputAst = remark2.parse(`${ANCHOR}
43188-
${output}`);
43219+
const outputAst = remark2.parse(output);
43220+
const inlineAnchorIndex = findInlineAnchorIndex(descriptionAst);
43221+
if (inlineAnchorIndex) {
43222+
descriptionAst.children.splice(inlineAnchorIndex, 1, ...outputAst.children);
43223+
return remark2.stringify(descriptionAst);
43224+
}
4318943225
const anchorIndex = descriptionAst.children.findIndex(
4319043226
(node2) => node2.type === "html" && node2.value === ANCHOR
4319143227
);
@@ -43194,19 +43230,8 @@ ${output}`);
4319443230
descriptionAst.children.push(...outputAst.children);
4319543231
return remark2.stringify(descriptionAst);
4319643232
}
43197-
let nearestListIndex = anchorIndex;
43198-
for (let i = anchorIndex; i < descriptionAst.children.length; i += 1) {
43199-
const node2 = descriptionAst.children[i];
43200-
if (node2?.type === "list") {
43201-
nearestListIndex = i;
43202-
break;
43203-
}
43204-
}
43205-
descriptionAst.children.splice(
43206-
anchorIndex,
43207-
nearestListIndex - anchorIndex + 1,
43208-
...outputAst.children
43209-
);
43233+
const numChildrenToReplace = nextChildIsListAndContainsPrs(descriptionAst.children[anchorIndex + 1]) ? 2 : 1;
43234+
descriptionAst.children.splice(anchorIndex, numChildrenToReplace, ...outputAst.children);
4321043235
return remark2.stringify(descriptionAst);
4321143236
}
4321243237

0 commit comments

Comments
 (0)