Files
rdbms-playground/docs/adr/0054-release-versioning-and-version-surfaces.md
T
claude@clouddev1 c30a6114b9 feat(cli): --version/-V + in-app version command + release guard (ADR-0054)
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.
2026-06-16 15:57:54 +00:00

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

  1. Cargo.toml version is the single source of truth. This is the idiomatic Rust position and avoids making Cargo.toml lie. The version is read at compile time via env!("CARGO_PKG_VERSION"); no build-time injection of the tag into the crate.

  2. 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 node app::VERSION, AppCommand::Version), emitting the same line into the output panel. Both go through cli::version_text() → the catalog key cli.version_line ("rdbms-playground {version}"), so there is exactly one rendered string and one version source.
  3. Release-CI discipline. release.yaml's pre-build test job gains a version guard: it parses CARGO_PKG_VERSION from cargo metadata and fails the release unless the pushed tag equals v<that version>. So --version, the release name, and the downloaded asset are always in lockstep — enforced by the machine, not by memory.

  4. The release ritual: bump Cargo.toml → commit → tag v<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.toml a placeholder/lie. Rejected.
  • Git-hash + build-date enrichment (a build.rs so dev builds read 0.2.0 (a1b2c3d)): useful for bug reports, but not needed for the tag↔release↔--version consistency this ADR is about. Deferred; can be added behind the same version_text() seam without changing the policy.
  • UI placement beyond the version command (status-bar string, etc.): the command + help listing 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.toml bump 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 requires hint.cmd.version, which is supplied. Tested: CLI flag parse (--version/-V/default-off), version_text() carries CARGO_PKG_VERSION, the in-app command parses to AppCommand::Version and 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.