Repository navigation
Check that every pull request description into main starts with Fixes #N - #52
Merged
Merged
Conversation
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>
Brings review round 1 of #48. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
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>
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>
anth-volk
marked this pull request as ready for review
November 2, 2026 13:36
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #51
What this does
Fails a pull request whose base, or whose stack's final target, is
mainwhen its description does not start withFixes #Nnaming an open issue here, and registers that as a rule. 16.1 · 6 in the plan; stacked on #50. Making the check required onmainis 16.1 · 7, a manual ruleset change..github/workflows/pr-description.yamlruns onpull_requesteventsopened,edited,reopenedandsynchronize, for pull requests whose base ismain(branches: [main]). In a stack thatgh stacklinks 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 sendseditedfor them, and merging closed their issue). Permissions:contents,issuesandpull-requestsread.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 exactlyFixes #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, andNhas no leading zero. It then looksNup withscripts.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::errorannotation that says what is wrong and how to fix it, naming 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].workflowsnow includespr-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 withFixes #N.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 relockuv.lock, writes its own descriptions and cannot name an issue. Every other author is checked as before (0e19393red: the new test fails;15da936green: the file's 23 tests pass).uv run --no-projectis a registered exception, as the rules job's are;emitter.ci.pull-request-workflow-structurecovers the new workflow;emitter.ci.required-checksno 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
9ab7b44Testspython -m unittest scripts.rules.tests.test_pr_descriptionfails to importscripts.rules.pr_description;pytest tests/test_workflows.py::test_pull_request_descriptions_are_checked_for_pull_requests_into_mainfails, aspr-description.yamlis missingb2a6bc6The check, the workflow and the rulepython -m scripts.rules.pr_descriptionthrough a fakegh, and the workflow test passes. All five guards andguard --base-ref origin/mainpass; actionlint 1.7.12 passes771603bChangelog fragmentbash tools/check-changelog.shpassesOnly the new and changed tests were run, by name; no command ran a test directory or suite.
Review round 1:
8073edccorrected 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, andrender,guardand the workflow test pass.CI
The new workflow is the only workflow change. No existing trigger changes.
GH_TOKENgh api repos/<repository>/issues/<N>, run byscripts/rules/issues.pygithub.token), limited by the workflow'spermissionstocontents,issuesandpull-requestsreadenv:GITHUB_EVENT_PATHscripts/rules/pr_description.py, for the descriptionpull_requesteventsGITHUB_REPOSITORYscripts/rules/pr_description.py, for the issue's repositoryNo 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 --autogives 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 ofscripts/rules/.🤖 Generated with Claude Code