Skip to content

Commit ecaabc7

Browse files
committed
ci: auto-fill PR metadata
1 parent f7945e5 commit ecaabc7

1 file changed

Lines changed: 135 additions & 0 deletions

File tree

.github/workflows/pr-metadata.yml

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
name: pr-metadata
2+
3+
# Keep PR triage fields useful without requiring manual cleanup on every branch.
4+
# This workflow only updates PR metadata; it never checks out or executes PR code.
5+
on:
6+
pull_request_target:
7+
types: [opened, reopened, synchronize, ready_for_review]
8+
9+
permissions:
10+
contents: read
11+
issues: write
12+
pull-requests: write
13+
14+
jobs:
15+
triage:
16+
runs-on: ubuntu-latest
17+
env:
18+
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
19+
TRIAGE_PROJECT_URLS: ${{ vars.TRIAGE_PROJECT_URLS }}
20+
steps:
21+
- name: Assign author and label by changed paths
22+
uses: actions/github-script@v7
23+
with:
24+
script: |
25+
const pr = context.payload.pull_request;
26+
const owner = context.repo.owner;
27+
const repo = context.repo.repo;
28+
const issue_number = pr.number;
29+
30+
const assignees = ['TechEngineBot'];
31+
if (!pr.user?.type?.endsWith('Bot')) {
32+
assignees.push(pr.user.login);
33+
}
34+
35+
const files = await github.paginate(github.rest.pulls.listFiles, {
36+
owner,
37+
repo,
38+
pull_number: issue_number,
39+
per_page: 100,
40+
});
41+
42+
const labels = new Set();
43+
const trackers = new Set();
44+
for (const file of files) {
45+
const path = file.filename;
46+
const isDataDump = path.startsWith('site/public/v1/') || path === 'site/public/openapi.json';
47+
if (path.startsWith('site/') && !isDataDump) {
48+
labels.add('site');
49+
trackers.add('#19');
50+
}
51+
if (path.startsWith('data/') || isDataDump) {
52+
labels.add('data');
53+
trackers.add('#1');
54+
}
55+
if (path.startsWith('app/')) labels.add('app');
56+
if (path.startsWith('.github/workflows/')) labels.add('ci');
57+
if (path.startsWith('docs/') || path === 'README.md' || path.endsWith('.md')) labels.add('documentation');
58+
}
59+
60+
await github.rest.issues.addAssignees({
61+
owner,
62+
repo,
63+
issue_number,
64+
assignees: [...new Set(assignees)],
65+
});
66+
67+
if (labels.size) {
68+
await github.rest.issues.addLabels({
69+
owner,
70+
repo,
71+
issue_number,
72+
labels: [...labels],
73+
});
74+
}
75+
76+
const milestoneByLabel = new Map([
77+
['site', 'Homepage and site improvements'],
78+
['data', 'Massive dataset rebuild (1989-2026)'],
79+
]);
80+
for (const [label, title] of milestoneByLabel) {
81+
if (!labels.has(label)) continue;
82+
const milestones = await github.paginate(github.rest.issues.listMilestones, {
83+
owner,
84+
repo,
85+
state: 'open',
86+
per_page: 100,
87+
});
88+
const milestone = milestones.find((item) => item.title === title);
89+
if (milestone) {
90+
await github.rest.issues.update({
91+
owner,
92+
repo,
93+
issue_number,
94+
milestone: milestone.number,
95+
});
96+
}
97+
break;
98+
}
99+
100+
if (trackers.size) {
101+
const marker = '<!-- techapi-tracking -->';
102+
const existing = pr.body || '';
103+
const refs = [...trackers].sort().map((ref) => `- Refs ${ref}`).join('\n');
104+
const block = `${marker}\n\n## Tracking\n${refs}`;
105+
const body = existing.includes(marker)
106+
? existing.replace(new RegExp(`${marker}[\\s\\S]*$`), block)
107+
: `${existing.trim()}\n\n${block}`.trim();
108+
await github.rest.pulls.update({
109+
owner,
110+
repo,
111+
pull_number: issue_number,
112+
body,
113+
});
114+
}
115+
116+
- name: Add PR to configured projects
117+
if: env.TRIAGE_PROJECT_URLS != '' && env.PROJECT_TOKEN != ''
118+
env:
119+
GH_TOKEN: ${{ env.PROJECT_TOKEN }}
120+
PR_URL: ${{ github.event.pull_request.html_url }}
121+
shell: bash
122+
run: |
123+
set -euo pipefail
124+
IFS=',' read -ra urls <<< "${TRIAGE_PROJECT_URLS}"
125+
for url in "${urls[@]}"; do
126+
url="$(echo "$url" | xargs)"
127+
[ -z "$url" ] && continue
128+
if [[ "$url" =~ github.com/orgs/([^/]+)/projects/([0-9]+) ]]; then
129+
gh project item-add "${BASH_REMATCH[2]}" --owner "${BASH_REMATCH[1]}" --url "$PR_URL"
130+
elif [[ "$url" =~ github.com/users/([^/]+)/projects/([0-9]+) ]]; then
131+
gh project item-add "${BASH_REMATCH[2]}" --owner "${BASH_REMATCH[1]}" --url "$PR_URL"
132+
else
133+
echo "::warning::Unsupported project URL: $url"
134+
fi
135+
done

0 commit comments

Comments
 (0)