Skip to content

Commit f2a9fce

Browse files
committed
fix(ci): let the PR labeler actually write labels (#566)
* fix(ci): let the PR labeler actually write labels * test(ci): pin the labeler to the permissions the API demands
1 parent f868351 commit f2a9fce

2 files changed

Lines changed: 17 additions & 4 deletions

File tree

.github/scripts/pr-labeler.test.cjs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,15 @@ describe("pr-labeler workflow", () => {
165165
it("keeps trusted default-branch checkout, concurrency cancel, and minimal permissions", () => {
166166
assert.match(workflow, /ref:\s*\$\{\{\s*github\.event\.repository\.default_branch\s*\}\}/);
167167
assert.match(workflow, /cancel-in-progress:\s*true/);
168-
assert.match(workflow, /pull-requests:\s*read/);
169168
assert.match(workflow, /issues:\s*write/);
170-
assert.doesNotMatch(workflow, /pull-requests:\s*write/);
169+
// The issues label endpoints are shared with pull requests: writing a label
170+
// onto a PR number needs pull_requests=write alongside issues=write, which
171+
// GitHub reports as `issues=write; pull_requests=write`. Pinning this to
172+
// read made the workflow fail closed on the first PR that actually needed a
173+
// label applied (#565), so write is the minimum here, not an escalation.
174+
assert.match(workflow, /pull-requests:\s*write/);
175+
// contents stays read — the labeler never pushes.
176+
assert.match(workflow, /contents:\s*read/);
177+
assert.doesNotMatch(workflow, /contents:\s*write/);
171178
});
172179
});

.github/workflows/pr-labeler.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,14 @@ concurrency:
1717

1818
permissions:
1919
contents: read
20-
# pulls.get only needs read; label mutations use the issues API.
21-
pull-requests: read
20+
# pulls.get only needs read, but the issues label endpoints are shared with
21+
# pull requests: adding or removing a label on a PR number is rejected with
22+
# "Resource not accessible by integration" unless the token also carries
23+
# pull_requests=write (the API reports `issues=write; pull_requests=write`
24+
# in x-accepted-github-permissions). Read-only here silently worked while
25+
# every run happened to be a no-op sync, and failed on the first PR that
26+
# actually needed a label written.
27+
pull-requests: write
2228
issues: write
2329

2430
jobs:

0 commit comments

Comments
 (0)