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
ST4 --> ST5["git checkout main && git pull<br/>git tag vX.Y.Z<br/>git push origin vX.Y.Z"]:::git
35
+
ST4 --> ST5["git checkout main && git pull<br/>git tag -d vX.Y.Z (local)<br/>git tag vX.Y.Z && git push origin vX.Y.Z"]:::git
36
36
ST5 --> ST6[CI: publish-pypi.yml]:::ci
37
37
ST6 --> ST7[PyPI + GitHub Release]:::stable
38
38
@@ -75,10 +75,10 @@ If you update any dependencies (e.g. to resolve security findings), regenerate t
75
75
Then verify the change does not break any tests.
76
76
```
77
77
78
-
**Security audit:** run `pip-audit` and resolve any vulnerability with an available fix before bumping the version:
78
+
**Security audit:** run `just audit` and resolve any vulnerability with an available fix before bumping the version:
79
79
80
80
```bash
81
-
poetry run pip-audit
81
+
just audit
82
82
```
83
83
84
84
Vulnerabilities with no upstream fix available should be noted and tracked as known accepted risks.
@@ -159,69 +159,105 @@ Prefer `just commit` over a manual `git commit` to stay consistent with the conv
159
159
160
160
## 6. Version bump
161
161
162
+
The version bump is driven entirely by [Commitizen](https://commitizen-tools.github.io/commitizen/). The increment (MAJOR / MINOR / PATCH) is inferred from the conventional-commit messages since the last tag, the version in `pyproject.toml` is updated, and the matching `CHANGELOG.md` section is generated and committed with an annotated tag.
163
+
162
164
```{important}
163
-
Always run `--dry-run` first and review the proposed CHANGELOG entries carefully before applying the bump.
165
+
Always run `--dry-run` first and review the proposed version and CHANGELOG entries carefully before applying the bump.
166
+
```
167
+
168
+
The following Commitizen settings in `pyproject.toml` shape this behaviour:
169
+
170
+
| Setting | Value | Effect |
171
+
| --- | --- | --- |
172
+
|`prerelease_offset`|`1`| Prereleases start at `rc1` (not the default `rc0`) |
173
+
|`changelog_merge_prerelease`|`true`| On the stable bump, all `rcN` CHANGELOG sections are rolled up into a single `vX.Y.Z` section |
174
+
|`update_changelog_on_bump`|`true`|`CHANGELOG.md` is regenerated automatically on every bump |
175
+
176
+
The bump commands are wrapped in `just` recipes so the correct Commitizen flags are applied consistently:
|`just bump-rc`|`cz bump --prerelease rc`| Apply an RC bump |
182
+
|`just bump-preview`|`cz bump --dry-run`| Preview a stable bump |
183
+
|`just bump`|`cz bump`| Apply a stable bump |
184
+
185
+
Each recipe forwards extra arguments to Commitizen, so flags such as `--increment MAJOR` can be appended directly (e.g. `just bump-rc-preview --increment MAJOR`).
186
+
187
+
### 6a. Release candidate bump
188
+
189
+
Use the `bump-rc` recipes to cut an RC. The first prerelease of a cycle is `rc1` (thanks to `prerelease_offset = 1`); subsequent ones increment to `rc2`, `rc3`, and so on.
190
+
191
+
```{note}
192
+
Commitizen can only infer the target version from commits. For a **major** release where the commit history does not contain a `feat!:` / `BREAKING CHANGE:` marker, force the increment explicitly with `--increment MAJOR` (likewise `MINOR` / `PATCH`).
164
193
```
165
194
166
195
**Step 1, preview:**
167
196
168
197
```bash
169
-
poetry run cz bump --dry-run
198
+
# Append --increment MAJOR/MINOR/PATCH if the bump is not inferred correctly
199
+
just bump-rc-preview
170
200
```
171
201
172
-
Inspect the output:
173
-
174
-
- The proposed increment (MAJOR / MINOR / PATCH) matches expectations
175
-
- The CHANGELOG entries are complete and correctly classified
176
-
- There are no duplicate entries (can happen when multiple commits share identical messages)
202
+
Confirm the proposed tag (e.g. `v2.0.0rc1`) and that the CHANGELOG entries are complete and correctly classified.
177
203
178
204
**Step 2, apply:**
179
205
180
206
```bash
181
-
poetry run cz bump
207
+
just bump-rc
182
208
```
183
209
184
-
This will:
185
-
186
-
- Update `version` in `pyproject.toml`
187
-
- Append the new section to `CHANGELOG.md`
188
-
- Create a local commit: `bump: version X.Y.Z-1 → X.Y.Z`
210
+
This updates `version` in `pyproject.toml`, appends the `vX.Y.ZrcN` section to `CHANGELOG.md`, creates the `bump:` commit, and creates the `vX.Y.ZrcN` tag locally.
189
211
190
-
**Step 3, review the bump commit:**
212
+
**Step 3, review and push** (commit and tag together):
191
213
192
214
```bash
193
215
git show HEAD
216
+
git push --follow-tags origin release/vX.Y.Z
194
217
```
195
218
196
-
Check that `pyproject.toml` shows the correct version and that `CHANGELOG.md` reads cleanly. Manually amend duplicate entries if present, then push:
219
+
```{note}
220
+
`--follow-tags` pushes the annotated `vX.Y.ZrcN` tag along with the branch in one step, which triggers `publish-testpypi.yml`. See **[Tag and publish a release candidate](#7-tag-and-publish-a-release-candidate)** below if you prefer to push the tag separately.
221
+
```
222
+
223
+
### 6b. Stable bump
224
+
225
+
When all RCs are approved, cut the final stable version with the plain `bump` recipes. Because `changelog_merge_prerelease = true`, the intermediate `rcN` sections are merged into a single complete `vX.Y.Z` CHANGELOG section, so end users see the full release notes in one place.
197
226
198
227
```bash
199
-
git push origin release/vX.Y.Z
228
+
just bump-preview # append --increment MAJOR if needed
229
+
just bump
200
230
```
201
231
202
-
**For a release candidate**, set the version explicitly instead of using `cz bump`:
232
+
This updates `pyproject.toml`, regenerates `CHANGELOG.md` (with prereleases merged), and creates the `bump:` commit plus the `vX.Y.Z` tag.
233
+
234
+
**Review the bump commit:**
203
235
204
236
```bash
205
-
poetry version X.Y.ZrcN
206
-
poetry lock
207
-
git add pyproject.toml poetry.lock CHANGELOG.md
208
-
git commit -m "bump: version X.Y.Z-1 → X.Y.ZrcN"
237
+
git show HEAD
238
+
```
239
+
240
+
Check that `pyproject.toml` shows the correct version and that `CHANGELOG.md` reads cleanly. Manually amend duplicate entries if present, then push the branch (the stable tag is pushed later, after the release PR is merged — see step 9):
241
+
242
+
```bash
243
+
git push origin release/vX.Y.Z
209
244
```
210
245
211
246
See **[Versioning](versioning.md)** for the full SemVer rules and commit-type reference.
212
247
213
248
## 7. Tag and publish a release candidate
214
249
215
-
RC tags are pushed **directly from the release branch**, with no PR to `main` required.
250
+
`cz bump --prerelease rc` (step 6a) already created the annotated `vX.Y.ZrcN` tag locally. RC tags are pushed **directly from the release branch**, with no PR to `main` required.
251
+
252
+
If you pushed with `git push --follow-tags` in step 6a, the tag is already live and you can skip to verifying CI. Otherwise, push the tag explicitly:
216
253
217
254
```bash
218
-
git tag -a vX.Y.ZrcN -m "Release candidate vX.Y.ZrcN"
219
255
git push origin vX.Y.ZrcN
220
256
```
221
257
222
258
This triggers `publish-testpypi.yml`, which publishes to **TestPyPI** and creates a GitHub pre-release.
223
259
224
-
If issues are found, fix them on the release branch (return to step 2), bump to the next RC (`rcN+1`), and repeat.
260
+
If issues are found, fix them on the release branch (return to step 2), bump to the next RC with `cz bump --prerelease rc` (which yields `rcN+1`), and repeat.
225
261
226
262
## 8. Release PR (stable only)
227
263
@@ -236,10 +272,11 @@ Once all RCs are approved (or skipping RC for a straightforward release), open a
236
272
237
273
## 9. Create and push the stable tag
238
274
239
-
After the release PR is merged into `main`:
275
+
The stable `cz bump` in step 6b created a local `vX.Y.Z` tag on the release branch, but the authoritative tag must point at the merge commit on `main`. After the release PR is merged into`main`, drop the local tag and re-create it on`main`:
240
276
241
277
```bash
242
278
git checkout main && git pull
279
+
git tag -d vX.Y.Z # remove the local tag created by cz bump
0 commit comments