Skip to content

Commit af4b621

Browse files
authored
Merge pull request #26 from CryogenicBot/preserve-checklist-state
allow merging of checklist comments
2 parents c95b5b5 + d03291a commit af4b621

File tree

3 files changed

+98
-34
lines changed

3 files changed

+98
-34
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ Overrides the default header text in the PR comment.
5757

5858
Overrides the default footer text in the PR comment.
5959

60+
##### `merge-comment`
61+
62+
Merges any new checklist items with the existing checklist comment.
63+
6064
##### `include-hidden-files`
6165

6266
Includes files and folders starting with `.` when matching. Defaults to `false`.

dist/index.js

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19198,15 +19198,39 @@ const { readFileSync } = __nccwpck_require__(5747);
1919819198
const header = core.getInput("comment-header");
1919919199
const footer = core.getInput("comment-footer");
1920019200
const minimatchOptions = {
19201-
dot: core.getInput('include-hidden-files') === 'true'
19201+
dot: core.getInput("include-hidden-files") === "true",
1920219202
};
1920319203
function getChecklistPaths() {
1920419204
const inputFile = core.getInput("input-file");
1920519205
const parsedFile = YAML.parse(readFileSync(inputFile, { encoding: "utf8" }));
1920619206
return parsedFile.paths;
1920719207
}
19208-
function formatItemsForPath([path, items]) {
19209-
const showPaths = core.getInput("show-paths") === 'true';
19208+
function formatItemsForPath(previousComment, [path, items]) {
19209+
const showPaths = core.getInput("show-paths") === "true";
19210+
const mergeComment = core.getInput("merge-comment") === "true";
19211+
if (!!previousComment && mergeComment) {
19212+
const existingCheckedItems = previousComment
19213+
.split("\n")
19214+
.filter((line) => line !== "" && line.startsWith("- [x]"))
19215+
.map((line) => line.substring(5).trim());
19216+
const preservedItems = items.filter((item) => {
19217+
return !!existingCheckedItems.find((existingItem) => existingItem.includes(item));
19218+
});
19219+
const newItems = items.filter((item) => {
19220+
return !existingCheckedItems.find((existingItem) => existingItem.includes(item));
19221+
});
19222+
return showPaths
19223+
? [
19224+
`__Files matching \`${path}\`:__\n`,
19225+
...preservedItems.map((item) => `- [x] ${item}\n`),
19226+
...newItems.map((item) => `- [ ] ${item}\n`),
19227+
"\n",
19228+
].join("")
19229+
: [
19230+
...preservedItems.map((item) => `- [x] ${item}\n`),
19231+
...newItems.map((item) => `- [ ] ${item}\n`),
19232+
].join("");
19233+
}
1921019234
return showPaths
1921119235
? [
1921219236
`__Files matching \`${path}\`:__\n`,
@@ -19227,8 +19251,8 @@ function run() {
1922719251
const modifiedPaths = (yield client.rest.pulls.listFiles({
1922819252
owner: owner,
1922919253
repo: repo,
19230-
pull_number: number
19231-
})).data.map(file => file.filename);
19254+
pull_number: number,
19255+
})).data.map((file) => file.filename);
1923219256
const applicableChecklistPaths = Object.entries(checklistPaths).filter(([key, _]) => {
1923319257
for (const modifiedPath of modifiedPaths) {
1923419258
if (minimatch(modifiedPath, key, minimatchOptions)) {
@@ -19240,28 +19264,28 @@ function run() {
1924019264
const existingComment = (yield client.rest.issues.listComments({
1924119265
owner: owner,
1924219266
repo: repo,
19243-
issue_number: number
19244-
})).data.find(comment => comment.body.includes(footer));
19267+
issue_number: number,
19268+
})).data.find((comment) => comment.body.includes(footer));
1924519269
if (applicableChecklistPaths.length > 0) {
1924619270
const body = [
1924719271
`${header}\n\n`,
19248-
...applicableChecklistPaths.map(formatItemsForPath),
19249-
`\n${footer}`
19272+
...applicableChecklistPaths.map(([path, items]) => formatItemsForPath(existingComment.body, [path, items])),
19273+
`\n${footer}`,
1925019274
].join("");
1925119275
if (existingComment) {
1925219276
yield client.rest.issues.updateComment({
1925319277
owner: owner,
1925419278
repo: repo,
1925519279
comment_id: existingComment.id,
19256-
body
19280+
body,
1925719281
});
1925819282
}
1925919283
else {
1926019284
yield client.rest.issues.createComment({
1926119285
owner: owner,
1926219286
repo: repo,
1926319287
issue_number: number,
19264-
body
19288+
body,
1926519289
});
1926619290
}
1926719291
}
@@ -19270,14 +19294,14 @@ function run() {
1927019294
yield client.rest.issues.deleteComment({
1927119295
owner: owner,
1927219296
repo: repo,
19273-
comment_id: existingComment.id
19297+
comment_id: existingComment.id,
1927419298
});
1927519299
}
1927619300
console.log("No paths were modified that match checklist paths");
1927719301
}
1927819302
});
1927919303
}
19280-
run().catch(err => core.setFailed(err.message));
19304+
run().catch((err) => core.setFailed(err.message));
1928119305

1928219306
})();
1928319307

index.ts

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ const minimatch = require("minimatch");
55
const { readFileSync } = require("fs");
66

77
const header = core.getInput("comment-header");
8-
const footer = core.getInput("comment-footer")
8+
const footer = core.getInput("comment-footer");
99

1010
const minimatchOptions = {
11-
dot: core.getInput('include-hidden-files') === 'true'
11+
dot: core.getInput("include-hidden-files") === "true",
1212
};
1313

1414
function getChecklistPaths(): Record<string, string[]> {
@@ -17,22 +17,56 @@ function getChecklistPaths(): Record<string, string[]> {
1717
return parsedFile.paths;
1818
}
1919

20-
function formatItemsForPath([path, items]): string {
21-
const showPaths = core.getInput("show-paths") === 'true';
20+
function formatItemsForPath(previousComment, [path, items]) {
21+
const showPaths = core.getInput("show-paths") === "true";
22+
const mergeComment = core.getInput("merge-comment") === "true";
23+
24+
if (!!previousComment && mergeComment) {
25+
const existingCheckedItems = previousComment
26+
.split("\n")
27+
.filter((line) => line !== "" && line.startsWith("- [x]"))
28+
.map((line) => line.substring(5).trim());
29+
const preservedItems = items.filter((item) => {
30+
return !!existingCheckedItems.find((existingItem) =>
31+
existingItem.includes(item)
32+
);
33+
});
34+
const newItems = items.filter((item) => {
35+
return !existingCheckedItems.find((existingItem) =>
36+
existingItem.includes(item)
37+
);
38+
});
39+
40+
return showPaths
41+
? [
42+
`__Files matching \`${path}\`:__\n`,
43+
...preservedItems.map((item) => `- [x] ${item}\n`),
44+
...newItems.map((item) => `- [ ] ${item}\n`),
45+
"\n",
46+
].join("")
47+
: [
48+
...preservedItems.map((item) => `- [x] ${item}\n`),
49+
...newItems.map((item) => `- [ ] ${item}\n`),
50+
].join("");
51+
}
2252

2353
return showPaths
24-
? [
25-
`__Files matching \`${path}\`:__\n`,
26-
...items.map((item) => `- [ ] ${item}\n`),
27-
"\n",
28-
].join("")
29-
: [...items.map((item) => `- [ ] ${item}\n`)].join("");
54+
? [
55+
`__Files matching \`${path}\`:__\n`,
56+
...items.map((item) => `- [ ] ${item}\n`),
57+
"\n",
58+
].join("")
59+
: [...items.map((item) => `- [ ] ${item}\n`)].join("");
3060
}
3161

3262
async function run() {
3363
const context = github.context;
3464
const { owner, repo } = context.repo;
35-
const number = (context.payload.issue ?? context.payload.pull_request ?? context.payload).number;
65+
const number = (
66+
context.payload.issue ??
67+
context.payload.pull_request ??
68+
context.payload
69+
).number;
3670

3771
const ghToken = core.getInput("gh-token");
3872
const client = github.getOctokit(ghToken);
@@ -42,9 +76,9 @@ async function run() {
4276
await client.rest.pulls.listFiles({
4377
owner: owner,
4478
repo: repo,
45-
pull_number: number
79+
pull_number: number,
4680
})
47-
).data.map(file => file.filename);
81+
).data.map((file) => file.filename);
4882

4983
const applicableChecklistPaths = Object.entries(checklistPaths).filter(
5084
([key, _]) => {
@@ -61,42 +95,44 @@ async function run() {
6195
await client.rest.issues.listComments({
6296
owner: owner,
6397
repo: repo,
64-
issue_number: number
98+
issue_number: number,
6599
})
66-
).data.find(comment => comment.body.includes(footer));
100+
).data.find((comment) => comment.body.includes(footer));
67101

68102
if (applicableChecklistPaths.length > 0) {
69103
const body = [
70104
`${header}\n\n`,
71-
...applicableChecklistPaths.map(formatItemsForPath),
72-
`\n${footer}`
105+
...applicableChecklistPaths.map(([path, items]) =>
106+
formatItemsForPath(existingComment.body, [path, items])
107+
),
108+
`\n${footer}`,
73109
].join("");
74110

75111
if (existingComment) {
76112
await client.rest.issues.updateComment({
77113
owner: owner,
78114
repo: repo,
79115
comment_id: existingComment.id,
80-
body
116+
body,
81117
});
82118
} else {
83119
await client.rest.issues.createComment({
84120
owner: owner,
85121
repo: repo,
86122
issue_number: number,
87-
body
123+
body,
88124
});
89125
}
90126
} else {
91127
if (existingComment) {
92128
await client.rest.issues.deleteComment({
93129
owner: owner,
94130
repo: repo,
95-
comment_id: existingComment.id
131+
comment_id: existingComment.id,
96132
});
97133
}
98134
console.log("No paths were modified that match checklist paths");
99135
}
100136
}
101137

102-
run().catch(err => core.setFailed(err.message));
138+
run().catch((err) => core.setFailed(err.message));

0 commit comments

Comments
 (0)