Releasing a new version¶
This page is the canonical checklist for cutting a new QQA4CO release. Follow it top-to-bottom; never skip a step. Every previous release that went sideways skipped exactly one item on this list.
Versioning¶
QQA4CO follows SemVer (MAJOR.MINOR.PATCH).
Until 1.0 we will:
- bump PATCH for bug fixes and additive doc changes,
- bump MINOR for new public API,
- bump MAJOR only when removing or renaming a public symbol.
__version__ is single-sourced from pyproject.toml via
importlib.metadata.version("qqa"). Do not edit
src/qqa/__init__.py to bump versions — only pyproject.toml.
Pre-release checklist¶
- Working tree is clean — no uncommitted changes (
git status). - All CI passes locally:
CHANGELOG.mdhas an "Unreleased" section with every public change since the last tag. Move it under a new dated heading## [X.Y.Z] - YYYY-MM-DD.- Bump
versioninpyproject.tomlto the new value. - Update
CITATION.cff— bumpversion:anddate-released:so Zenodo and the GitHub citation widget pick it up. - Re-run the verification sweep if you touched any solver:
and commit the regenerated
docs/verification.md.
Cutting the release¶
# 1. One commit with the version bump + CHANGELOG move + CITATION bump.
git add pyproject.toml CHANGELOG.md CITATION.cff docs/verification.md
git commit -m "release: vX.Y.Z"
# 2. Push main and wait for CI, docs, and secret scanning to pass.
git push origin main
# 3. Build and validate the exact wheel and sdist locally.
uv build
uv run twine check dist/*
# 4. Publish a GitHub Release. This creates the tag and triggers publish.yml,
# which uploads to PyPI through Trusted Publishing.
gh release create vX.Y.Z --target main --title "vX.Y.Z" --notes-file release-notes.md
Post-release checklist¶
- Verify
pip install qqa==X.Y.Zworks from a fresh venv on another machine. - GitHub Release — confirm its
Publish to PyPIworkflow completed. - Zenodo — confirm the new DOI was minted (CITATION.cff is what triggers it).
- Docs — confirm the GitHub Pages workflow pushed the new
mkdocs buildto https://yuma-ichikawa.github.io/QQA4CO/. - Streamlit Cloud — update deployment dependencies if needed and follow the Streamlit deployment runbook.
- Open a
CHANGELOG.md"Unreleased" stub for the next cycle.
Trusted Publishing (recommended once configured)¶
Once Trusted Publishing is set up on PyPI for the qqa project, publishing
the vX.Y.Z GitHub Release triggers a GitHub Actions workflow that builds and
uploads the wheel + sdist with no API token in the repo.
Track the workflow run from the GitHub Actions tab.
If the workflow fails:
.github/workflows/publish.ymllogs always show the exact failure step.dist/build failures usually mean a staledist/directory shipped in the wheel — purge it locally and re-tag.- Trusted Publishing rejection means the PyPI configuration drifted — re-configure under "Publishing" on the PyPI project page.
Rolling back a bad release¶
PyPI does not allow re-uploading the same version. If you ship a broken wheel:
- Yank it on PyPI:
uv run twine yank qqa --version X.Y.Z(do not delete — yanking letspip install qqa==X.Y.Zkeep working for pinned users while preventing fresh installs). - Bump to
X.Y.(Z+1)with the fix and follow the full release checklist again. - Document the yanked version in
CHANGELOG.mdso users searching the changelog understand why a version is "missing".
Never amend a tag that has been pushed; create a new one.