Releasing (Maintainer Runbook)
This document is the runbook for project maintainers. Adopters do not need to read this.
Four distribution paths ship together: crates.io, prebuilt binaries, npm, and PyPI.
Pre-flight
- Ensure the working tree is clean and tests pass (
cargo test --workspace --locked). - Verify self-governance (
spec-spine compile && spec-spine index check && spec-spine lint --fail-on-warn && spec-spine couple --base origin/main --head HEAD). - Bump versions consistently using
scripts/bump_version.py <version>. - Ensure
cargo package --workspace --lockedsucceeds.
1. crates.io: Publish in dependency order
Crates must be published leaf-first:
cargo publish -p spec-spine-types
cargo publish -p spec-spine-core
cargo publish -p spec-spine-cli
Wait for the index to update between publishes.
2. Prebuilt binaries: Push a tag
The release workflow is tag-gated.
git tag vX.Y.Z
git push origin vX.Y.Z
This builds per-triple archives (with .sha256 sidecars) for five supported targets and attaches them to the GitHub Release. It also generates a CycloneDX SBOM and a SLSA build-provenance attestation.
3. npm: The binary-distribution shim
The same v* tag drives the publish-npm job. It does not rebuild Rust; it repackages the archives as npm packages.
- A main package
spec-spinewith a tiny launcher. - Five platform packages
@spec-spine/cli-<os>-<cpu>listed asoptionalDependencies.
The job requires the NPM_TOKEN secret.
4. PyPI: The wheel shim
The publish-pypi job repackages the archives as five platform wheels and one sdist under the spec-spine project.
The job requires the repository variable PYPI_TRUSTED_PUBLISHING=true and uses OIDC Trusted Publishing.
5. Determinism Gate
The .github/workflows/determinism.yml workflow proves that the emitted registry + index shard trees are byte-identical across four triples (it folds every shard's path and content into one tree digest). Keep this gate green; a span drift on any platform fails it.