Releasing#
A QUARTIC2D release has one source artifact, the annotated Git tag, and three publication surfaces: PyPI, a GitHub Release, and a Zenodo software archive. The release automation publishes them in that order so an archived GitHub release is not created before the Python distributions have passed validation and reached PyPI.
1. Prepare the release commit#
Update
src/quartic2d/_version.pyCITATION.cffthe matching version heading in
CHANGELOG.md
For a release commit, CHANGELOG.md must use a date in YYYY-MM-DD form and CITATION.cff must contain the same date-released value.
Check the metadata before tagging:
python tools/check_release_metadata.py
For the current unreleased 0.1.0 state, the checker prints
package version : 0.1.0
citation version: 0.1.0
changelog state : Unreleased
release metadata: consistent
Install the maintainer dependencies:
python -m pip install -e ".[test,docs,dev,release,ogata]"
2. Run the local release checks#
python -m pytest
python -m ruff check src tests examples benchmarks docs/scripts tools
python -m benchmarks.gaussian_validation --quick
python docs/scripts/generate_figures.py examples
python docs/scripts/generate_example_artifacts.py
python docs/scripts/check_artifacts.py
python -m sphinx -W --keep-going -b html docs/source docs/_build/html
python docs/scripts/check_rendered_docs.py docs/_build/html
A clean source state gives the following stable end conditions:
pytest: all tests passed
ruff: no diagnostics
gaussian validation: PASS
documentation artifact manifest: PASS
Sphinx: build succeeded.
Run the executable examples:
MPLBACKEND=Agg bash -c '
for example in examples/*.py; do
echo "==> $example"
python "$example"
done
'
If publication benchmark evidence accompanies the release, run it from the exact release commit:
python -m benchmarks.run_suite publication 2>&1 | \
tee ~/Downloads/quartic2d_publication_run.log
The log path is deliberately outside the repository. Benchmark provenance samples the Git working tree during execution, so a tracked output log would make the run dirty even when no computational input changed.
A successful run ends with
BENCHMARK SUITE COMPLETE
Status : PASS
Results : <repository>/benchmarks/results
Check the generated manifest before archiving the benchmark dataset. The commit must match the release commit and the recorded source state must be clean.
3. Build and inspect the distributions#
rm -rf build dist src/*.egg-info
python -m build
python -m twine check dist/*
The final lines should report successful wheel/sdist creation followed by PASSED from twine check for both distributions.
Inspect the archives:
python -m zipfile -l dist/*.whl
tar -tf dist/*.tar.gz
Both commands print archive member lists. Confirm that quartic2d/, package metadata, license, README, examples, documentation sources, tests, and benchmark sources are present according to MANIFEST.in, while generated result/build directories are absent.
The source distribution includes the package metadata, license, documentation sources, examples, tests, benchmark sources, and maintainer/release documentation. Generated benchmark results, documentation builds, caches, and local environments are excluded.
4. Test the wheel outside the checkout#
An editable installation can hide packaging mistakes. Test the built wheel in a fresh environment:
python -m venv /tmp/quartic2d-release-check
source /tmp/quartic2d-release-check/bin/activate
python -m pip install --upgrade pip
python -m pip install dist/*.whl
cd /tmp
python - <<'PY'
import quartic2d
print(quartic2d.__version__)
print(quartic2d.__all__)
PY
deactivate
For version 0.1.0 the import block prints
0.1.0
['HankelTransform', 'HarmonicConvergenceResult', 'HarmonicTransform', 'Interaction', 'InteractionConvergenceResult', '__version__']
5. Enable GitHub Pages#
Before the first public release, enable GitHub Pages for the repository from
Settings → Pages → Build and deployment → Source → GitHub Actions. The
Documentation workflow builds and validates the Sphinx site on every push to
main and deploys that verified artifact through the github-pages
environment.
actions/configure-pages cannot enable Pages with the default GITHUB_TOKEN,
so this repository setting must be enabled once by a maintainer. After enabling
it, rerun the Documentation workflow and require both its build and deployment
jobs to pass before tagging a release.
6. Configure PyPI Trusted Publishing#
The release workflow uses the GitHub environment pypi and OIDC Trusted Publishing. Configure the PyPI project or pending publisher with
owner:
QuantumArtificerrepository:
quartic2dworkflow:
release.ymlenvironment:
pypi
No long-lived PyPI token is stored in the repository.
Official guidance: Publishing package distribution releases and PyPI Trusted Publishing.
7. Enable Zenodo before the first tag#
Connect the GitHub account to Zenodo, synchronize repositories, and enable QuantumArtificer/quartic2d before publishing the first release tag.
QUARTIC2D uses CITATION.cff as the release metadata source. Add .zenodo.json only if Zenodo-specific metadata are needed. When .zenodo.json is present, Zenodo uses it instead of CITATION.cff for GitHub-release metadata.
Zenodo guidance: GitHub integration and software metadata.
8. Create and push the release tag#
Commit the fully checked release state, then create an annotated tag:
git status --short
python tools/check_release_metadata.py --tag v0.1.0
git tag -a v0.1.0 -m "QUARTIC2D v0.1.0"
git push origin main
git push origin v0.1.0
For a clean tree, git status --short prints nothing. check_release_metadata.py --tag ... must end with release metadata: consistent before the tag is created.
The tag push starts .github/workflows/release.yml.
The workflow performs the following sequence:
checks the tag, package version,
CITATION.cff, release date, and changelogruns tests, Ruff, analytic validation, documentation, and executable examples
builds the wheel and source distribution once and checks their metadata
installs the built wheel and imports it outside the repository checkout
publishes the verified distributions to PyPI through Trusted Publishing
creates the GitHub Release from the same tag and attaches the distributions plus
SHA256SUMSallows the enabled Zenodo GitHub integration to archive that GitHub Release
A failure before step 5 leaves no PyPI or GitHub release. A PyPI failure prevents creation of the GitHub Release and therefore prevents the Zenodo archive from being triggered by this release path.
9. Verify the published release#
After the workflow succeeds:
install
quartic2d==X.Y.Zfrom PyPI in a clean environmentconfirm the GitHub Release contains the wheel, source distribution, and
SHA256SUMSconfirm the GitHub Release points to the intended annotated tag
confirm the Zenodo record contains the correct title, author, version, license, and repository link
record the version DOI after Zenodo creates it
The DOI does not exist before the first archive is created. Add it to the next source commit and to subsequent citation metadata. Do not rewrite the already published tag solely to insert an identifier that did not exist when that source state was created.
The release lint gate uses the repository-local Ruff policy in pyproject.toml through the dev extra. User-level Ruff configuration is not part of the release contract.