Skip to content

Check that every pull request description into main starts with Fixes #N - #52

Merged
anth-volk merged 14 commits into
mainfrom
claude/rules-pr-description
Nov 2, 2026
Merged

anth-volk merged 14 commits into
mainfrom
claude/rules-pr-description

Conversation

@anth-volk

@anth-volk anth-volk commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #51

What this does

Fails a pull request whose base, or whose stack's final target, is main when its description does not start with Fixes #N naming an open issue here, and registers that as a rule. 16.1 · 6 in the plan; stacked on #50. Making the check required on main is 16.1 · 7, a manual ruleset change.

  • The workflow. The new .github/workflows/pr-description.yaml runs on pull_request events opened, edited, reopened and synchronize, for pull requests whose base is main (branches: [main]). In a stack that gh stack links on GitHub, GitHub gives every pull request the stack's final target, main, as its base, so the check runs on each pull request of this stack too, as CI does (it ran on this one, whose displayed base is Check that workflow steps are single commands, and that tools scripts pass shellcheck and have tests #50's branch). It is a workflow of its own, so editing a description reruns only this check. Its one job, pr-description, is named "PR description", the name the ruleset will require, and skips closed pull requests (GitHub also sends edited for them, and merging closed their issue). Permissions: contents, issues and pull-requests read.
  • The check. python -m scripts.rules.pr_description (new, in the rules tool, standard library only) reads the description from the event payload. Its first line must be exactly Fixes #N, read as the simulation API's check reads it: CRLF, CR or LF end a line, trailing spaces and tabs are ignored, leading whitespace fails, a missing or empty description fails, and N has no leading zero. It then looks N up with scripts.rules.issues.require_open_issue, the lookup Add the rules registry tool, reading repository-specific values from the registry, and run it on pull requests #40 moved into the tool for this, which refuses a pull request number, a closed issue, a missing one and one moved to another repository. A failure is one ::error annotation that says what is wrong and how to fix it, naming the rule.
  • The rule. emitter.process.pr-tracking-issue, enforced by the workflow job's step "Check the first line and the tracking issue". Its proof uses two real descriptions: Release automatically on every merge to main #13's, which named no issue, fails, and Keep telemetry running after an unreadable saved login or a malformed collector answer, and refuse an unsendable collector token #38's, Fixes #37, passes. [discovery].workflows now includes pr-description.yaml. The relock pull requests from Pin one uv version, install and test from uv.lock, and relock weekly with Dependabot #48 already start with Fixes #N.
  • Dependabot. A pull request whose author is dependabot[bot] passes without a lookup: Dependabot, which Pin one uv version, install and test from uv.lock, and relock weekly with Dependabot #48 now uses to relock uv.lock, writes its own descriptions and cannot name an issue. Every other author is checked as before (0e19393 red: the new test fails; 15da936 green: the file's 23 tests pass).
  • Also: the check's uv run --no-project is a registered exception, as the rules job's are; emitter.ci.pull-request-workflow-structure covers the new workflow; emitter.ci.required-checks no longer calls "Required checks" the only required check, which 16.1 · 7 will make untrue; the README's publication section states the rule.

Test-first record

Commit Result
9ab7b44 Tests Red: python -m unittest scripts.rules.tests.test_pr_description fails to import scripts.rules.pr_description; pytest tests/test_workflows.py::test_pull_request_descriptions_are_checked_for_pull_requests_into_main fails, as pr-description.yaml is missing
b2a6bc6 The check, the workflow and the rule Green: the module's 21 tests pass, including one that runs it as python -m scripts.rules.pr_description through a fake gh, and the workflow test passes. All five guards and guard --base-ref origin/main pass; actionlint 1.7.12 passes
771603b Changelog fragment bash tools/check-changelog.sh passes

Only the new and changed tests were run, by name; no command ran a test directory or suite.

Review round 1: 8073edc corrected when the check runs (the workflow comment, emitter.process.pr-tracking-issue, emitter.ci.pull-request-workflow-structure, the README) and documented the placeholder description; documentation only, and render, guard and the workflow test pass.

CI

The new workflow is the only workflow change. No existing trigger changes.

Name Read by Provider Wiring
GH_TOKEN gh api repos/<repository>/issues/<N>, run by scripts/rules/issues.py GitHub Actions' token for the job (github.token), limited by the workflow's permissions to contents, issues and pull-requests read The check step's env:
GITHUB_EVENT_PATH scripts/rules/pr_description.py, for the description Set by the runner on pull_request events Present in every step
GITHUB_REPOSITORY scripts/rules/pr_description.py, for the issue's repository Set by the runner Present in every step

No secret or variable is involved. The workflow has run on this pull request (see above); its first run failed on the placeholder description gh stack submit --auto gives a new pull request, and passed once the description was replaced, which the README now says. Unverified: a run on a pull request from a fork, which gets a read-only token; that is enough for the check.

Release

The fragment is changelog.d/pr-description-check.changed.md, a patch bump: merging releases the next patch version of both distributions. The wheels are unchanged, and the source archive leaves the new module out with the rest of scripts/rules/.

🤖 Generated with Claude Code

anth-volk and others added 3 commits October 30, 2026 19:32
scripts/rules/tests/test_pr_description.py tests a check that the first
line of a pull request's description is exactly Fixes #N, read as the
simulation API's check reads it, and that N is an open issue here, looked
up with scripts.rules.issues: the messages, the error annotation, the
environment it needs, and a run as python -m scripts.rules.pr_description
through a fake gh. Its proof fixtures are #13's description, which named
no issue, and #38's.

tests/test_workflows.py tests that pr-description.yaml runs only for
pull requests into main, on every event that can change the description,
with read-only permissions, in a job named "PR description".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The new pr-description.yaml runs python -m scripts.rules.pr_description
for open pull requests into main, on every event that can change the
description, in a job named "PR description" that main's ruleset can
require. The check fails unless the description's first line is exactly
Fixes #N and N is an open issue, not a pull request, in this repository,
looked up with the rules tool's scripts.rules.issues. It follows the
simulation API's check.

Registered as emitter.process.pr-tracking-issue, with a proof, and the
registry now discovers the workflow's job. Its uv run --no-project is a
registered exception, as the rules job's are. The README states the
rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@anth-volk
anth-volk added this pull request to stack #46 October 30, 2026 15:36
@anth-volk anth-volk changed the title claude/rules pr description Check that every pull request description into main starts with Fixes #N Oct 30, 2026
Brings review round 1 of #48.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk and others added 3 commits October 30, 2026 20:00
Brings review round 1 of #50. AGENTS.md and docs/generated/rules.md are
rendered again from the merged registry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings main after #43's merge and the 0.11.3 version commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s it

Review round 1 of #52: the check ran on #52, whose base is #50's branch.
GitHub gives every pull request of a stack that gh stack links the
stack's final target, main, as its base, so branches: [main] matches each
of them, as CI runs on each. The workflow comment, the two rules'
statements and the README say so. The README also says that a pull
request gh stack submit --auto opens starts with a placeholder
description, which fails the check until it is replaced; editing it runs
the check again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk and others added 2 commits October 30, 2026 20:25
Brings review round 2 of #48: the uv release written once, in pyproject.toml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The merged uv-version guard requires every setup-uv step to read the
release with version-file: pyproject.toml; the PR description workflow's
step, new in this branch, now does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk and others added 3 commits October 30, 2026 21:03
Brings main after #45, and Dependabot in place of the custom relock. The
README keeps both the Dependabot exception to the changelog check and
the PR description check's paragraph; the PR description job's setup-uv
step reads the release from .github/uv-version.txt, as the merged
uv-version rule requires; and emitter.process.pr-tracking-issue no longer
names the removed relock script.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dependabot, which now relocks uv.lock, writes its own pull request
descriptions and cannot name an issue. Test that the PR description
check passes a pull request whose author is dependabot[bot] without
looking anything up, and still checks every other author.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A pull request whose author is dependabot[bot] passes without a
tracking-issue lookup: Dependabot writes its own descriptions, and the
weekly uv.lock updates it proposes need no issue. Every other author is
checked as before. The rule's statement and the README say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings main after #48's merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Base automatically changed from claude/rules-ci-scripts to main October 30, 2026 17:59
@anth-volk
anth-volk marked this pull request as ready for review November 2, 2026 13:36
@anth-volk
anth-volk merged commit 011ac74 into main Nov 2, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Check that every pull request description starts with Fixes #N

1 participant