Skip to content

Commit 527beb2

Browse files
eduralphclaude
andauthored
Require every PR to link an issue (the only required status check) (#3)
A GitHub Action that fails a PR unless it has a linked/closing issue (a "Closes #N" reference or a Development-sidebar link). Marked required in branch protection separately; no CI/test checks gate merges. Pairs with enforce_admins so the PR+issue process binds admins too. Co-authored-by: Eduard Ralph <15236434+eduralph@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 961e2ec commit 527beb2

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: PR hygiene
2+
3+
# Enforce that every PR is tied to an issue. This is the ONLY required status
4+
# check on `main` (no CI/test gates) — it pairs with branch protection's
5+
# `enforce_admins` so the PR+issue process binds everyone, admins included.
6+
#
7+
# A PR satisfies the check when it has a linked/closing issue: a closing keyword
8+
# in the description ("Closes #123", "Fixes #123", "Resolves #123") or an issue
9+
# linked via the PR's Development sidebar. Editing the PR body re-runs the check.
10+
11+
on:
12+
pull_request:
13+
types: [opened, edited, reopened, synchronize, ready_for_review]
14+
15+
permissions:
16+
contents: read
17+
pull-requests: read
18+
19+
jobs:
20+
require-linked-issue:
21+
name: require-linked-issue
22+
runs-on: ubuntu-latest
23+
steps:
24+
- name: Verify the PR links an issue
25+
uses: actions/github-script@v7
26+
with:
27+
script: |
28+
const { owner, repo } = context.repo;
29+
const number = context.payload.pull_request.number;
30+
const query = `
31+
query($owner: String!, $repo: String!, $number: Int!) {
32+
repository(owner: $owner, name: $repo) {
33+
pullRequest(number: $number) {
34+
closingIssuesReferences(first: 1) { totalCount }
35+
}
36+
}
37+
}`;
38+
const res = await github.graphql(query, { owner, repo, number });
39+
const linked = res.repository.pullRequest.closingIssuesReferences.totalCount;
40+
if (linked === 0) {
41+
core.setFailed(
42+
'This PR is not linked to an issue. Add a closing reference to the ' +
43+
'PR description (e.g. "Closes #123") or link an issue via the ' +
44+
'Development sidebar, then the check re-runs automatically.'
45+
);
46+
} else {
47+
core.info(`PR is linked to ${linked} issue(s) — OK.`);
48+
}

0 commit comments

Comments
 (0)