11# Releasing la-stack
22
3- This guide documents the exact commands for performing a clean release using a
4- dedicated release PR, followed by tagging, publishing to crates.io, and
5- creating a GitHub release.
3+ This guide documents the release flow for ` vX.Y.Z ` : prepare a dedicated
4+ release PR, merge it, create the final annotated tag from the generated
5+ changelog, publish to crates.io, and create the GitHub release.
6+
7+ The release changelog is generated with ` git-cliff --tag ` through
8+ ` just changelog-unreleased ` , so no temporary local tag is needed.
69
710Applies to versions vX.Y.Z. Prefer updating documentation before publishing
811to crates.io.
@@ -25,7 +28,7 @@ Verify your git remotes:
2528git remote -v
2629```
2730
28- Ensure your local main is up to date before beginning:
31+ Ensure your local ` main ` is up to date before beginning:
2932
3033``` bash
3134git checkout main
@@ -36,49 +39,50 @@ git pull --ff-only
3639
3740## Step 1: Create a clean release PR
3841
39- This PR should primarily include: version bumps, changelog updates, and
40- documentation updates. All major code changes should already be on main.
42+ This PR should primarily include version bumps, changelog updates, benchmark
43+ comparison updates, and documentation updates. All major code changes should
44+ already be on ` main ` .
4145
42- ** Exception:** Small, critical fixes discovered during the release process
43- (e.g., documentation errors, script bugs, formatting issues) may be included
44- but should be minimal and release-critical only.
46+ Small, critical fixes discovered during the release process may be included,
47+ but keep them minimal and release-critical.
4548
46491 . Create the release branch
4750
4851``` bash
49- git checkout -b release/$TAG
52+ git checkout -b " release/$TAG "
5053```
5154
52552 . Bump versions
5356
54- Preferred ( if cargo-edit is installed) :
57+ Preferred, if ` cargo-edit ` is installed:
5558
5659``` bash
57- # Bump package version in Cargo.toml
58- cargo set-version $VERSION
60+ cargo set-version " $VERSION "
5961```
6062
61- Alternative: edit ` Cargo.toml ` manually ( update ` version = "..." ` under
62- ` [package] ` ) .
63+ Alternative: edit ` Cargo.toml ` manually and update ` version = "..." ` under
64+ ` [package] ` .
6365
64- Update references in documentation (search, then manually edit as needed) :
66+ Review version references in documentation:
6567
6668``` bash
67- # List occurrences of version-like strings to review
6869rg -n " \bv?[0-9]+\.[0-9]+\.[0-9]+\b" README.md docs/ || true
6970```
7071
71- 3 . Generate changelog using a temporary local tag (DO NOT PUSH this tag)
72+ 3 . Generate the release changelog
7273
7374``` bash
74- # Create a temporary annotated tag locally to enable changelog generation
75- # Do not push this tag; it will be recreated later after merge
76- git tag -a " $TAG " -m " la-stack $TAG "
77-
78- # Generate changelog (git-cliff + post-processing)
79- just changelog
75+ # Generates CHANGELOG.md as though TAG already exists, then applies
76+ # markdown hygiene and archives completed minor release series.
77+ just changelog-unreleased " $TAG "
8078```
8179
80+ ` just changelog-unreleased ` runs
81+ ` GIT_CLIFF_OFFLINE=true git-cliff --tag "$TAG" -o CHANGELOG.md ` , then
82+ ` postprocess-changelog ` , then ` archive-changelog ` . The root changelog keeps
83+ Unreleased plus the active minor series; older completed minor series live
84+ under ` docs/archive/changelog/ ` .
85+
82864 . Run benchmarks and update the README comparison table
8387
8488``` bash
@@ -101,7 +105,14 @@ just bench-save-baseline $TAG
101105This baseline can be compared against in future optimization work.
102106See ` docs/BENCHMARKING.md ` for the full comparison workflow.
103107
104- 6 . Stage and commit release artifacts
108+ 6 . Validate the release branch
109+
110+ ``` bash
111+ just ci
112+ cargo publish --locked --dry-run
113+ ```
114+
115+ 7 . Stage and commit release artifacts
105116
106117``` bash
107118git add Cargo.toml Cargo.lock CHANGELOG.md README.md docs/
@@ -114,7 +125,7 @@ git commit -m "chore(release): release $TAG
114125- Update documentation for release"
115126```
116127
117- 7 . Push the branch and open a PR
128+ 8 . Push the branch and open a PR
118129
119130``` bash
120131git push -u origin " release/$TAG "
@@ -124,64 +135,46 @@ PR metadata:
124135
125136- Title: chore(release): release $TAG
126137- Description: Clean release PR with version bump, changelog, and
127- documentation updates. No code changes .
138+ documentation updates. No feature work .
128139
129- Note: Do NOT push the temporary tag created in step 3.
140+ ### Handling fixes discovered during the release process
130141
131- ### Handling fixes discovered during release process
142+ If you discover issues after generating the changelog:
132143
133- If you discover issues (bugs, formatting problems, etc.) after creating the
134- changelog:
135-
136- 1 . ** For critical fixes that must be in this release:**
144+ 1 . For critical fixes that must be in this release, make and commit the fix,
145+ then regenerate the release changelog:
137146
138147 ``` bash
139- # Make your fixes
140- # Run code quality tools
141- # Commit the fixes
142- git add .
143- git commit -m " fix: [description of fix]"
144-
145- # Delete the temporary tag and regenerate changelog
146- git tag -d " $TAG "
147- git tag -a " $TAG " -m " la-stack $TAG "
148- just changelog
149-
150- # Commit updated changelog
151- git add CHANGELOG.md
148+ just changelog-unreleased " $TAG "
149+ git add CHANGELOG.md docs/archive/changelog/
152150 git commit -m " docs: update changelog with release fixes"
153151 ```
154152
155- 2 . ** For non-critical fixes:**
156- - Document them as known issues in the release notes
157- - Include them in the next release
158- - This avoids the changelog regeneration loop
153+ 2 . For non-critical fixes, document them as known issues in the release notes
154+ or include them in the next release.
159155
160156---
161157
162158## Step 2: After the PR is merged into main
163159
164- 1 . Sync your local main to the merge commit
160+ 1 . Sync your local ` main ` to the merge commit
165161
166162``` bash
167163git checkout main
168164git pull --ff-only
169165```
170166
171- 2 . Recreate the final annotated tag using the changelog content
167+ 2 . Create the final annotated tag using the changelog content
172168
173169``` bash
174- # Remove the temporary local tag if it exists
175- git tag -d " $TAG " 2> /dev/null || true
176-
177- # Create the final annotated tag with the changelog section as the tag message
178- # Note: For large changelogs (>125KB), this automatically creates an annotated
179- # tag with a reference message pointing to CHANGELOG.md instead of the full
180- # content
170+ # Creates the annotated tag from the matching CHANGELOG.md section.
171+ # Archived versions are read from docs/archive/changelog/ automatically.
172+ # For large changelogs (>125KB), the tag message points to the changelog
173+ # section instead of embedding the full content.
181174just tag " $TAG "
182175```
183176
184- 3 . ( Optional) Verify tag message content
177+ 3 . Optional: verify the tag message content
185178
186179``` bash
187180git tag -l --format=' %(contents)' " $TAG "
@@ -193,32 +186,35 @@ git tag -l --format='%(contents)' "$TAG"
193186git push origin " $TAG "
194187```
195188
196- 5 . Create the GitHub release with notes from the tag annotation
189+ 5 . Publish to crates.io
197190
198191``` bash
199- # Requires GitHub CLI (gh) and authenticated session
200- gh release create " $TAG " --notes-from-tag
192+ # Publish the crate (ensure docs are already updated on main via the PR)
193+ cargo publish --locked
201194```
202195
203- 6 . Publish to crates.io
196+ 6 . Create the GitHub release with notes from the tag annotation
204197
205198``` bash
206- # Sanity check before publishing
207- cargo publish --locked --dry-run
208-
209- # Publish the crate (ensure docs are already updated on main via the PR)
210- cargo publish --locked
199+ # Requires GitHub CLI (gh) and authenticated session
200+ gh release create " $TAG " --title " $TAG " --notes-from-tag
211201```
212202
203+ Always set the GitHub release title to the exact tag string, including the
204+ leading ` v ` .
205+
213206---
214207
215208## Notes and tips
216209
217- - Never push the temporary tag created for changelog generation; only push
218- the final tag after the PR is merged.
219- - Keep the release PR strictly to version + changelog + documentation to
220- maintain a clean history.
210+ - Do not create a temporary local release tag for changelog generation; use
211+ ` just changelog-unreleased "$TAG" ` .
212+ - Keep the release PR scoped to version, changelog, archive, benchmark
213+ comparison, and documentation changes.
214+ - ` just changelog ` regenerates the current changelog from existing tags and may
215+ update ` docs/archive/changelog/ ` .
216+ - ` just changelog-unreleased "$TAG" ` is for release PR preparation before the
217+ final tag exists.
218+ - ` just tag "$TAG" ` is for the final post-merge annotated tag.
221219- If multiple crates or files reference the version, confirm all of them are
222220 updated consistently.
223- - For future convenience, parts of this document can be automated into a
224- release script.
0 commit comments