Releasing

August 11, 2026 · View on GitHub

This repository publishes one crate: blip25-vocoder. Everything else in the tree is development scaffolding that never leaves it.

Publishing is irreversible. A version can be yanked but never deleted, and a crate name can never be reclaimed. This crate ships a patent-encumbered, reverse-engineered codec — re-read PATENT_NOTICE.md and ATTRIBUTION.md before any upload under a new crate name.

One-time setup

  1. A crates.io API token in repo secrets as CARGO_REGISTRY_TOKEN (Settings → Secrets and variables → Actions).
  2. Publishing a crate name for the first time needs a token with the publish-new scope. Afterwards publish-update is enough.

What ships

The include list in Cargo.toml is an allowlist, so the published .crate is much smaller than the repository. It ships src/**/*.rs, Cargo.toml, LICENSE, README.md, the three README-documented examples (vocoder_demo, vocoder_bench, foreign_protocol), the self-contained tests (no_panic_garbage, roundtrip, stream_soak), and golden_corpus.rs together with its golden_corpus.bin fixture.

It does not ship:

  • tests/dvsi_gold.rs / tests/dvsi_gold.bin and tests/engine_golden.bin — fixtures captured from the reference vocoder, which are not ours to redistribute.
  • the rest of examples/ — instrumentation that hard-codes local paths to the non-redistributable reference vector corpus and cannot run for anyone else.
  • conformance/roundtrip and conformance/no-std-guard, both publish = false.
  • fuzz/ and wasm/, which are outside the workspace.
  • every Markdown file except README.md. A crates.io or docs.rs reader sees the patent posture only through the notice at the top of the README, which links back to PATENT_NOTICE.md in the repository. If that notice changes, the README must change with it or the packaged crate understates the constraint.

Release steps

  1. Pick the version. Semver: patch and minor bumps must be backward compatible, and only a major bump may break the public API. The semver CI job checks this against the last published release and fails if the bump is too small.

  2. Bump it in two places in the root Cargo.toml — they must match:

    • [package] version
    • [workspace.package] version

    The blip25-vocoder entry under [workspace.dependencies] carries the same version and is how the conformance/ members resolve the crate by path; bump it too, or those members stop building.

  3. Update CHANGELOG.md: move [Unreleased] content into a new ## [X.Y.Z] - YYYY-MM-DD section and add the compare link at the bottom. If the release changes codec output, provenance, or the legal posture, say so at the top of the section — that is what an existing user needs first.

  4. Verify locally (all of these run in CI, but the publish is one-way):

    cargo test --workspace --release
    cargo test --all-features --release
    RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
    cargo deny check advisories bans licenses sources
    cargo +1.85 build --all-features            # declared MSRV
    python3 .github/scripts/check_publishable.py
    cargo package                               # full verify build
    

    cargo package is the one that matters most: it assembles the .crate from the include list, unpacks it into target/package/, and builds it there with nothing else from the repository present. A file the code needs but include omits fails here rather than after upload.

    check_publishable.py covers what a verify build cannot: it uses cargo metadata and cargo package --list, neither of which touches the registry, to confirm the workspace publishes exactly this one crate, that every path dependency declares a version, that every compile-time include_bytes!/include_str! target of a packaged source file is itself packaged, and that LICENSE and README.md ship.

  5. Commit to main, wait for CI green.

  6. Tag and push:

    git tag -a vX.Y.Z -m "…"
    git push origin vX.Y.Z
    

    .github/workflows/publish.yml fires on v*, re-verifies that the tag matches the crate version, runs the tests, then publishes.

  7. Confirm the upload. Check that docs.rs built the release — it builds with all-features = true per [package.metadata.docs.rs], so a feature-gated doc error can fail there after a clean publish. Fixing it needs a new patch version; the uploaded one cannot be replaced.

If a publish fails

A failed cargo publish leaves nothing on the registry, so the version number is still free: fix the problem, delete and re-push the tag (git push --delete origin vX.Y.Z), and let the workflow run again.

Once the upload succeeds the version is immutable. Any correction is a new version, and the bad one gets yanked rather than replaced.