Add release.yml guard for untracked workspace crates (catches forgotten cargo publish)
- Dominant language
- Rust
- Stars
- 0
- Forks
- 1
- Avg merge
- 11m
- Merged PRs (30d)
- 47
Description
## Context
The 0.5.1 coordinated release cycle (EPIC #124) forgot to publish `voxora-local` and `voxora-vad` (the two new crates added in EPIC #117 / 0.5.0). The mistake surfaced when downstream consumers tried to enable the new `local` Cargo feature on `voxora-bridge` and the lockfile resolver could not find `voxora-local@0.5.1` on crates.io.
## Why it matters
The release cycle depends on the operator remembering to publish every crate in the workspace. `.github/workflows/release.yml::publish-cratesio` already has an internal-deps guard (issue #94, hardened by #119) that fails fast if a participating crate depends on an un-released internal crate, but **that guard is in the wrong direction** — it catches the *consumer* missing a dependency, not the *producer* missing a publish.
## What
Add a guard to `.github/workflows/release.yml` that, before any `cargo publish`, verifies every workspace crate that participates in the current release has either:
1. Been published to crates.io at the version specified by the tag, OR
2. Has `publish = false` set in its manifest (which means it intentionally should not be on crates.io).
The guard reads the same `cargo metadata` output the internal-deps guard already uses, iterates every workspace member whose `publish == true`, queries `crates.io` for each (via the existing `check-cratesio-deps.py` helper or a new dedicated script), and short-circuits with an `::error` annotation listing the crates that need to be published before the workflow proceeds.
## Acceptance
- A release cycle that tries to release 8 of 9 `publish = true` workspace crates fails the guard with a clear message naming the 9th crate before any HTTP round-trip to crates.io.
- The guard is idempotent: re-running after the operator publishes the missing crate passes cleanly.
- `voxora-testkit` (the only current `publish = false` workspace crate) is **excluded** from the iteration.
- Guard failure produces an actionable error message: `workspace crate `voxora-local@0.5.10` is not on crates.io; run `cargo publish -p voxora-local --locked` first`.
## Out of scope
- Replacing the manual publish ordering with `release-plz` (issue #58).
- Catching semver mismatches between the tag and `Cargo.toml` (already covered by `validate-tag-input`).
- Auto-publish the missing crates (operator stays in control).
Contributor guide
Assessment
This issue has not been assessed yet.