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. Tag and push.
git tag -a vX.Y.Z -m "vX.Y.Z"
git push origin main vX.Y.Z
# 3. Build the wheel and sdist.
rm -rf dist/
uv build
# 4. Upload to PyPI (Trusted Publishing via the GitHub Actions release
# workflow is the preferred path — see below). For a manual upload:
uv run twine upload dist/*
Post-release checklist¶
- Verify
pip install qqa==X.Y.Zworks from a fresh venv on another machine. - GitHub Release — create one against the new tag, paste the
matching
CHANGELOG.mdsection as the body. - 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 — bump the pinned
qqaversion in the deploy'srequirements.txtif needed (seedeploy/STREAMLIT_DEPLOY.md). - 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, a
push of the vX.Y.Z tag should trigger 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:
workflows/release.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.