Skip to content

Commit b78a5ae

Browse files
committed
docs: rewrite release guide with sequential steps
1 parent b1e4dcc commit b78a5ae

1 file changed

Lines changed: 194 additions & 61 deletions

File tree

docs/developer_guide/release.md

Lines changed: 194 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Build and release
1+
# Build and Release
22

3-
The document outlines the steps to build and release the `deeptab` package. At this point, it is assumed that the development and testing of the package have been completed successfully.
3+
The document outlines the steps to build and release the `deeptab` package. It is assumed that all feature branches and PRs for the release have been reviewed, approved, and merged into `main` before starting this process.
44

55
## Release workflow
66

@@ -15,83 +15,204 @@ The document outlines the steps to build and release the `deeptab` package. At t
1515
'edgeLabelBackground': '#f9fafb'
1616
}}}%%
1717
flowchart TD
18-
A[Create release/vX.Y.Z branch]:::setup --> B{Release type?}:::decision
19-
B -->|RC| RC1[Bump version e.g. 1.7.0rc1]:::setup
20-
B -->|Stable| ST1[Bump version e.g. 1.7.0]:::setup
21-
RC1 --> RC2[Update CHANGELOG.md]:::setup
22-
RC2 --> RC3[Commit & push branch]:::setup
23-
RC3 --> RC4["git tag vX.Y.ZrcN<br/>git push origin vX.Y.ZrcN"]:::git
24-
RC4 --> RC5[CI: publish-testpypi.yml]:::ci
25-
RC5 --> RC6[TestPyPI + GitHub pre-release]:::rc
26-
RC6 -->|Issues found| RC1
27-
RC6 -->|RC approved| ST1
28-
ST1 --> ST2[Update CHANGELOG.md]:::setup
29-
ST2 --> ST3[Commit & push branch]:::setup
30-
ST3 --> ST4[Open PR: release/vX.Y.Z → main]:::pr
31-
ST4 --> ST5{Review & approve}:::decision
32-
ST5 --> ST6[Merge PR into main]:::pr
33-
ST6 --> ST7[git checkout main && git pull]:::git
34-
ST7 --> ST8["git tag vX.Y.Z<br/>git push origin vX.Y.Z"]:::git
35-
ST8 --> ST9[CI: publish-pypi.yml]:::ci
36-
ST9 --> ST10[PyPI + GitHub Release]:::stable
37-
38-
classDef setup fill:#dbeafe,stroke:#3b82f6,color:#1e3a5f
39-
classDef pr fill:#ede9fe,stroke:#8b5cf6,color:#3b0764
18+
A["git checkout main &#38;&#38; git pull<br/>git checkout -b release/vX.Y.Z"]:::git --> B[Hotfixes &#38; doc updates]:::setup
19+
B --> QA["Quality checks<br/>lint → format → check → test"]:::ci
20+
QA --> QAP{All pass?}:::decision
21+
QAP -->|No| B
22+
QAP -->|Yes| D["Build docs: just docs"]:::setup
23+
D --> E[Commit changes &#38; push branch]:::git
24+
E --> F{Release type?}:::decision
25+
F -->|RC| RC1["cz bump --dry-run<br/>then cz bump rcN"]:::setup
26+
F -->|Stable| ST1["cz bump --dry-run<br/>then cz bump"]:::setup
27+
RC1 --> RC2["git tag vX.Y.ZrcN<br/>git push origin vX.Y.ZrcN"]:::git
28+
RC2 --> RC3[CI: publish-testpypi.yml]:::ci
29+
RC3 --> RC4[TestPyPI + GitHub pre-release]:::rc
30+
RC4 -->|Issues found| B
31+
RC4 -->|RC approved| ST1
32+
ST1 --> ST2["Open PR: release/vX.Y.Z → main"]:::pr
33+
ST2 --> ST3{Review &#38; approve}:::decision
34+
ST3 --> ST4[Merge PR into main]:::pr
35+
ST4 --> ST5["git checkout main &#38;&#38; git pull<br/>git tag vX.Y.Z<br/>git push origin vX.Y.Z"]:::git
36+
ST5 --> ST6[CI: publish-pypi.yml]:::ci
37+
ST6 --> ST7[PyPI + GitHub Release]:::stable
38+
39+
classDef setup fill:#dbeafe,stroke:#3b82f6,color:#1e3a5f
40+
classDef pr fill:#ede9fe,stroke:#8b5cf6,color:#3b0764
4041
classDef decision fill:#fef9c3,stroke:#ca8a04,color:#713f12
41-
classDef git fill:#f0fdf4,stroke:#22c55e,color:#14532d
42-
classDef ci fill:#fff7ed,stroke:#f97316,color:#7c2d12
43-
classDef rc fill:#fdf4ff,stroke:#d946ef,color:#701a75
44-
classDef stable fill:#ecfdf5,stroke:#10b981,color:#064e3b
42+
classDef git fill:#f0fdf4,stroke:#22c55e,color:#14532d
43+
classDef ci fill:#fff7ed,stroke:#f97316,color:#7c2d12
44+
classDef rc fill:#fdf4ff,stroke:#d946ef,color:#701a75
45+
classDef stable fill:#ecfdf5,stroke:#10b981,color:#064e3b
4546
```
4647

47-
## 1. Test documentation
48+
## 1. Create the release branch
4849

49-
It is expected from the contributor to update the documentation as an when required along side the change in source code. Please use the below process to test the documentation:
50+
After all PRs for the release are merged into `main`, create a dedicated release branch.
5051

51-
```sh
52-
cd docs/
52+
```{important}
53+
Always branch off from an up-to-date `main`. Never start a release from a stale local copy.
54+
```
55+
56+
```bash
57+
git checkout main && git pull
58+
git checkout -b release/vX.Y.Z
59+
git push -u origin release/vX.Y.Z
60+
```
61+
62+
## 2. Apply hotfixes and documentation updates
63+
64+
Use the release branch to apply any last-minute bug fixes, dependency security patches, or documentation updates required before the release.
65+
66+
```{note}
67+
Only **bug fixes and documentation changes** belong on the release branch. New features must target the next release cycle via `main`.
68+
```
69+
70+
```{warning}
71+
If you update any dependencies (e.g. to resolve security findings), regenerate the lock file immediately:
72+
73+
poetry update <package>
74+
75+
Then verify the change does not break any tests.
76+
```
77+
78+
**Security audit** — run `pip-audit` and resolve any vulnerability with an available fix before bumping the version:
79+
80+
```bash
81+
poetry run pip-audit
82+
```
83+
84+
Vulnerabilities with no upstream fix available should be noted and tracked as known accepted risks.
85+
86+
## 3. Quality checks
5387

54-
make doctest
88+
Run all checks in the order shown below. **Each step must pass cleanly before proceeding to the next.**
89+
90+
### 3.1 Linting
91+
92+
```bash
93+
just lint
5594
```
5695

57-
Fix any docstring related issue, then proceed with next steps.
96+
Runs `ruff check --fix` and auto-corrects fixable issues. Review and manually resolve any remaining errors.
5897

59-
## 2. Version update
98+
### 3.2 Formatting
99+
100+
```bash
101+
just format
102+
```
60103

61-
See **[Versioning](versioning.md)** for the full explanation of SemVer rules, commit types, and how `cz bump` works. The commands are summarised below.
104+
Runs `ruff format` to ensure consistent code style across the codebase.
62105

63-
**For a stable release** — let `cz bump` derive the next version automatically from conventional commits:
106+
### 3.3 Pre-commit hooks
64107

65108
```bash
66-
cz bump
109+
just check
110+
```
111+
112+
Runs all pre-commit hooks across all files: ruff lint/format, prettier (YAML/Markdown/JSON), and Pyright type checking.
113+
114+
```{important}
115+
If `just check` modifies any files, stage and commit them before continuing:
116+
117+
git add -u && git commit -m "style: apply pre-commit formatting"
118+
```
119+
120+
### 3.4 Unit tests
121+
122+
```bash
123+
just test
124+
```
125+
126+
Runs the full test suite with coverage reporting.
127+
128+
```{warning}
129+
A test failure at this stage must be fixed on the release branch before proceeding. Do not skip, suppress, or comment out failing tests.
130+
```
131+
132+
## 4. Documentation
133+
134+
Build the HTML docs locally. Sphinx treats all warnings as errors (`-W`), so every warning must be resolved before proceeding.
135+
136+
```bash
137+
just docs
138+
```
139+
140+
Review the rendered output in `docs/_build/html/`. Check for broken links, missing API entries, and any rendering issues on new or changed pages.
141+
142+
```{note}
143+
See the **[Documentation Guide](documentation.md)** for docstring conventions and tips on building docs locally.
144+
```
145+
146+
## 5. Commit all changes
147+
148+
Once all checks and the documentation build pass cleanly, stage and commit any outstanding changes:
149+
150+
```bash
151+
git add -A
152+
git commit -m "chore(release): pre-release fixes and QA for vX.Y.Z"
153+
git push origin release/vX.Y.Z
154+
```
155+
156+
```{note}
157+
Prefer `just commit` over a manual `git commit` to stay consistent with the conventional commit style enforced by commitizen.
158+
```
159+
160+
## 6. Version bump
161+
162+
```{important}
163+
Always run `--dry-run` first and review the proposed CHANGELOG entries carefully before applying the bump.
164+
```
165+
166+
**Step 1 — preview:**
167+
168+
```bash
169+
poetry run cz bump --dry-run
170+
```
171+
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)
177+
178+
**Step 2 — apply:**
179+
180+
```bash
181+
poetry run cz bump
67182
```
68183

69184
This will:
70185

71-
- Determine the next version from conventional commits since the last tag
72-
- Update the version in `pyproject.toml`
73-
- Update `CHANGELOG.md`
74-
- Create a local commit `bump: version X.Y.Z-1 → X.Y.Z`
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`
75189

76-
**For a release candidate** — set the version explicitly (e.g. `1.7.0rc1`):
190+
**Step 3 — review the bump commit:**
77191

78192
```bash
79-
poetry version 1.7.0rc1
80-
poetry lock
193+
git show HEAD
194+
```
195+
196+
Check that `pyproject.toml` shows the correct version and that `CHANGELOG.md` reads cleanly. Manually amend duplicate entries if present, then push:
197+
198+
```bash
199+
git push origin release/vX.Y.Z
81200
```
82201

83-
Then update `CHANGELOG.md` manually and commit:
202+
**For a release candidate** — set the version explicitly instead of using `cz bump`:
84203

85204
```bash
205+
poetry version X.Y.ZrcN
206+
poetry lock
86207
git add pyproject.toml poetry.lock CHANGELOG.md
87-
git commit -m "bump: version 1.6.1 → 1.7.0rc1"
208+
git commit -m "bump: version X.Y.Z-1 → X.Y.ZrcN"
88209
```
89210

90-
The version number follows the format `major.minor.patch` for stable, or `major.minor.patchrcN` for release candidates.
211+
See **[Versioning](versioning.md)** for the full SemVer rules and commit-type reference.
91212

92-
## 3. Tag and publish a release candidate
213+
## 7. Tag and publish a release candidate
93214

94-
RC tags are pushed **directly from the release branch** — no PR to `main` required.
215+
RC tags are pushed **directly from the release branch** — no PR to `main` is required.
95216

96217
```bash
97218
git tag -a vX.Y.ZrcN -m "Release candidate vX.Y.ZrcN"
@@ -100,36 +221,48 @@ git push origin vX.Y.ZrcN
100221

101222
This triggers `publish-testpypi.yml`, which publishes to **TestPyPI** and creates a GitHub pre-release.
102223

103-
If issues are found, fix them on the release branch, bump to the next RC (`rcN+1`), and repeat.
224+
If issues are found, fix them on the release branch (return to step 2), bump to the next RC (`rcN+1`), and repeat.
104225

105-
## 4. Release PR (stable only)
226+
## 8. Release PR (stable only)
106227

107-
Once all RCs are approved, open a PR from `release/vX.Y.Z` to `main`:
228+
Once all RCs are approved (or skipping RC for a straightforward release), open a PR from `release/vX.Y.Z` to `main` on GitHub.
108229

109230
- After review and approval, merge the PR
110231
- **Merging to `main` does NOT trigger a PyPI release**
111232

112-
> **Promoting a model from experimental to stable?** Verify the [Model Promotion Policy](model_promotion_policy.md) checklist is complete before merging a release PR that includes a promotion.
233+
```{important}
234+
**Promoting a model from experimental to stable?** Verify the [Model Promotion Policy](model_promotion_policy.md) checklist is complete before merging a release PR that includes a promotion.
235+
```
113236

114-
## 5. Create and push the stable tag
237+
## 9. Create and push the stable tag
115238

116-
After the release PR is merged:
239+
After the release PR is merged into `main`:
117240

118241
```bash
119242
git checkout main && git pull
120243
git tag -a vX.Y.Z -m "Release vX.Y.Z"
121244
git push origin vX.Y.Z
122245
```
123246

124-
## 6. Publish package
247+
```{warning}
248+
Pushing the tag triggers PyPI publication immediately and cannot be undone. Confirm that `main` is in the expected state and the version in `pyproject.toml` is correct before pushing.
249+
```
250+
251+
## 10. Publish package
125252

126-
The tag push automatically triggers the appropriate GitHub Actions workflow — see **[CI/CD](ci_cd.md)** for the full workflow details. In summary:
253+
The tag push automatically triggers the appropriate GitHub Actions workflow — see **[CI/CD](ci_cd.md)** for full details. In summary:
127254

128255
- Stable tag (`vX.Y.Z`) → `publish-pypi.yml` → PyPI + GitHub Release
129256
- RC tag (`vX.Y.ZrcN`) → `publish-testpypi.yml` → TestPyPI + GitHub pre-release
130257

131-
Both workflows use **OIDC Trusted Publishing** (no API tokens required).
258+
Both workflows use **OIDC Trusted Publishing** — no API tokens required.
259+
260+
## 11. GitHub Release
261+
262+
The GitHub Release is created automatically by the publish workflow. Once it appears, verify that:
132263

133-
## 7. GitHub Release
264+
- The release notes reflect the correct CHANGELOG section
265+
- Assets (wheel and sdist) are attached
266+
- The release is marked stable (not pre-release) for a stable tag
134267

135-
The GitHub Release is created automatically by the publish workflow. Verify the release notes are correct and add any manual context if needed.
268+
Add any manual context or migration notes to the release description if needed.

0 commit comments

Comments
 (0)