Cargo.toml version is the single source of truth, surfaced by a --version/-V CLI flag and an in-app `version` command (both via cli::version_text -> cli.version_line). release.yaml gains a guard that fails the release unless the v* tag equals v<CARGO_PKG_VERSION>, keeping --version, the release name, and the asset in lockstep. New app command wired across grammar/REGISTRY/dispatch/usage/help/hint-corpus/keys; 6 test-first tests. Also fixes a stale "macOS deferred" comment in release.yaml. ADR-0054 + README index + plan-doc step 1.
3.7 KiB
ADR-0054: Release versioning policy + version surfaces (--version / version)
Status
Accepted — implemented 2026-06-16 (plan:
docs/plans/20260616-public-availability.md, step 1). First step on the
road to public availability. Adds a --version / -V CLI flag and an
in-app version command, both reporting CARGO_PKG_VERSION, plus a
release-CI guard that the v* tag equals that version. No prior issue or
requirements.md item existed for this — it was an untracked gap.
Context
Before this, Cargo.toml carried version = "0.1.0", the binary exposed
no way to report its version, and release.yaml named assets from the
git tag (rdbms-playground-<tag>-<target>) while building from
Cargo.toml. Tag and crate version were decoupled: tagging v0.2.0
would publish an asset named …-v0.2.0-… containing a binary that (had it
been able to say) reported 0.1.0. On the way to public availability —
where users download a versioned artifact and file bug reports against "the
version I'm running" — that drift is a correctness problem.
Decision
-
Cargo.tomlversionis the single source of truth. This is the idiomatic Rust position and avoids makingCargo.tomllie. The version is read at compile time viaenv!("CARGO_PKG_VERSION"); no build-time injection of the tag into the crate. -
Two user-facing surfaces, one source:
--version/-V— CLI flag (hand-rolled parser, mirrors--help): prints and exits before any other work (main.rs).version— an in-app app command (REGISTRY nodeapp::VERSION,AppCommand::Version), emitting the same line into the output panel. Both go throughcli::version_text()→ the catalog keycli.version_line("rdbms-playground {version}"), so there is exactly one rendered string and one version source.
-
Release-CI discipline.
release.yaml's pre-buildtestjob gains a version guard: it parsesCARGO_PKG_VERSIONfromcargo metadataand fails the release unless the pushed tag equalsv<that version>. So--version, the release name, and the downloaded asset are always in lockstep — enforced by the machine, not by memory. -
The release ritual: bump
Cargo.toml→ commit → tagv<that number>→ push the tag. The guard rejects any deviation.
Rejected / deferred
- Inject the tag into the build (tag as source of truth): fiddly with
cargo and makes
Cargo.tomla placeholder/lie. Rejected. - Git-hash + build-date enrichment (a
build.rsso dev builds read0.2.0 (a1b2c3d)): useful for bug reports, but not needed for the tag↔release↔--versionconsistency this ADR is about. Deferred; can be added behind the sameversion_text()seam without changing the policy. - UI placement beyond the
versioncommand (status-bar string, etc.): the command +helplisting is enough for now (user decision).
Consequences
- A release can no longer ship a binary whose self-reported version disagrees with its tag/filename.
- Cutting a release now requires a
Cargo.tomlbump commit — a small, deliberate step (and a natural place to update a changelog later). - New keys:
cli.version_line(+help.app.version,parse.usage.version,hint.cmd.version.what/.example); a new REGISTRY command means the comprehensiveness coverage test now also requireshint.cmd.version, which is supplied. Tested: CLI flag parse (--version/-V/default-off),version_text()carriesCARGO_PKG_VERSION, the in-app command parses toAppCommand::Versionand emits the version. - This is step 1 of
docs/plans/20260616-public-availability.md; the installer (install.sh) and package-manager work (D3) build on top.