Release Process¶
This document outlines the canonical checklist for releasing new versions of Assay.
Checklist¶
1. Preparation¶
- Bump Versions: Update
versioninCargo.tomlfor all crates. - Root
Cargo.toml(workspace members inheritance) crates/assay-common/Cargo.toml(if not inherited)assay-python-sdk/Cargo.toml- Update Lockfile: Run
cargo check --workspaceto updateCargo.lock. - Changelog: Update
CHANGELOG.mdwith new features and fixes. - Lints: Run
cargo clippy --workspace --all-targetsto ensure no new warnings. - Release parser toolchain: Use Ruby
3.3.12with Psych5.1.2. GitHub Actions installs the pinned Ruby before running the release-channel contract; the local version-line preflight fails closed on another parser toolchain so YAML key semantics cannot drift between operator and CI. - Version-line preflight: Bind the workspace to the intended stable tag before it exists: This is the workspace-only pre-tag check. On the host that owns the runner VM, repeat it with
CHECK_VM=1to prove the VM still matches GitHub Latest while the workspace matches the intended release target. The Harness default is an independently proven compatibility pin and may intentionally lag the latest Assay release. The VM remains bound to the current GitHub Latest release until the new tag is published.
2. Permissions Check (Crucial)¶
- Trusted Publishing: Ensure GitHub Actions OIDC is enabled for the release tag on every current crates.io crate:
assay-commonassay-registryassay-canonicalassay-evidenceassay-coreassay-metricsassay-policyassay-mcp-serverassay-monitorassay-runner-schemaassay-runner-linuxassay-runner-coreassay-simassay-cli- Non-crates.io workspace members: Confirm these remain
publish = falseunless a dedicated distribution freeze changes the contract: assay-adapter-api(historical crates.io versions exist, but the current release line does not publish it)assay-adapter-acpassay-adapter-a2aassay-adapter-ucpassay-it(distributed through PyPI wheels, not crates.io)assay-ebpfassay-xtaskgateway-evidence-replay- Public Crate Policy Check: Run
bash scripts/ci/check-public-crate-policy.sh. - Public MSRV Check: Run
ASSAY_PUBLIC_MSRV=1.89.0 scripts/ci/check-msrv-policy.sh. - Token Scopes: If using a token fallback, ensure it has
publish-updatescope.
3. Execution¶
- Tag: Create and push the git tag.
- Watch CI: Monitor the
release.ymlworkflow. - Step:
Publish to Crates.io(usesscripts/ci/publish_idempotent.sh). - Step:
Create GitHub Release(upload binaries and release assets). - Step:
Build assay-mcp-server MCPB(producesrelease/assay-mcp-server-${VERSION}-linux.mcpbplus.sha256). - Step:
Render generated registry metadata(producesrelease/server.jsonfor later MCP registry submission). - Step:
Generate CycloneDX SBOM bundle(producesrelease/assay-${VERSION}-sbom-cyclonedx.tar.gzplus.sha256). - Step:
Enforce release attestation policy(producesrelease/assay-${VERSION}-release-provenance.jsonplus.sha256and uploads raw attestation verification evidence as a workflow artifact). - Step:
Build release proof kit(producesrelease/assay-${VERSION}-release-proof-kit.tar.gzplus.sha256). - Step:
Check release asset preflight(fails before publication unless therelease/directory exactly matches the expected asset contract, every.sha256verifies, andserver.jsonpoints at the generated MCPB checksum). - Step:
Create GitHub Release(uploads only the preflighted files fromrelease/).
4. Verification¶
- Published MSRV Install Check: use a fresh install root so Cargo cannot reuse an existing installation, then execute the resulting binary: This exercises the lockfile shipped with the published CLI rather than the workspace lock.
- LSM Smoke Test: Manually dispatch the
lsm-smoke-testworkflow or runscripts/verify_lsm_docker.sh --release-tag vX.Y.Z. - SBOM Asset Check: Confirm the GitHub release includes
assay-${VERSION}-sbom-cyclonedx.tar.gzandassay-${VERSION}-sbom-cyclonedx.tar.gz.sha256. - MCPB Asset Check: Confirm the GitHub release includes
assay-mcp-server-${VERSION}-linux.mcpbandassay-mcp-server-${VERSION}-linux.mcpb.sha256. - Registry Metadata Check: Confirm the GitHub release includes
server.jsongenerated from the MCPB asset and matching SHA-256. - Provenance Asset Check: Confirm the GitHub release includes
assay-${VERSION}-release-provenance.jsonandassay-${VERSION}-release-provenance.json.sha256. - Proof Kit Asset Check: Confirm the GitHub release includes
assay-${VERSION}-release-proof-kit.tar.gzandassay-${VERSION}-release-proof-kit.tar.gz.sha256. - Release Asset Preflight Check: Confirm
Check release asset preflightpassed beforeCreate GitHub Release; this is the machine-readable asset contract for GitHub release publication. - Workflow Evidence Check: Confirm the workflow artifacts include
release-provenance-evidencewith the rawgh attestation verify --format jsonresults for each release archive. - Offline Verification Check: Unpack the proof kit and run
verify-offline.sh --assets-dir /path/to/release-assetsagainst the downloaded release archives. See Release Proof Kit. - Operator Flow Check: For the compact end-to-end story that connects transcript ingest, shipped
C2pack evaluation, and proof-kit verification, see Operator Proof Flow. - Registry Publication Decision: Treat
release/server.jsonas publish-ready input, not proof of an existing live official registry listing.
Troubleshooting¶
HTTP 403 Forbidden¶
- Cause: Missing ownership or Trusted Publishing not configured for a specific crate.
- Fix: Go to crates.io settings for the failing crate and add the GitHub repository as a Trusted Publisher.
Token not valid for crate¶
- Cause: A crate in the current public release contract is missing a Trusted Publishing grant.
- Fix: Configure crates.io Trusted Publishing for that crate. The release intentionally fails instead of silently skipping a public crate and creating release drift.
"Crate already uploaded"¶
- Cause: Partial failure in a previous run.
- Fix:
publish_idempotent.shhandles this automatically. Re-running the job is safe.