Skip to content

Releasing

Clifft uses setuptools-scm to derive the package version from git tags. The release workflow builds wheels for Linux (x86_64, aarch64), macOS (arm64), and Windows (amd64), then publishes to PyPI via trusted publishers.

Versioning

The version is determined automatically from git tags:

  • Tagged commits (e.g., v0.2.0): version is 0.2.0
  • Development builds: version is 0.2.1.dev3+g1a2b3c4 (tag + commit distance + hash)

There is no hardcoded version in pyproject.toml. The git tag is the single source of truth.

Release process

Verify that wheels build and install correctly by running the release workflow manually. Manual dispatch always publishes to TestPyPI only — it cannot publish to PyPI.

  1. Go to Actions > Release > Run workflow
  2. Select the branch (usually main)
  3. Wait for builds to complete, then verify:

    pip install --index-url https://test.pypi.org/simple/ \
        --extra-index-url https://pypi.org/simple/ clifft
    python -c "import clifft; print(clifft.__version__)"
    

2. Update the changelog

Generate the new release section using git-cliff:

git cliff --unreleased --tag v0.2.0 --prepend CHANGELOG.md

This prepends only the unreleased changes since the previous tag and preserves older hand-edited release sections. Do not use -o CHANGELOG.md for routine releases unless you intentionally want to regenerate the entire changelog.

Review, edit if needed (add the release summary, fix typos, clarify entries, remove noise), then commit:

git add CHANGELOG.md
git commit -m "docs: update changelog for v0.2.0"

3. Update the docs home page

Update the "What's New" section in docs/index.md with a short, editorial summary of the release. Keep this section user-facing and curated rather than generated directly from the changelog. Link to the most relevant new documentation or tutorial, and include a link to the full changelog.

4. Tag and push

git tag v0.2.0
git push origin main v0.2.0

5. CI runs automatically

The tag push triggers the release workflow:

  1. Build — sdist and wheels for all platforms
  2. Publish to TestPyPI — dry run on the test index
  3. Publish to PyPI — the real release (only on tag push)
  4. Create GitHub Release — extracts release notes from CHANGELOG.md
  5. Publish versioned docs — updates the exact version, stable, and the root stable Playground

If any step fails, subsequent steps are skipped.

6. Verify

pip install clifft==0.2.0
python -c "import clifft; print(clifft.__version__)"

Check that the GitHub Release was created.

Then verify the hosted docs and Playground:

  • https://unitaryfoundation.github.io/clifft/<version>/ exists.
  • For the newest release, https://unitaryfoundation.github.io/clifft/stable/ shows the new release docs.
  • https://unitaryfoundation.github.io/clifft/playground/?url=<raw-stim-url> still loads a remote circuit.

Documentation versions

Documentation is versioned separately from package builds. Pushes to main publish unreleased documentation to https://unitaryfoundation.github.io/clifft/dev/. Tagged releases publish the exact release version, update the stable docs copy, and refresh the root stable Playground at https://unitaryfoundation.github.io/clifft/playground/. If a lower SemVer patch line is released after a newer stable version, the workflow publishes the exact version docs but leaves stable and the root Playground unchanged.

Each docs version includes its own Playground build, so examples and docs match the selected Clifft version. The root /playground/ path is a stable compatibility URL for externally shared links. Dev Playground links are unreleased and should not be used as permanent public links.

Changelog maintenance

The changelog is generated from conventional commit messages using git-cliff with the config in cliff.toml.

Use conventional commit prefixes: feat:, fix:, docs:, perf:, refactor:, test:, build:, ci:. Commits with chore: and style: are excluded from the changelog.

Install git-cliff locally:

# macOS
brew install git-cliff

# Or via cargo
cargo install git-cliff

Prerequisites (one-time setup)

These steps are needed once when setting up the repository:

  1. PyPI trusted publisher: On pypi.org, configure a trusted publisher for clifft (owner: unitaryfoundation, repo: clifft, workflow: release.yml, environment: pypi).

  2. TestPyPI trusted publisher: Same on test.pypi.org with environment testpypi.

  3. GitHub environments: Create two environments in repo settings:

    • pypi — optionally add required reviewers for production releases
    • testpypi — no restrictions needed
  4. Initial version tag: After migrating to the new repo, push the first tag to establish the version baseline:

    git tag v0.1.0
    git push origin v0.1.0