feat(version): replace --version with version subcommand; add check/update/--train (MK-26) #45

Merged
David merged 1 commit from feat/version-subcommand-update-train-MK-26 into main 2026-05-25 18:28:58 +02:00
Owner

Resolves MK-26.

Replaces the bare --version clap flag with a version subcommand tree and adds a --train release-channel selector, mirroring the youtrack-cli + forgejo-cli ergonomics.

What changed

  • monkey version / monkey version show print the build banner (same content the old --version produced). The bare --version flag is removed and now errors.
  • monkey version check [--train <name>] HEADs the channel sha256 sidecar, compares Last-Modified against the baked MONKEY_BUILD_DATE, and reports behind / current / unknown. A 404 produces an available trains: message rather than a raw HTTP error.
  • monkey version update [--train <name>] [--force] [--dry-run] [--url <base>] resolves the running binary, refuses inside an OCI container with a docker pull pointer, pre-checks the parent directory is writable before downloading, then downloads, SHA256-verifies, atomically renames over the running binary, smoke-tests <new> version, and prints FROM/TO lines.
  • New src/version.rs module: action enum, URL/train resolution, container detection (Docker / containerd / podman via /.dockerenv + /proc/1/cgroup), writable pre-flight, sha256 verify, and the freshness decision.
  • HTTP client is reqwest with rustls + ring and bundled webpki roots, so the static-musl build needs no OpenSSL / aws-lc-rs toolchain or system CA certs. Date handling uses time; hashing uses sha2. httpmock is a dev-dependency only (not in the binary).
  • build.rs bakes MONKEY_UPDATE_URL (env-overridable, defaults to the public Forgejo Generic Package base).
  • .forgejo/workflows/build-binary.yml writes a <asset>.sha256 sidecar next to each published binary, publishes binary + sidecar together, and on release tags also publishes to the stable channel that version update defaults to. latest stays an alias for stable until beta / nightly channels exist.
  • README documents monkey version update under the Static binary section.

Release-channel notes

stable is the default train. beta / nightly / latest are accepted and resolve to the stable registry path in this MVP (placeholders until the workflow grows channel-aware publishing). Unknown train names fall through and surface the available trains: message on a 404.

Tests

  • Unit tests (run on every cargo test): container-detection matcher, per-train URL builder, sha256 mismatch rejection, dry-run / up-to-date decision, writable pre-flight, HTTP-date parsing.
  • #[ignore]d httpmock integration test (tests/version_update.rs) drives the full download / verify / atomic-replace / smoke-test path and the sha256-mismatch rejection path. Run with cargo test --test version_update -- --ignored.
  • just check passes, including the builder-stage musl Docker compile (verifies reqwest + ring + rustls cross-compile cleanly).

Note on the issue trailer

Per the repo's commit policy, the commit carries a bare #MK-26 (link only). The Forgejo VCS integration applies trailer commands at push time, not merge time, so a State Done trailer would resolve the issue prematurely while this PR is still under review. State should move to Done on merge.

Resolves MK-26. Replaces the bare `--version` clap flag with a `version` subcommand tree and adds a `--train` release-channel selector, mirroring the youtrack-cli + forgejo-cli ergonomics. ## What changed - `monkey version` / `monkey version show` print the build banner (same content the old `--version` produced). The bare `--version` flag is removed and now errors. - `monkey version check [--train <name>]` HEADs the channel sha256 sidecar, compares `Last-Modified` against the baked `MONKEY_BUILD_DATE`, and reports behind / current / unknown. A 404 produces an `available trains:` message rather than a raw HTTP error. - `monkey version update [--train <name>] [--force] [--dry-run] [--url <base>]` resolves the running binary, refuses inside an OCI container with a `docker pull` pointer, pre-checks the parent directory is writable before downloading, then downloads, SHA256-verifies, atomically renames over the running binary, smoke-tests `<new> version`, and prints FROM/TO lines. - New `src/version.rs` module: action enum, URL/train resolution, container detection (Docker / containerd / podman via `/.dockerenv` + `/proc/1/cgroup`), writable pre-flight, sha256 verify, and the freshness decision. - HTTP client is reqwest with rustls + ring and bundled webpki roots, so the static-musl build needs no OpenSSL / aws-lc-rs toolchain or system CA certs. Date handling uses `time`; hashing uses `sha2`. `httpmock` is a dev-dependency only (not in the binary). - `build.rs` bakes `MONKEY_UPDATE_URL` (env-overridable, defaults to the public Forgejo Generic Package base). - `.forgejo/workflows/build-binary.yml` writes a `<asset>.sha256` sidecar next to each published binary, publishes binary + sidecar together, and on release tags also publishes to the `stable` channel that `version update` defaults to. `latest` stays an alias for `stable` until beta / nightly channels exist. - README documents `monkey version update` under the Static binary section. ## Release-channel notes `stable` is the default train. `beta` / `nightly` / `latest` are accepted and resolve to the `stable` registry path in this MVP (placeholders until the workflow grows channel-aware publishing). Unknown train names fall through and surface the `available trains:` message on a 404. ## Tests - Unit tests (run on every `cargo test`): container-detection matcher, per-train URL builder, sha256 mismatch rejection, dry-run / up-to-date decision, writable pre-flight, HTTP-date parsing. - `#[ignore]`d httpmock integration test (`tests/version_update.rs`) drives the full download / verify / atomic-replace / smoke-test path and the sha256-mismatch rejection path. Run with `cargo test --test version_update -- --ignored`. - `just check` passes, including the builder-stage musl Docker compile (verifies reqwest + ring + rustls cross-compile cleanly). ## Note on the issue trailer Per the repo's commit policy, the commit carries a bare `#MK-26` (link only). The Forgejo VCS integration applies trailer commands at push time, not merge time, so a `State Done` trailer would resolve the issue prematurely while this PR is still under review. State should move to Done on merge.
feat(version): replace --version flag with version subcommand tree (MK-26)
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 21s
Create release / Create release from merged PR (pull_request) Has been skipped
14a317d712
Drop clap's bare `--version` flag and add a `version` subcommand tree mirroring the youtrack-cli + forgejo-cli ergonomics, plus a `--train` release-channel selector.

`monkey version` (and the explicit `monkey version show`) print the build banner. `monkey version check [--train]` HEADs the channel sha256 sidecar and compares its `Last-Modified` against the baked `MONKEY_BUILD_DATE`, reporting behind/current/unknown; a 404 surfaces an `available trains:` message instead of a raw HTTP error. `monkey version update [--train] [--force] [--dry-run] [--url]` resolves the running binary, refuses inside an OCI container with a `docker pull` pointer, pre-checks that the parent directory is writable before downloading, then downloads, SHA256-verifies, atomically renames over the running binary, smoke-tests `<new> version`, and prints FROM/TO lines.

New module `src/version.rs` holds the action enum, URL/train resolution, container detection (Docker/containerd/podman via `/.dockerenv` + `/proc/1/cgroup`), the writable pre-flight, the sha256 verify, and the freshness decision. HTTP uses reqwest with rustls+ring and bundled webpki roots so the static-musl build needs no OpenSSL/aws-lc-rs toolchain or system CA certs; date handling uses the time crate; hashing uses sha2.

build.rs bakes `MONKEY_UPDATE_URL` (env-overridable, defaults to the public Forgejo Generic Package base). The build-binary workflow now writes a `<asset>.sha256` sidecar next to each published binary, publishes binary+sidecar together, and on release tags also publishes to the `stable` channel that `version update` defaults to (`latest` remains its alias until beta/nightly channels exist).

In-tree unit tests cover container detection, the per-train URL builder, sha256 mismatch rejection, the dry-run/up-to-date decision, the writable pre-flight, and HTTP-date parsing. An `#[ignore]`d httpmock integration test drives the full download/verify/replace path and the mismatch-rejection path.

#MK-26

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
David merged commit 97ad203787 into main 2026-05-25 18:28:58 +02:00
David deleted branch feat/version-subcommand-update-train-MK-26 2026-05-25 18:28:58 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pandoras-box/monkey!45
No description provided.