ci: require every PR to close an issue or say why it doesn't#4798
Conversation
342 issues are open and 329 of them were touched this month, so nothing is rotting -- the backlog is not stale, it is unclosed. Only 8 of 35 open PRs carried a closing keyword. The other 27 will merge and leave their issues open, which is how 121 issues accumulate on a single milestone and why the backlog no longer says which work is actually done. The check reads the PR body for one of GitHub's closing keywords attached to an issue number, or a one-line `No-Issue: <why>` opt-out for chores, reverts and dependency bumps. Either satisfies it, so this is a prompt rather than a wall. Body only, deliberately: GitHub resolves closing keywords from the PR description, so a "Closes #123" sitting in the title auto-closes nothing. Accepting the title would have passed PRs that close no issue -- the same false-assurance shape as a green check that guards nothing. The body is read through env rather than interpolated into the script, since it is attacker-controlled text. Verified the matcher against 13 cases: all six closing-keyword spellings and a multiline body match; indented and inline opt-outs match; bare `#1234`, prose "this fixes the parser" with no number, an empty `No-Issue:`, and an unmarked chore correctly fail. Repo settings changed alongside this: delete_branch_on_merge and allow_auto_merge are now on, so merged branches stop accumulating.
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Claude finished @Hmbown's task in 4m 33s —— View job Review:
|
No-Issue: repo-hygiene automation, filed from a backlog measurement rather than a report.
What the numbers said
342 issues open, 329 of them touched this month. Nothing is rotting — the backlog isn't stale, it's unclosed.
stale.ymlruns green daily but is scoped toonly-labels: needs-info, which is 8 issues out of 342.The leak: only 8 of 35 open PRs carry a closing keyword. The other 27 will merge and leave their issues open. That's how 121 issues land on one milestone and why the backlog stopped saying which work is actually done.
What this does
Reads the PR body for a GitHub closing keyword attached to an issue number, or a one-line opt-out:
Either satisfies it. It's a prompt, not a wall.
Body only, deliberately. GitHub resolves closing keywords from the PR description —
Closes #123in the title auto-closes nothing. Accepting the title would pass PRs that close no issue: a green check guarding nothing, which is the shape this repo already has incache_guard.rsand in theprotected_invariantsnothing enforces.The body is read through
env:rather than interpolated into the script, since it's attacker-controlled.Verification
Matcher tested against 13 cases. All six closing-keyword spellings match (
close/closes/closed/fix/fixes/fixed/resolve/resolves/resolved), multiline bodies match, indented opt-outs match. Correctly rejected: bare#1234with no keyword, prose"this fixes the parser"with no number, an emptyNo-Issue:, and an unmarked chore. YAML validated.Also changed, outside this diff
delete_branch_on_mergeandallow_auto_mergeare now enabled on the repo — merged branches stop accumulating (4 were sitting merged-but-undeleted).Note on existing PRs
pull_requestfires onopened/edited/reopened/synchronize, so the 27 unlinked PRs stay green until someone pushes to them. No retroactive red wall.