Releasing Fiducio
Releases are manual and gated. No workflow uploads to PyPI on its own.
What the workflows enforce
validate.yml(reusable) builds one wheel/sdist pair and runs the checks, using those archives wherever a package is installed:- Twine and a content check (
scripts/check_distribution.py): license,py.typed, identical sources in the wheel and sdist, the project page shipped in the sdist and absent from the wheel; - ruff on Python 3.11 and mypy on Python 3.10–3.14;
- the full test suite and the examples against the installed wheel, on Python 3.10–3.14 with the locked PyTorch (Linux, plus macOS and Windows on 3.12), plus one run with the minimum supported PyTorch 2.10;
mkdocs build --strictfrom the checkout and from the unpacked sdist, the project-page check (scripts/check_site.py), and a wheel rebuilt from the sdist that must match the tested wheel;- the benchmark harness tests on Python 3.12 with every competitor installed.
- Twine and a content check (
tests.ymlruns it on pull requests and onmain;package.ymlreruns it manually.publish-pypi.yml(manual, withconfirm: publish) first runsscripts/check_release.py. It fails unless the run was started from avX.Y.Ztag equal toproject.versionand the tagged commit is onmain. It then runs the validation and uploads the validated artifacts with Trusted Publishing and attestations, once thepypienvironment has been approved.- The OIDC
id-token: writepermission is granted only to the PyPI publish job and the Pages deploy job. Third-party actions are pinned by commit SHA.
Procedure
- Merge the release PR once
Testsis green. UpdateCHANGELOG.md, the version inpyproject.toml,CITATION.cffanduv.lock(uv lock) in that PR. CI derives the expected version frompyproject.toml. - From an up-to-date
main, create and push an annotated tag:git tag -a vX.Y.Z -m "Fiducio X.Y.Z" && git push origin vX.Y.Z. - Actions → Publish to PyPI (manual) → Run workflow. Pick the tag as the
ref and type
publish. Approve thepypienvironment when validation has passed. - Download the published files from PyPI. Check their SHA-256 against the
workflow artifact and verify the attestations (
pypi-attestations verify pypior the PyPI UI). - In a fresh environment:
pip install fiducio==X.Y.Z, then fit, transform, save and reload a calibrator. - Publish the GitHub release for the tag with the changelog entry.
Rollback
- Failure before the upload: stop. Nothing has been published. Fix, then retag only if the tag was never used for an upload.
- After an upload: never replace or delete published archives. Release a new patch version, and if needed yank the broken version on PyPI.
- Pages: revert only the offending commit on
main. The docs workflow redeploys the previous site, and the existing documentation is preserved.
Repository settings (not encoded in the repository)
These settings are applied by a maintainer in the GitHub UI.
| Setting | Before (2026-09-21) | After |
|---|---|---|
main protection |
none (no branch protection, no rulesets) | ruleset on main: block deletion and force-push, require a pull request, require the status check Tests / validation / Release checks |
| Tag protection | none | ruleset on refs/tags/v*: block deletion, update and non-fast-forward. Creation is limited to maintainers |
pypi environment |
required reviewers, no deployment-ref policy | keep required reviewers; deployment policy restricted to tags matching v*.*.* |
github-pages environment |
custom branch policy | unchanged (main) |
| Private vulnerability reporting | disabled | enabled (needed by SECURITY.md) |
| Immutable releases | disabled | enabled for new releases; existing v0.1.0 is not modified |
| PyPI Trusted Publisher | configured for publish-pypi.yml, environment pypi |
unchanged; check the workflow filename and environment still match |