ADR-024: CI and the Release Workflow
Status
Accepted
Supersedes ADR-010.
Context
Every change must be linted, tested and buildable before it is released, and a release must reach PyPI the moment it is tagged. When publishing was a separate step, done by hand from one person’s machine, the SDK’s GitHub releases ran several versions ahead of PyPI.
Decision
CI/CD uses GitHub Actions, in two workflows, and every make target has a CI counterpart.
ci.ymlruns on every push tomain,alphaandbeta, and on every pull request: the pre-commit hooks, the unit tests with coverage on every supported Python version (ADR-019), the Sphinx build with warnings as errors, a check of the docs site’s Terraform, and then a build of the sdist and wheel, checked withtwine check --strict. Coverage, with branches, is uploaded to Codecov, which checks 95% of the project and of each patch, and CI fails below 95%.release.ymlis started by hand, and releases and publishes in one run: the whole ofci.yml, semantic-release (ADR-015), a build from the new tag that must hold exactly that version, the distributions attached to the GitHub release, a rehearsal upload to TestPyPI that is installed back and checked, and then PyPI, frommainonly, also installed back and checked. Prereleases fromalphaandbetastop at TestPyPI.Uploads use trusted publishing (OIDC), with no stored PyPI token, and are switched on by the repository variables
PUBLISH_TO_TESTPYPIandPUBLISH_TO_PYPI.
Alternatives Considered
Release on every push to
main, which releases every merged fix before they can be reviewed together.Publish to PyPI by hand after the release, which lets a tagged release never reach PyPI.
Publish with a PyPI api token stored as a secret, which can leak and must be rotated.
Consequences
Positive:
A tagged release is on PyPI, or the run that tagged it failed visibly.
The same workflows as the other Smarter Project packages.
Negative:
Releases need someone to start them.
Each package index needs
release.ymlregistered as a trusted publisher.