You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(readme): document the release-cutting workflow
New "Cutting a release" subsection under Working in the codebase
(placed adjacent to "Commit message convention" since releases are
driven by the conventional-commit history). Documents the seven-step
recipe used to cut v1.0.1: git cliff --bumped-version → pyproject
bump + make lock → git cliff --tag → chore commit → annotated tag →
push commit + tag → gh release create --notes-from-tag --verify-tag.
Adds non-obvious-detail callouts for each tool flag (why
--bumped-version, what make lock regenerates, why --notes-from-tag,
why --verify-tag). TOC updated to include the new subsection.
@@ -634,6 +634,46 @@ The committed history is the input to **[git-cliff](https://github.com/orhun/git
634
634
635
635
Forks that want to *enforce* the convention at author time (rather than rely on the reviewer + pre-commit gates) can adopt **[Commitizen](https://github.com/commitizen-tools/commitizen)** as an interactive authoring helper — it prompts for type/scope/description and refuses to create commits that don't conform. Intentionally not wired into this project because the convention is short enough to author by hand and the existing pre-commit hooks catch the common drift sources; meaningful in larger teams where conformance otherwise erodes.
636
636
637
+
### Cutting a release
638
+
639
+
Releases follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and are driven from the conventional-commit history. The end-to-end recipe:
640
+
641
+
```bash
642
+
# 1. Ask git-cliff what version to bump to based on commits since the last tag
643
+
git cliff --bumped-version
644
+
645
+
# 2. Bump pyproject.toml to that version, regenerate the lockfiles
646
+
sed -i '''s/^version = ".*"/version = "X.Y.Z"/' pyproject.toml
647
+
make lock
648
+
649
+
# 3. Regenerate the changelog (treats unreleased commits as if tagged X.Y.Z)
650
+
git cliff --tag vX.Y.Z -o CHANGELOG.md
651
+
652
+
# 4. Commit everything in one chore commit
653
+
git add pyproject.toml uv.lock CHANGELOG.md
654
+
git commit -m "chore: release vX.Y.Z"
655
+
656
+
# 5. Tag with annotated release notes — the body shows up on the Releases page
657
+
git tag -a vX.Y.Z -m "vX.Y.Z — short title
658
+
659
+
Longer release notes here..."
660
+
661
+
# 6. Push the commit and the tag
662
+
git push origin main
663
+
git push origin vX.Y.Z
664
+
665
+
# 7. Publish the GitHub Release (pulls notes from the annotated tag)
-**`git cliff --bumped-version`** reads conventional-commit types since the last tag and follows SemVer: `feat:` triggers a minor bump, `fix:` a patch, `docs`/`chore`/`ci` etc. stay at patch. Breaking changes (`!` or `BREAKING CHANGE:` footer) trigger a major bump. v1.0.1 was chosen this way — only `docs:` commits since v1.0.0, so `--bumped-version` returned `v1.0.1`.
672
+
-**`make lock`** regenerates `uv.lock` and `lambda/requirements.txt` so the lockfile records the new project version. The only diff in `uv.lock` is the one-line `version =` field for this project; transitive pins do not move.
673
+
-**`git cliff --tag vX.Y.Z -o CHANGELOG.md`** regenerates the *entire*`CHANGELOG.md` rather than prepending — this keeps the footer URL list (`[X.Y.Z]: .../compare/..`) consistent across releases. The cost is rewriting unchanged previous sections; in practice that's a no-op since the content is deterministic.
674
+
-**`--notes-from-tag`** on `gh release create` pulls the annotated tag body into the GitHub Release object, so the same release notes are available via `git show vX.Y.Z`, the GitHub web UI, and the Releases API without duplicating them.
675
+
-**`--verify-tag`** rejects the call if the tag doesn't exist on origin, catching the "forgot to `git push origin vX.Y.Z`" case before it creates an orphan Release.
676
+
637
677
### Documentation
638
678
639
679
The docs site is built by [Zensical](https://zensical.org/) (MkDocs-Material's successor, same maintainer) with the [mkdocstrings](https://mkdocstrings.github.io/) Python handler. It covers two audiences:
0 commit comments