docs(contributing): add PR description template and convention #123
@@ -0,0 +1,109 @@
|
||||
<!--
|
||||
PR title: Conventional Commits — type(scope): description
|
||||
e.g. fix(mv): bring header and completions up to repo conventions
|
||||
Lowercase after the colon, imperative mood, no trailing period.
|
||||
Append `!` after the scope for a breaking change: feat(logging)!: ...
|
||||
Types in use: feat, fix, docs, test, chore, perf, refactor, style.
|
||||
See CONTRIBUTING.md § Commit Conventions.
|
||||
|
||||
Still writing code? Prefix the title with `WIP:` —
|
||||
WIP: feat(media): add play-media fzf picker
|
||||
Gitea recognizes the prefix, marks the PR a draft, and blocks merging
|
||||
until you remove it. The prefix goes before the whole conventional
|
||||
subject, and comes off when the branch is complete.
|
||||
|
||||
`WIP:` means MORE CHANGES ARE COMING. It is not for a finished branch
|
||||
waiting on verification — that is what an unchecked box in Verification
|
||||
already signals. A complete branch with open checkboxes is a normal PR,
|
||||
not a WIP.
|
||||
|
||||
Keep the two headings below, in this order, and delete these comments.
|
||||
Optional sections may be added between them (see the note above
|
||||
"Verification").
|
||||
-->
|
||||
|
||||
## Summary
|
||||
|
||||
<!--
|
||||
What changed and why. A short prose paragraph, 2-5 bullets, or a
|
||||
paragraph followed by bullets — whichever fits the change.
|
||||
|
||||
- Name concrete paths and identifiers in backticks (`functions/mv.fish`,
|
||||
`$__fish_config_op_autoexec`), not vague descriptions.
|
||||
- Lead a bullet with a **bold phrase** when it covers a distinct file or
|
||||
behavior, so the list scans at a glance.
|
||||
- Explain the reasoning, not just the diff — a reader should understand
|
||||
why this approach over the obvious alternative.
|
||||
- Say so explicitly when there is no behavioral change, when a file is
|
||||
generated by the docs pipeline, or when the change is scoped to the
|
||||
site build only.
|
||||
|
||||
If this PR resolves a tracked issue, close it with a trailing line at the
|
||||
end of this section — not at the very bottom, since Verification is
|
||||
always last:
|
||||
|
||||
Closes #42
|
||||
|
||||
Gitea and GitHub both auto-close the issue on merge. `Fixes #N` and
|
||||
`Resolves #N` work identically; pick whichever reads correctly. Use one
|
||||
line per issue (`Closes #42, closes #43` — the keyword must be repeated,
|
||||
a bare `#43` after a comma is only a link and will NOT close). For an
|
||||
issue that is related but should stay open, reference it without a
|
||||
keyword: `Refs #42`. Omit all of this entirely when no issue is involved
|
||||
— do not leave an empty `Closes #` behind.
|
||||
-->
|
||||
|
||||
<!--
|
||||
OPTIONAL SECTIONS — add any `##` heading here that the change actually
|
||||
needs, and skip them entirely for a straightforward one. Used in this
|
||||
repo, roughly in order of frequency:
|
||||
|
||||
## Root cause — for a bug fix, what was actually wrong
|
||||
## Why — motivation, when it isn't obvious
|
||||
## How it works — mechanism, for a non-trivial new feature
|
||||
## Behavior — user-visible behavior before/after
|
||||
## Changes — a longer breakdown than Summary can carry
|
||||
## Docs — documentation touched by this change
|
||||
## Notes — caveats, follow-ups, deferred work
|
||||
## Scope note — what this deliberately does NOT cover
|
||||
## Opinionated guard (C1-C6)
|
||||
— which tier gates this, and behavior when off
|
||||
## ⚠️ Breaking Change — required whenever the title carries `!`;
|
||||
state the break and the migration path
|
||||
|
||||
A "Why not <alternative>?" heading is also common when a reviewer would
|
||||
reasonably ask why the obvious approach was rejected.
|
||||
-->
|
||||
|
||||
## Verification
|
||||
|
||||
<!--
|
||||
Every check this change needs, as a checkbox list. Always the last
|
||||
section.
|
||||
|
||||
A CHECKED box means verified — either it ran programmatically (test
|
||||
suite, linter, docs verifier, CI) or the author performed it by hand and
|
||||
confirmed the result. Check these off before opening the PR.
|
||||
|
||||
An UNCHECKED box is an outstanding manual check the reviewer still has to
|
||||
perform. Leave anything you could not verify yourself unchecked rather
|
||||
than dropping it, so it stays visible.
|
||||
|
||||
**This list is the merge gate: the PR does not merge until every box is
|
||||
checked.** So only put things here that can actually be resolved — a
|
||||
check nobody is able to run blocks the PR forever. Genuinely unverifiable
|
||||
caveats, assumptions, and known limitations belong in a `## Notes`
|
||||
section instead, where they inform the review without gating it.
|
||||
|
||||
- One check per line, imperative, with the exact command in backticks
|
||||
and the expected result stated.
|
||||
- Cover the regression path, not just the happy path: the old behavior
|
||||
still working, the opinionated toggle disabled, the error branch.
|
||||
- Include the repo's standing gates when the change touches what they
|
||||
guard: `fish -n <file>`, `fish_indent`, `python3 docs/verify-manual.py`,
|
||||
`python3 docs/build-manual.py --site`, `fish tests/run-tests.fish`.
|
||||
- Reset any universal variable you set during a check.
|
||||
-->
|
||||
|
||||
- [ ]
|
||||
- [ ]
|
||||
@@ -48,6 +48,19 @@ assumes you *do* have push access (maintainers, regular contributors).
|
||||
branching doesn't touch the working tree.)
|
||||
- **Merge target is `main`, via PR.** Contributors open the PR; the repo
|
||||
owner merges it. Don't merge your own PR.
|
||||
- **Don't merge until the `## Verification` checklist is fully checked.**
|
||||
Unchecked boxes are outstanding manual checks, not decoration. See
|
||||
[Pull request descriptions](#pull-request-descriptions) below.
|
||||
- **Prefix in-progress PRs with `WIP:`.** If the branch still has code
|
||||
changes coming, open it as `WIP: type(scope): description`. Gitea
|
||||
recognizes the prefix, flags the PR as a draft, and refuses to merge it
|
||||
until the prefix is removed; drop it once the branch is complete.
|
||||
|
||||
`WIP:` signals **more changes are coming** — not "done but unverified".
|
||||
A finished branch waiting on manual checks is an ordinary PR whose
|
||||
`## Verification` boxes aren't all ticked yet; that's already the merge
|
||||
gate above and doesn't need the prefix. The two are independent: a PR
|
||||
can be WIP with everything ticked, or complete with checks outstanding.
|
||||
- **Keep feature branches focused.** If you stumble onto something unrelated
|
||||
to your current task while working (a pre-existing bug, a stray cleanup),
|
||||
don't fold it into the same commit or PR. Handle it with one of these,
|
||||
@@ -64,6 +77,41 @@ assumes you *do* have push access (maintainers, regular contributors).
|
||||
approval before doing this** — there's no standing exception, no matter
|
||||
how trivial the change looks.
|
||||
|
||||
### Pull request descriptions
|
||||
|
||||
Fill in `.github/PULL_REQUEST_TEMPLATE.md` — Gitea pre-loads it into the
|
||||
description box when you open a PR. Every PR carries, in this order:
|
||||
|
||||
- **`## Summary`** — what changed and why, as a short paragraph, 2-5
|
||||
bullets, or both. Name concrete paths and identifiers in backticks, and
|
||||
explain the reasoning rather than restating the diff.
|
||||
- **Optional `##` sections** — add what the change actually needs
|
||||
(`Root cause`, `Why`, `How it works`, `Behavior`, `Docs`, `Notes`,
|
||||
`Scope note`, `Opinionated guard (C1-C6)`), and skip them entirely for a
|
||||
straightforward change. A breaking change (title ending in `!` before
|
||||
the colon) must include `## ⚠️ Breaking Change` with the migration path.
|
||||
- **`## Verification`** — always last. Every check this change needs, as a
|
||||
checkbox list, each with the exact command and its expected result.
|
||||
A **checked** box means verified, whether programmatically (test suite,
|
||||
linter, docs verifier, CI) or by hand; check those off before opening the
|
||||
PR. An **unchecked** box is an outstanding manual check the reviewer
|
||||
still has to perform — leave anything you couldn't verify yourself
|
||||
unchecked rather than dropping it.
|
||||
|
||||
**This list is the merge gate: a PR isn't merged until every box is
|
||||
checked.** Only list checks that can actually be resolved — one nobody
|
||||
can run blocks the PR indefinitely. Put genuinely unverifiable caveats,
|
||||
assumptions, and known limitations in `## Notes` instead, where they
|
||||
inform the review without gating it.
|
||||
|
||||
When a PR resolves a tracked issue, close it with a trailing `Closes #42`
|
||||
line at the end of `## Summary` — not at the very bottom of the body, since
|
||||
`## Verification` is always last. `Fixes #N` and `Resolves #N` behave
|
||||
identically. Repeat the keyword for each issue (`Closes #42, closes #43`); a
|
||||
bare `#43` is only a link and won't close anything. To point at a related
|
||||
issue that should stay open, drop the keyword and use `Refs #42`. Leave the
|
||||
line out entirely when no issue is involved.
|
||||
|
||||
## Commit Conventions
|
||||
|
||||
Commit subjects follow [Conventional Commits](https://www.conventionalcommits.org/):
|
||||
|
||||
Reference in New Issue
Block a user