fix(#1389): exempt auto-backmerge PRs from the Require Issue Link gate (#1391)

The required "Issue link required" check failed on automated back-merge
PRs (chore/backmerge-main-to-next-<sha>), which legitimately map to no
issue — a `Closes #N` would pollute the released CHANGELOG. When such a
PR parks for manual review (needs_review), the maintainer could only
merge via --admin.

Carve them out at the failing step's `if:` (step-level, so the required
check still reports SUCCESS rather than a branch-protection-blocking
"skipped"), keyed on the workflow-authored branch name AND same-repo
identity so a fork PR cannot forge the exemption.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-17 14:24:57 -04:00
committed by GitHub
parent 75c2e259d0
commit ef2c0a2b7b
2 changed files with 34 additions and 1 deletions

View File

@@ -29,7 +29,16 @@ jobs:
fi
- name: Comment and fail if no issue link
if: steps.check.outputs.found == 'false'
# Exempt auto-backmerge PRs (chore/backmerge-main-to-next-*): they map to
# no issue and a `Closes #N` would pollute the released CHANGELOG. Keyed on
# the workflow-authored branch name AND same-repo identity so a fork PR
# cannot forge the exemption. Step-level (not job-level) so the required
# "Issue link required" check still reports SUCCESS rather than a
# branch-protection-blocking "skipped". See #1389.
if: >-
steps.check.outputs.found == 'false' &&
!(startsWith(github.head_ref, 'chore/backmerge-main-to-next-') &&
github.event.pull_request.head.repo.full_name == github.repository)
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
# Uses GitHub API SDK — no shell string interpolation of untrusted input

View File

@@ -79,3 +79,27 @@ describe('PR policy workflow maintainer carve-outs', () => {
assert.match(workflow, /CONTRIBUTING\.md#pull-request-guidelines/);
});
});
describe('Require Issue Link back-merge automation carve-out', () => {
test('the fail step is skipped for same-repo auto-backmerge PRs', () => {
const workflow = readWorkflow('.github/workflows/require-issue-link.yml');
// Auto-backmerge PRs (chore/backmerge-main-to-next-*) map to no issue, and a
// `Closes #N` would pollute the released CHANGELOG. The fail step must carve
// them out — keyed on the workflow-authored branch name AND same-repo
// identity so a fork PR cannot forge the exemption (#1389).
assert.match(
workflow,
/startsWith\(github\.head_ref, 'chore\/backmerge-main-to-next-'\)/
);
assert.match(
workflow,
/github\.event\.pull_request\.head\.repo\.full_name == github\.repository/
);
// The carve-out must live on the failing step's `if:` alongside the
// found=='false' check (step-level, so the required check still reports
// SUCCESS rather than a branch-protection-blocking "skipped").
assert.match(workflow, /steps\.check\.outputs\.found == 'false'/);
});
});