Skip to content

Releasing Zirium

Zirium publishes one Rust crate, one Python package and standalone CLI archives. The internal zirium-python crate is a build component and remains publish = false. The selected release is 0.7.0, with Zirql 0.3.0 as its shared-language dependency.

Keep the versions in crates/zirium/Cargo.toml, crates/zirium-python/Cargo.toml, pyproject.toml, Cargo.lock and uv.lock at 0.7.0. Update the changelog, installation commands and versioned API/source links together. Refresh the lockfiles without upgrading unrelated dependencies:

Terminal window
cargo check --workspace
uv lock

Use the existing Quality and Release workflows for validation and packaging. A successful build and publishing action are sufficient release assurance. The compatibility guide describes local checks for development or investigating a concrete failure; repeating fresh installations and archive audits is not a release gate.

Release’s manual candidate mode accepts a full 40-character commit ID:

Terminal window
candidate=$(git rev-parse HEAD)
gh workflow run release.yml --ref main -f mode=candidate -f source_ref="$candidate"

The workflow must already be on main. Candidate mode checks out that exact commit, checks package versions, runs Quality, and uploads the existing Python and two CLI target artifacts. It creates no tag or GitHub Release and disables all three publishing jobs. It skips Quality’s registry-package check because that check requires the dependency to be available on crates.io. A successful candidate run therefore does not establish registry resolution.

The final release resolves the verified Zirql 0.3.0 release from crates.io:

zirql = "=0.3.0"

The sdist contains both Rust crates, so the extension’s ../zirium path resolves inside the archive. Its stored manifests and root Cargo.lock must resolve Zirql from crates.io, with no Git dependency or sibling checkout. Installing the sdist needs Rust and access to the registry dependencies. The wheel contains the compiled extension and needs no Rust toolchain.

Refresh Cargo.lock without upgrading unrelated dependencies and commit the final source. The Release workflow builds the artifacts and checks registry resolution. For manual publication, successful CI and the normal publish command are sufficient; use no path or registry patches:

Terminal window
cargo publish -p zirium --locked

Publish Zirql before any Zirium release that requires its new version. Version, dependency and documentation changes do not reopen accepted code reviews or require repeating language tests.

Both registries trust GitHub owner zayenz, repository zirium, workflow release.yml, and their respective environment:

Registry GitHub environment
crates.io crates-io
PyPI pypi

Both environments require manual approval by zayenz. Publishing jobs receive short-lived credentials; no registry token needs to be stored in GitHub. CLI publication uses the workflow’s GitHub token and runs independently of these registry approvals.

Once publication is authorized, the final commit is on main and Zirql is available on crates.io, tag that commit and push only that tag:

Terminal window
git tag -a v0.7.0 -m "Zirium 0.7.0"
git push origin v0.7.0

Do not use git push --tags; local tags may not belong to the public release history. Release checks that the tag names a commit on main, matches all package versions and has a changelog entry. It runs Quality with actual registry package verification enabled.

Quality builds conventional CPython 3.11–3.14 wheels for Linux x86_64 (manylinux) and macOS arm64, plus the source distribution. PyPI receives these checked artifacts directly. There are no stable-ABI wheels. Open Review deployments, select the registry environments and approve their uploads. The internal extension crate is never published to crates.io.

After successful publication, report the version and links to the Rust API, crates.io package, PyPI package and GitHub release. Publish the docs through site/PUBLISHING.md. A successful deployment completes the docs release; further validation needs a concrete failure, known defect or explicit request.

Release builds the CLI with Rust 1.88.0 and the committed lockfile for x86_64-unknown-linux-musl and aarch64-apple-darwin. Linux uses Ubuntu 22.04 with musl tools and rejects dynamically linked executables. macOS uses macos-15 with MACOSX_DEPLOYMENT_TARGET=11.0. The platform baselines are Linux kernel 3.2 and macOS 11; CI runs on the listed runners, not the minimum OS versions.

Each archive contains zirium, LICENSE-MIT and LICENSE-APACHE under zirium-0.7.0-TARGET/, with a .tar.gz.sha256 sidecar. The build job extracts the archive outside the checkout, checks its version and runs a strict StableHLO query against the embedded registry. Candidate runs upload these archives as workflow artifacts only.

For publication, the publishing job verifies the downloaded checksums, uploads the archives to a draft GitHub Release, then publishes it. Only this job has contents: write. Trust the successful publishing job’s artifact checks.

The three channels publish independently. Retry only the failed channel after checking whether its upload succeeded. Do not move or replace a published tag. If the workflow needs a fix, commit it to main and run it against the existing tag:

Terminal window
gh workflow run release.yml --ref main -f mode=publish -f tag=v0.7.0 -f registry=pypi

Use registry=crates-io, registry=pypi or registry=binaries for one channel. registry=both selects crates.io and PyPI; registry=all selects all three and is the manual default. Tag pushes also select all three. Binary retries may replace assets in a draft release but refuse to replace a published release’s assets. Registry publishing retains the environment approvals.