Skip to content

Commit d9d7cb2

Browse files
committed
tools: add tool that fills pr-url as code review suggestion
1 parent d991f69 commit d9d7cb2

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Suggest PR URL
2+
3+
on:
4+
pull_request:
5+
types: [opened]
6+
paths:
7+
- doc/api/**/*.md
8+
9+
permissions:
10+
pull-requests: write
11+
12+
jobs:
13+
suggest-fill-prurl:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
17+
with:
18+
persist-credentials: false
19+
sparse-checkout: /tools/actions/suggest-fill-prurl.mjs
20+
sparse-checkout-cone-mode: false
21+
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
22+
with:
23+
node-version: latest
24+
- run: ./tools/actions/suggest-fill-prurl.mjs
25+
env:
26+
GH_TOKEN: ${{ secrets.GH_USER_TOKEN }}
27+
PR_NUMBER: ${{ github.event.number }}
28+
REPO: ${{ github.repository }}
29+
SHA: ${{ github.sha }}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/usr/bin/env node
2+
3+
// Replaces:
4+
// pr-url: https://github.com/nodejs/node/pull/FILLME
5+
// With:
6+
// pr-url: https://github.com/nodejs/node/pull/ACTUAL_PR_NUMBER
7+
// And posts it as ```suggestion``` on pull request on GitHub
8+
9+
import { env } from 'node:process';
10+
11+
const { GH_TOKEN, PR_NUMBER, REPO, SHA } = env;
12+
if (!GH_TOKEN || !PR_NUMBER || !REPO || !SHA) {
13+
throw new Error('Missing required environment variables');
14+
}
15+
16+
const PLACEHOLDER = 'FILLME';
17+
const placeholderReg = new RegExp(`^\\+.*${RegExp.escape(`https://github.com/${REPO}/pull/${PLACEHOLDER}`)}`);
18+
19+
const headers = new Headers({
20+
'Accept': 'application/vnd.github+json',
21+
'Authorization': `Bearer ${GH_TOKEN}`,
22+
'User-Agent': 'nodejs-bot',
23+
'X-GitHub-Api-Version': '2022-11-28',
24+
});
25+
26+
// https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#list-pull-requests-files
27+
const res = await fetch(
28+
new URL(`repos/${REPO}/pulls/${PR_NUMBER}/files`, 'https://api.github.com'),
29+
{ headers },
30+
);
31+
if (!res.ok) {
32+
throw new Error(`Failed to fetch PR files, status=${res.status}`);
33+
}
34+
35+
const files = await res.json();
36+
37+
const comments = files.flatMap(({ status, filename, patch }) => {
38+
if (!patch || !['added', 'modified'].includes(status)) {
39+
return [];
40+
}
41+
42+
return patch.split('\n').map((line, position) => {
43+
if (!placeholderReg.test(line)) {
44+
return false;
45+
}
46+
const suggestion = line
47+
.slice(1)
48+
.replace(`https://github.com/${REPO}/pull/${PLACEHOLDER}`, `https://github.com/${REPO}/pull/${PR_NUMBER}`);
49+
return {
50+
path: filename,
51+
position,
52+
body: `Replace ${PLACEHOLDER} with PR number ${PR_NUMBER}\n` +
53+
'```suggestion\n' +
54+
`${suggestion}\n` +
55+
'```\n',
56+
};
57+
}).filter(Boolean);
58+
});
59+
60+
if (comments.length) {
61+
const payload = {
62+
comments,
63+
commit_id: SHA,
64+
event: 'COMMENT',
65+
};
66+
67+
// https://docs.github.com/en/rest/pulls/reviews?apiVersion=2022-11-28#create-a-review-for-a-pull-request
68+
await fetch(
69+
new URL(`repos/${REPO}/pulls/${PR_NUMBER}/reviews`, 'https://api.github.com'),
70+
{
71+
method: 'POST',
72+
headers,
73+
body: JSON.stringify(payload),
74+
},
75+
);
76+
}

0 commit comments

Comments
 (0)