Files
ferro-ta/RELEASE.md
T
Pratik Bhadane 307beeca02 release: cut v1.0.0
Prepare the first public 1.0.0 release and finish the remaining CI hardening work.

Highlights:
- align Python, Rust, WASM, Conda, API, MCP, and docs version metadata to 1.0.0
- promote package metadata to Production/Stable and update stability/versioning docs for the stable series
- move the accumulated Unreleased notes into a dated 1.0.0 changelog section and keep a fresh top-level Unreleased block
- strengthen the changelog checker so it validates a single top-level Unreleased section
- fix the CI/package support mismatch by declaring Python >=3.10 consistently and gating pandas-ta extras to Python 3.12+
- restore Sphinx autodoc compatibility for documented ferro_ta.<module> imports by registering module aliases
- make the TA-Lib benchmark guardrail less flaky by checking median and tail-percentile speedups instead of failing on a single mild outlier
- switch PyPI publishing to OIDC-only trusted publishing and wire the changelog check into the required CI gate
- apply the Ruff-driven cleanup across the Python and test tree and refresh uv/cargo lockfiles

Validated locally:
- python3 scripts/check_changelog.py
- uv run --with ruff ruff check python tests
- uv run --with ruff ruff format --check python tests
- uv lock --check
- sphinx-build -b html docs docs/_build -W --keep-going
- build/install the ferro_ta 1.0.0 wheel successfully
2026-03-23 23:57:30 +05:30

5.1 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

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.

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). Update all before tagging:

File Location
Cargo.toml Root (source of truth)
crates/ferro_ta_core/Cargo.toml Same version for crates.io publish
pyproject.toml Root
wasm/package.json "version": "0.2.0"

Cargo.toml (root):

[package]
name = "ferro_ta"
version = "0.2.0"   # ← update here

pyproject.toml:

[project]
version = "0.2.0"   # ← 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 [0.2.0] — 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/v0.2.0...HEAD
[0.2.0]: https://github.com/pratikbhadane24/ferro-ta/compare/v0.1.0...v0.2.0

Follow the Keep a Changelog format: Added, Changed, Deprecated, Removed, Fixed, Security.


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 build-wheels and publish jobs 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: build-wheelspublish (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')"
  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