A changelog, kept from now rather than assembled at the end
Every version bump gets an entry in the same commit. Not afterwards: the reason a change was made is known while it is being made and gone a week later, and a changelog assembled from commit subjects at release time is a list of things nobody can act on. Backfilled 0.8.2 through 0.9.8, because those shipped as a running deployment rather than as releases and 1.0.0's notes have to be assembled from something. The rule that earns the file its place is the last one in CLAUDE.md: a fix to something that *looked* like it worked gets a line, always. Those are the entries somebody stops working around a bug because of, and they are invisible from outside -- nobody reports a control that silently does nothing, they just quietly stop using it. Half of what is in here is that shape: a group delete that left its grants, a share panel that only saved if you also saved the resource, an update script that stopped after "== fetching ==". A release is a signed annotated tag whose message is that version's entry, and that is not decoration -- /admin/updates reads release notes out of the tag object, so the tag message is literally what an administrator sees on the update page. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1645,6 +1645,37 @@ that the right one works, because only the second half would have passed
|
||||
throughout. When adding a control that writes, check the verb against the route,
|
||||
and assert on the row rather than on the response.
|
||||
|
||||
## Releasing, and the changelog
|
||||
|
||||
**Every version bump gets a `CHANGELOG.md` entry, in the same commit.** Not
|
||||
afterwards and not at release time: the reason a change was made is known while
|
||||
it is being made and is gone a week later, and a changelog assembled from commit
|
||||
subjects at the end is a list of things nobody can act on.
|
||||
|
||||
Four rules, and the last is the one that earns the file its place:
|
||||
|
||||
- **Newest first, one section per version**, headed by the version alone.
|
||||
`## Unreleased` sits at the top between bumps.
|
||||
- **Written for somebody using or running this**, not for somebody reading the
|
||||
diff. "Deleting a group left every share naming it behind" is an entry; "call
|
||||
forget_principal in delete_group" is not.
|
||||
- **The version is `__version__` and nothing else.** `pyproject.toml` reads it
|
||||
from there, the service worker cache is keyed on it, and the footer shows it.
|
||||
- **A fix to something that *looked* like it worked gets a line, always.** Those
|
||||
are the entries somebody stops working around a bug because of, and they are
|
||||
invisible from the outside: nobody reports a control that silently does
|
||||
nothing, they just stop using it.
|
||||
|
||||
A release is a **signed annotated tag** whose message is that version's entry --
|
||||
`git tag -s v1.0.0 -m "$(…)"`. That is not decoration: `/admin/updates` reads
|
||||
release notes out of the tag object with `git for-each-ref`, so the tag message
|
||||
*is* what an administrator sees on the update page. `services/updates.py` strips
|
||||
the signature block, PGP and SSH both.
|
||||
|
||||
The first tagged release is **1.0.0**. Everything before it shipped as a running
|
||||
deployment, which is why `CHANGELOG.md` covers versions that were never released
|
||||
-- 1.0.0's notes are assembled from them.
|
||||
|
||||
## Changing the schema
|
||||
|
||||
There is no Alembic, but there *is* `db/migrations.py`. It compares the declared
|
||||
|
||||
Reference in New Issue
Block a user