Releases

An exact semantic-version tag triggers the release workflow. The tag version must match all four workspace distributions.

A release candidate must pass:

The repository uses tag-restricted GitHub environments and one PyPI pending Trusted Publisher for each workspace distribution. Every publisher is bound to alchemmist/quality-graph and .github/workflows/release.yml. The environments are pypi for quality-graph-core, pypi-python for quality-graph-python, pypi-github for quality-graph-github, and pypi-cli for quality-graph-cli.

Run make release-setup once to configure those environments and the initial pending publishers through the GitHub and PyPI interfaces. The setup uses no API token or repository secret.

PyPI allows at most three pending publishers per account and rejects duplicate pending OIDC identities. For the first release, register quality-graph-core, quality-graph-python, and quality-graph-github with their distinct environments before creating the tag. The first tag run publishes those projects while the CLI remains failed and the GitHub Release remains blocked. Register quality-graph-cli with pypi-cli after the three pending records convert to ordinary publishers. The next patch release publishes all four projects and creates the GitHub Release from all eight distribution files. Later releases complete in one pass.

The release workflow builds and verifies distributions in an unprivileged job. Four isolated publication jobs receive only id-token: write, and PyPI creates attestations through Trusted Publishing. A final job creates the GitHub Release from the exact uploaded files. No long-lived PyPI token is used.

Release procedure:

  1. confirm all four Trusted Publishers and their four named environments are configured;
  2. update local main so it exactly matches origin/main with a clean working tree;
  3. run make release-patch, make release-minor, or make release-major;
  4. wait for all PyPI publication jobs and the GitHub Release job;
  5. install the exact versions from PyPI in a clean environment and validate the Action from a separate repository.

The release targets update all four workspace versions and uv.lock, run the complete local quality gate, create one release vX.Y.Z commit and annotated tag, then atomically push main and the tag. They stop before commit, tag, or push if the tree is dirty, local main differs from origin/main, workspace versions disagree, the tag exists, or any check fails.

Do not create a moving Action tag. Consumers pin the release commit SHA.

v0.1.8