-
-
Notifications
You must be signed in to change notification settings - Fork 2
91 lines (82 loc) · 3.07 KB
/
pr-labels.yaml
File metadata and controls
91 lines (82 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
---
name: PR Labels
# Each PR must carry exactly one of the labels release-drafter knows
# how to slot into a release-notes section. We derive that label from
# the "Types of changes" checkbox in the PR template and apply it
# automatically — most external contributors can't label their own
# PRs. The job only fails when no checkbox is ticked.
# yamllint disable-line rule:truthy
on:
pull_request_target:
types:
- opened
- edited
- synchronize
- labeled
- unlabeled
branches:
- main
permissions:
pull-requests: write
jobs:
apply_label:
name: Apply
runs-on: ubuntu-latest
if: github.event.pull_request.state == 'open'
steps:
- name: 🏷 Apply label from PR description checkbox
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const known = [
'breaking-change', 'bugfix', 'refactor',
'new-feature', 'enhancement', 'maintenance',
'ci', 'dependencies', 'docs',
];
// Match `- [x] ... `<label>`` lines in the PR body. The
// PR template puts the canonical label name in backticks
// at the end of each "Types of changes" bullet.
const body = context.payload.pull_request.body || '';
const re = /^\s*-\s*\[x\][^`\n]*`([^`]+)`/gim;
const ticked = [];
for (const m of body.matchAll(re)) {
const name = m[1];
if (known.includes(name) && !ticked.includes(name)) {
ticked.push(name);
}
}
const { owner, repo } = context.repo;
const issue_number = context.payload.pull_request.number;
if (ticked.length === 0) {
core.setFailed(
'No "Types of changes" checkbox is ticked in the PR ' +
'description. Edit the description and tick exactly ' +
'one box so this PR can be release-noted.'
);
return;
}
if (ticked.length > 1) {
core.setFailed(
`Multiple "Types of changes" checkboxes are ticked ` +
`(${ticked.join(', ')}). Tick exactly one.`
);
return;
}
const desired = ticked[0];
const current = (context.payload.pull_request.labels || [])
.map(l => l.name);
// Strip any stale labels from the known set so a
// contributor changing their mind in the description
// doesn't leave the previous label behind.
for (const name of current) {
if (known.includes(name) && name !== desired) {
await github.rest.issues.removeLabel({
owner, repo, issue_number, name,
}).catch(() => {});
}
}
if (!current.includes(desired)) {
await github.rest.issues.addLabels({
owner, repo, issue_number, labels: [desired],
});
}