Skip to content

Commit 42f7ee6

Browse files
committed
Track release impact via per-PR labels
Four `release:` labels now classify every PR: - release: breaking — public API / admin / schema requires action - release: migration — adds a backend/drizzle/*.sql file - release: upgrade-action — operators must do something manually - release: internal — no user-visible impact (default for refactors) PRs must carry at least one. The PR template now has a "Release impact" block with checkboxes for each label and prefilled prose sections (Breaking change details, Migration & upgrade actions, Notes for AI agents) the author fills in when the matching label is ticked. That text becomes the source material for the release body — labelling well during PR review is the work that makes release time fast. CONTRIBUTING.md gets a "Release impact labels" section documenting the labels, plus the gh recipe for fetching labelled PRs since the previous tag at release time. RELEASE_TEMPLATE.md references the same recipe in its top-of-file comment.
1 parent cdf7770 commit 42f7ee6

3 files changed

Lines changed: 102 additions & 15 deletions

File tree

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,65 @@
1010

1111
<!-- Steps a reviewer can take to verify the change locally. -->
1212

13+
## Release impact
14+
15+
<!--
16+
Tick every label that applies and apply the matching label(s) to the PR
17+
on the right sidebar. If only "internal" applies, you're done — skip
18+
the "Breaking change details" / "Migration & upgrade actions" blocks.
19+
20+
If "breaking", "migration", or "upgrade-action" apply, fill in the
21+
relevant block below. Whoever cuts the next release pulls these PRs
22+
via the GitHub UI / `gh pr list --label "release: breaking"` and
23+
copies the details into the release body.
24+
-->
25+
26+
- [ ] `release: breaking` — public API shape, admin workflow, or DB
27+
schema change that requires an upgrade action.
28+
- [ ] `release: migration` — adds a file under `backend/drizzle/*.sql`.
29+
- [ ] `release: upgrade-action` — operators must run a manual step
30+
(rename a code, re-link an item, set an env var, regenerate a token).
31+
- [ ] `release: internal` — no user-visible impact (refactor, tests,
32+
docs, CI). Default for refactors and test-only PRs.
33+
34+
### Breaking change details
35+
36+
<!--
37+
Required if `release: breaking` is ticked. What broke for whom?
38+
Be precise: include API path, schema column, admin URL, etc.
39+
This text gets copied into the GitHub release body.
40+
-->
41+
42+
### Migration & upgrade actions
43+
44+
<!--
45+
Required if `release: migration` or `release: upgrade-action` is ticked.
46+
47+
Migration:
48+
- Filename and what it does to data (not just schema — call out any
49+
backfill, default values, or dropped columns).
50+
51+
Upgrade actions:
52+
- Concrete commands or admin clicks operators must run, in order.
53+
-->
54+
55+
### Notes for AI agents
56+
57+
<!--
58+
Optional but encouraged when this PR encodes a non-obvious decision
59+
(an invariant two files must respect, a deliberate workaround for a
60+
tooling quirk, a path we tried and rejected). These migrate into
61+
CHANGELOG.md at release time.
62+
-->
63+
1364
## Checklist
1465

1566
- [ ] Tests pass: `cd backend && npm run check && npm run test:run`
1667
- [ ] Tests pass: `cd web && npm run test:run && npm run build`
1768
- [ ] Tests pass: `cd web/workers/chat && npx tsc --noEmit && npm run test:run`
1869
- [ ] No secrets, real tenant IDs, or `.dev.vars` committed
1970
- [ ] Docs updated if behaviour or env vars changed
71+
- [ ] Applied at least one `release:` label
2072

2173
## Licensing
2274

.github/RELEASE_TEMPLATE.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,18 @@ Drop sections that don't apply, but DO NOT drop "Breaking changes" or
88
"Upgrade actions" — leave them with "None." if there are none. Self-hosters
99
read these first.
1010
11-
Pull from the matching CHANGELOG.md entry. The release body should be a
12-
self-contained snapshot — readers should not need to follow a link to know
13-
whether they have to do something.
11+
Source material: every PR merged since the previous tag carries one or more
12+
`release:` labels. PRs labelled `release: breaking`, `release: migration`,
13+
or `release: upgrade-action` have prefilled prose under their respective
14+
template sections — copy/aggregate those into the body below. PRs labelled
15+
only `release: internal` are skipped.
16+
17+
LAST=$(git describe --tags --abbrev=0)
18+
gh pr list --state merged \
19+
--search "merged:>$(git log -1 --format=%cI "$LAST")" \
20+
--label "release: breaking" --label "release: migration" \
21+
--label "release: upgrade-action" \
22+
--json number,title,body,labels
1423
-->
1524

1625
## Summary

CONTRIBUTING.md

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,24 +51,50 @@ a separate license (see [COMMERCIAL.md](COMMERCIAL.md)).
5151
- Tailwind for styling.
5252
- One feature/fix per PR. Keep diffs small.
5353

54-
## Releasing
54+
## Release impact labels
55+
56+
Every PR must carry at least one `release:` label so the next release can be
57+
assembled from merged PRs without re-reading every diff:
5558

56-
When publishing a GitHub release:
59+
- `release: breaking` — public API shape, admin workflow, or DB schema change
60+
requiring an upgrade action.
61+
- `release: migration` — adds a file under `backend/drizzle/*.sql`.
62+
- `release: upgrade-action` — operators must run a manual step on upgrade.
63+
- `release: internal` — no user-visible impact (refactor, tests, docs, CI).
5764

58-
1. Add a new dated entry at the top of [CHANGELOG.md](CHANGELOG.md). Always
59-
include **Breaking changes**, **Migrations**, and **Upgrade actions**
65+
A single PR can carry several. Use `release: internal` as the default for PRs
66+
that genuinely don't affect users — that signals "consider me, then skip me"
67+
rather than "I forgot to label". The PR template in
68+
[.github/PULL_REQUEST_TEMPLATE.md](.github/PULL_REQUEST_TEMPLATE.md) prompts
69+
the author to fill in details for each non-internal label they tick; that text
70+
flows into the release body verbatim.
71+
72+
## Releasing
73+
74+
1. Find the previous tag: `LAST=$(git describe --tags --abbrev=0 2>/dev/null
75+
|| git rev-list --max-parents=0 HEAD)`.
76+
2. List PRs that need release-note coverage:
77+
```bash
78+
gh pr list --state merged --search "merged:>$(git log -1 --format=%cI "$LAST")" \
79+
--json number,title,labels,body \
80+
--label "release: breaking" --label "release: migration" --label "release: upgrade-action"
81+
```
82+
Each of these contributes a paragraph to the release body — copy the
83+
"Breaking change details" / "Migration & upgrade actions" sections from
84+
each PR description.
85+
3. Add a new dated entry at the top of [CHANGELOG.md](CHANGELOG.md). Always
86+
keep **Breaking changes**, **Migrations**, and **Upgrade actions**
6087
subsections — write "None." rather than dropping them.
61-
2. Tag the commit (`git tag vYYYY.MM.DD && git push --tags`) or use the
62-
GitHub UI.
63-
3. Draft the release body using
64-
[.github/RELEASE_TEMPLATE.md](.github/RELEASE_TEMPLATE.md) as a starting
65-
point — copy its contents into the release form, or pass it via
88+
4. Tag the release commit (`git tag vYYYY.MM.DD && git push --tags`).
89+
5. Draft the GitHub release body from
90+
[.github/RELEASE_TEMPLATE.md](.github/RELEASE_TEMPLATE.md):
6691
`gh release create <tag> --notes-file .github/RELEASE_TEMPLATE.md` and
67-
edit the resulting body. Keep the breaking-changes / upgrade-actions
68-
blocks even if empty: self-hosters scan these first.
92+
edit the resulting body. Paste the labelled PR content into the matching
93+
sections.
6994

7095
The release body should be self-contained — operators should not need to
71-
click through to CHANGELOG.md to find out whether they have work to do.
96+
click through to CHANGELOG.md or individual PRs to find out whether they
97+
have work to do.
7298

7399
## Reporting bugs
74100

0 commit comments

Comments
 (0)