Pull Request and Code Review Template
A fill-in pull request description and reviewer checklist — what changed and why, risk and rollback, tests that prove it, and a review standard that separates defects from preferences.
Markdown. No sign-up, no email.
Copy the first half into
.github/pull_request_template.mdso it appears automatically. The reviewer checklist below belongs in your contributing guide.The purpose of a PR description is to let a reviewer answer "is this correct and safe" without reconstructing the author's reasoning from the diff.
What this changes#
In one sentence: _______________
Why now: _______________
Issue / ticket: _______________
How it works#
Two or three sentences on the approach, aimed at someone who has not been in this code for a month. Explain the decision that was not obvious.
Approaches considered and rejected: _______________
Risk#
| Blast radius if this is wrong | |
| Reversible by rollback alone | yes / no |
| Database migration included | yes / no — backward compatible? |
| Configuration or secret change required | |
| Feature flag | name: ______ default: ______ |
| Performance impact considered | |
| Security impact considered |
If this breaks in production, what is the first symptom? _______________
That question is worth more than most of the checklist. An author who cannot answer it has not thought about how the change fails, only about how it works.
Testing#
- [ ] Tests added or updated, and they fail without this change
- [ ] Edge cases covered: empty, null, boundary, duplicate, concurrent
- [ ] Error paths tested, not only the success path
- [ ] Tested manually — how: _______________
- [ ] No new flaky behaviour introduced
What is deliberately not covered by tests, and why: _______________
Reviewer notes#
Start here: _______________ (name the file or function that carries the change)
Anything you want a specific opinion on: _______________
Reviewer Checklist#
Review the change, not the person. Distinguish between defects and preferences, and say which you are raising — the most common cause of slow, resented reviews is unlabelled taste presented with the same weight as a bug.
Correctness#
- [ ] It does what the description says
- [ ] Edge cases: empty input, nulls, boundaries, duplicates, very large values
- [ ] Error handling: failures are handled or deliberately propagated, not swallowed
- [ ] Concurrency: shared state, race conditions, retries that could double-apply
- [ ] The failure mode is safe — when this goes wrong, does it fail closed?
Safety#
- [ ] Input validated at the boundary
- [ ] No secrets, tokens or keys in the diff
- [ ] Authorisation checked, not just authentication
- [ ] Personal data handled consistently with policy
- [ ] Logging does not include sensitive values
- [ ] Dependencies added are necessary and maintained
Fit#
- [ ] Consistent with how the surrounding code already works
- [ ] Not a duplicate of something that exists
- [ ] Naming says what the thing is
- [ ] Comments explain why, where the reason is not obvious from the code
Operability#
- [ ] It can be observed in production — logs or metrics for the new path
- [ ] It can be rolled back
- [ ] Migration is backward compatible with the running version
Review conduct#
| Practice | Why |
|---|---|
| Label each comment: defect, question, or preference | The author knows what blocks merge |
| Ask rather than instruct where you are unsure | You are often missing context |
| Approve with minor comments where trust allows | Blocking on preferences slows the whole team |
| Review within a working day | A PR waiting three days is worse than one imperfect merge |
| Comment on something done well | Reviews that only ever criticise are avoided |
🔴 If a review takes more than about an hour, the change is too large to review properly. Say so and ask for it to be split — approving something you did not really read is worse than delaying it.
Sign-off#
| Name | Date | |
|---|---|---|
| Author | ||
| Reviewer | ||
| Second reviewer (if high risk) |