6.4 KiB
Release Playbook
This document describes the step-by-step process for cutting a new ferro-ta release. Follow every step in order to produce a consistent, reproducible release.
For the packaging and release overview, see PACKAGING.md.
Publish matrix (all automatic on release)
| Artifact | How |
|---|---|
| PyPI | CI job publish using PyPI Trusted Publishing (OIDC) |
| npm (WASM) | Workflow wasm-publish |
| crates.io | CI job publish-cratesio |
PyPI releases are expected to include:
- Wheels for CPython 3.10, 3.11, 3.12, and 3.13
- Linux x86_64 (
manylinux_2_17) - macOS universal2
- Windows x86_64
- One source distribution (
sdist)
Pre-release checklist
Before starting a release:
- All CI checks are green on
main: Rust (fmt, clippy), tests (with coverage gate), lint (ruff), typecheck (mypy, pyright), docs (Sphinx), WASM, audit (cargo-audit, pip-audit), fuzz (no crashes). - Security audit clean: Run
cargo auditandpip-auditlocally and confirm no high/critical vulnerabilities. Address any findings before tagging.bash cargo audit pip-audit # or: uv run --with pip-audit pip-audit - No open blocking issues or PRs that must land first.
CHANGELOG.mdhas a## [X.Y.Z]section (not[Unreleased]) with all changes since the last release documented under### Added,### Changed,### Fixed,### Removedheadings.- Public docs match the release:
docs/conf.py,docs/changelog.rst, anddocs/support_matrix.rstreflect the version and current support status.
Step 1 — Decide the version number
Follow Semantic Versioning 2.0.0 and the policy in VERSIONING.md:
| Change type | Version component to bump |
|---|---|
| Breaking API change (indicator removed, parameter renamed, return type changed) | MAJOR |
| New indicators, features, or bindings (backward-compatible) | MINOR |
| Bug fixes, performance, docs-only, dependency bumps | PATCH |
Example: current version is 0.1.0 and you are adding new indicators → new version is 0.2.0.
Step 2 — Sync version everywhere
These files must carry the same version string (e.g. 0.2.0). The easiest
way to do that is:
python3 scripts/bump_version.py 0.2.0
python3 scripts/bump_version.py --check
That script updates the tracked release-version carriers for you.
Files covered by the bump script:
| File | Location |
|---|---|
Cargo.toml |
Root (source of truth) |
crates/ferro_ta_core/Cargo.toml |
Same version for crates.io publish |
crates/ferro_ta_core/README.md |
Installation snippet should show the current crate version |
pyproject.toml |
Root |
wasm/package.json |
Package version |
conda/meta.yaml |
Conda recipe version |
docs/conf.py |
Default Sphinx release must resolve to the same version |
Cargo.toml (root):
[package]
name = "ferro_ta"
version = "X.Y.Z" # ← or use scripts/bump_version.py X.Y.Z
pyproject.toml:
[project]
version = "X.Y.Z" # ← must match Cargo.toml exactly
Rule:
Cargo.tomlis the source of truth. Sync the others to match before tagging.
Step 3 — Update CHANGELOG.md
- Open
CHANGELOG.md. - Rename the
[Unreleased]section to[X.Y.Z] — YYYY-MM-DD(today's date). - Add a fresh empty
[Unreleased]section at the top. - Update the comparison links at the bottom:
[Unreleased]: https://github.com/pratikbhadane24/ferro-ta/compare/vX.Y.Z...HEAD
[X.Y.Z]: https://github.com/pratikbhadane24/ferro-ta/compare/vPREVIOUS...vX.Y.Z
Follow the Keep a Changelog format:
Added, Changed, Deprecated, Removed, Fixed, Security.
Also update the docs-facing release surfaces for the same version:
docs/changelog.rstwith a concise release-notes entrydocs/support_matrix.rstif supported versions, tested wheels, or module stability changed
Step 4 — Commit the version bump
git add Cargo.toml crates/ferro_ta_core/Cargo.toml pyproject.toml wasm/package.json CHANGELOG.md
git commit -m "chore: release v0.2.0"
git push origin main
Wait for CI to pass on this commit before proceeding.
Step 5 — Create and push the tag
git tag v0.2.0
git push origin v0.2.0
Tags must be in the form
vMAJOR.MINOR.PATCH(e.g.v0.2.0).
Step 6 — Create a GitHub Release
- Go to Releases → Draft a new release in the GitHub UI.
- Select the tag
v0.2.0you just pushed. - Set the release title to
v0.2.0. - Paste the changelog section for
v0.2.0into the release notes. - Click Publish release.
Publishing the release triggers the CI wheel build jobs, build-sdist, and publish
automatically (the workflow responds to release: published). The PyPI upload
uses Trusted Publishing via GitHub OIDC, so no PYPI_API_TOKEN secret is used.
Step 7 — Monitor CI and verify PyPI
- Watch the Actions tab: the release wheel jobs,
build-sdist,publish(PyPI),publish-cratesio(crates.io), and the wasm-publish workflow (npm). - After the
publishjob succeeds, verify the package is live:
pip install ferro-ta==0.2.0
python -c "import ferro_ta; print(ferro_ta.__version__ if hasattr(ferro_ta,'__version__') else 'ok')"
For version-specific verification, also check at least one install on each supported Python line, for example:
uv venv --python 3.13 .venv-313
. .venv-313/bin/activate
uv pip install ferro-ta==0.2.0
python -c "import ferro_ta; print(ferro_ta.SMA([1.0, 2.0, 3.0], 2))"
- If anything fails: fix the issue, bump to a patch version (
0.2.1), and repeat.
Hotfix releases
For urgent bug fixes on a released version:
- Branch from the release tag:
git checkout -b hotfix/0.1.1 v0.1.0 - Apply the fix, bump to
0.1.1, update CHANGELOG. - Merge the branch into
main. - Tag and release as above.
Note:
ferro_ta_coreis published to crates.io automatically by the CI jobpublish-cratesiowhen you publish a release (requiresCARGO_REGISTRY_TOKENsecret).
See also
- VERSIONING.md — versioning policy and breaking-change rules
- CHANGELOG.md — changelog history
- CONTRIBUTING.md — development setup and PR guidelines