Files
2026-03-24 11:09:48 +05:30

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 audit and pip-audit locally 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.md has a ## [X.Y.Z] section (not [Unreleased]) with all changes since the last release documented under ### Added, ### Changed, ### Fixed, ### Removed headings.
  • Public docs match the release: docs/conf.py, docs/changelog.rst, and docs/support_matrix.rst reflect 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.toml is the source of truth. Sync the others to match before tagging.


Step 3 — Update CHANGELOG.md

  1. Open CHANGELOG.md.
  2. Rename the [Unreleased] section to [X.Y.Z] — YYYY-MM-DD (today's date).
  3. Add a fresh empty [Unreleased] section at the top.
  4. 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.rst with a concise release-notes entry
  • docs/support_matrix.rst if 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

  1. Go to Releases → Draft a new release in the GitHub UI.
  2. Select the tag v0.2.0 you just pushed.
  3. Set the release title to v0.2.0.
  4. Paste the changelog section for v0.2.0 into the release notes.
  5. 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

  1. Watch the Actions tab: the release wheel jobs, build-sdist, publish (PyPI), publish-cratesio (crates.io), and the wasm-publish workflow (npm).
  2. After the publish job 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))"
  1. 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:

  1. Branch from the release tag: git checkout -b hotfix/0.1.1 v0.1.0
  2. Apply the fix, bump to 0.1.1, update CHANGELOG.
  3. Merge the branch into main.
  4. Tag and release as above.

Note: ferro_ta_core is published to crates.io automatically by the CI job publish-cratesio when you publish a release (requires CARGO_REGISTRY_TOKEN secret).


See also