A workflow_dispatch publish.yaml (mirrors release-macos.yaml) with a `tag` input, run by hand once the automated release builds exist. Publishing stays manual and keeps the registry token off every tag push: it's irreversible (yank-only), the split release (tag Linux/Windows + dispatched macOS) makes a human the 'all assets up' gate, and crates.io has no Gitea-Actions trusted-publishing path. The crates.io job is idempotent (crates.io API pre-check + cargo publish as backstop) and independent (no inter-job needs), so future Scoop/Homebrew/winget jobs can be added alongside without interfering or breaking re-runs. Token via the CARGO_REGISTRY_TOKEN secret. ADR-0056 Amendment 1 + README index also record 0.2.0 published + binstall verified.
5.7 KiB
ADR-0056: crates.io publish-readiness + cargo binstall metadata (D3)
Status
Accepted — prepared 2026-06-17 (plan:
docs/plans/20260616-public-availability.md, step 3a). The crate is made
ready to publish and carries cargo-binstall metadata. The actual
cargo publish is a gated maintainer step (see Ordering). First D3
package-manager mechanism; builds on ADR-0054 (versioned releases),
ADR-0055 (installer), ADR-ci-003 (release assets). Tracked by plan + ADR
(no Gitea issue — user decision).
Context
cargo binstall rdbms-playground (and cargo install) need the crate on
crates.io (user decision, 2026-06-17). The manifest had
publish = false, a readme = "README.md" pointing at a missing
file, and no keywords/categories. Our release assets are bare
binaries (not archives) named rdbms-playground-v<version>-<target>
(.exe on Windows) with .sha256 sidecars (ADR-ci-003); critically the
release target triples differ from users' host triples — we ship the
static *-linux-musl build (hosts are *-linux-gnu) and
*-windows-gnu/-gnullvm (hosts are *-msvc); only macOS matches.
Decision
Publish-readiness (this change):
- Drop
publish = false; addhomepage = "https://relplay.org",keywords,categories = ["command-line-utilities", "database"], and anexclude(/website,/docs,/.gitea,/.codegraph) so the published crate is code-only (585 files/8.3 MiB → 353/913 KiB compressed). - Author
README.md(thereadmetarget + crates.io front page; engine-neutral and "simple/advanced mode" wording per ADR-0002 / the website copy rules), with install instructions (curl|sh, binstall, source, prebuilt). - Add
LICENSE-MITandLICENSE-APACHE(the latter the verbatim canonical text, added by the maintainer; both © Lazy Evaluation Ltd — the publication entity), and aCONTRIBUTING.mdstating the "inbound = outbound" dual-license arrangement (so Apache-2.0 §5 makes the §3 patent grant explicit on the self-hosted forge). Dual license kept (not MIT-only) — user decision after reviewing the patent-grant rationale.
cargo binstall metadata ([package.metadata.binstall], syntax
verified against cargo-binstall SUPPORT.md):
pkg-fmt = "bin"(bare binary),bin-dir = "{ bin }{ binary-ext }", and a basepkg-urlusingv{ version }(the{ version }placeholder excludes the leadingv).- Per-target
overridesmapping the common host triples to the asset we actually publish:x86_64/aarch64-unknown-linux-gnu→ the-muslasset;x86_64/aarch64-pc-windows-msvc→ the-gnu/-gnullvm.exe. macOS needs no override (host triple == asset triple). The docs do not promise automatic musl/gnu or msvc/gnu fallback, hence explicit overrides.
Ordering / gating (important):
cargo publishis irreversible (needs the crates.io token; a version can't be un-published, only yanked) — a deliberate maintainer step, not done here.- binstall's
pkg-urlresolves to a tagged release's assets, so publish at a new tagged version whose release already exists, and publish after that release is built. Do not publish0.1.0— it would diverge from the already-released0.1.0binaries (which predate--version, ADR-0054). The clean path: bump → tag → release builds →cargo publish.
Verification
cargo publish --dry-run --allow-dirtypackages + verify-builds cleanly (353 files, 913 KiB compressed; no metadata errors).cargo metadataconfirms thebinstallblock + all fouroverridesparse.- Unverified: an actual
cargo binstallrun — cargo-binstall isn't a dependency and nothing is on crates.io yet. Validate at the first publish + matching release (especially the windows-msvc→gnu and linux-gnu→musl overrides).
Consequences
- The crate can be published at the next tagged release with
cargo publish(+ the token);cargo install rdbms-playgroundandcargo binstall rdbms-playgroundthen work. - Remaining D3: Scoop, Homebrew (
lazyevaltap), winget (komac/manual) — each a manifest + a per-release bump, tracked in the plan. - Remaining follow-up: run the real
cargo binstallvalidation at the first publish + matching release (the license files, © holder, and CONTRIBUTING are now in place).
Amendment 1 — 2026-06-18: published live + a manual publish workflow
rdbms-playground 0.2.0 is published to crates.io (cargo install and
cargo binstall rdbms-playground both verified working by the user). The
"unverified binstall" caveat is resolved — the per-target overrides
resolve correctly against the v0.2.0 release assets.
How publishing is wired: a new manual workflow_dispatch workflow
(.gitea/workflows/publish.yaml), mirroring release-macos.yaml, takes a
tag input and runs cargo publish (token via the
CARGO_REGISTRY_TOKEN Gitea Actions secret — a crate-scoped,
publish-update token). Not automated on the tag, by decision: the
publish is irreversible (yank-only), keeping the registry token off every
tag push; the release is split (Linux/Windows on the tag, macOS
dispatched), so a human is the natural "all assets are up — go" gate; and
crates.io has no Gitea-Actions trusted-publishing path today, so a stored
token on the self-hosted runner would be the only automated option.
Each registry is its own idempotent job (no inter-job needs) — the
crates.io job skips cleanly if the version is already published (crates.io
API pre-check + cargo publish as the backstop) — so future
Scoop/Homebrew/winget jobs can be added alongside without breaking one
another or re-runs. The first such job's tag-vs-Cargo.toml guard
mirrors release.yaml.