rickub/clipublic Fork
⑂ main
Commits
⬇ Clone ▾
git clone https://git.rickub.com/rickub/cli.git
git clone ssh://git@rickub.com/rickub/cli.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

feat: warn when the CLI is older than the newest release on its host #5

Merged@ogirardot wants to merge feat/staleness-notice into main
Merged as aa8785956e63.
  • @ogirardot opened this merge request · 5d ago

    What

    Implements the staleness signal of rickub/rickub#305: a CLI older than the newest release on its host prints a visible one-line warning naming both versions.

    Why this shape (premise check)

    The issue's direction 1 says "the server knows its own version and the CLI already talks to it" — but the rickub server exposes no version endpoint today: cfg.BuildSHA (web/config.go:725) feeds only Sentry, /healthz answers plain "ok", and the JSON API has no /api/v1/version (nothing serves an instance build/version to clients). A server-side endpoint would be an rickub/rickub change, out of this repo.

    What the instance DOES already report, by design and documented as the stable contract, is the newest CLI release: GET /{owner}/{repo}/releases/latest is a 302 whose Location carries the tag — "Install scripts resolve 'latest' from the Location header — no API token, no HTML scraping" (web/handlers_releases.go, repoReleaseLatestRedirect). The CLI is distributed from rickub/cli releases on the host, so "the newest release on the host" is exactly the staleness that manufactured the false reports (#294, #279): a binary older than the current product. The "instance's version" reading and the "latest CLI release" reading coincide for the dogfood host and any mirror.

    The change

    • cmd/update_check.go — the probe (resolveLatestCLITag, no redirects followed, 2s timeout, unauthenticated: the route is public and the check must not wave a token around), semver comparison (compareVersions/newerThan — release > its prerelease, numeric rc identifiers, unparsable tags never warn), and the once-a-day-per-host stamp beside the config file (update-check/<normalized host>).
    • cmd/root.go — PersistentPreRunE runs maybeWarnAboutStaleCLI on every command. This is deliberate: the false reports were filed by agents using the CLI (run list, pr create), not by anyone running rickub version first; a warning that only shows on version prevents nothing.
    • Notice goes to stderr — --json stdout stays parseable, pipes stay clean.

    Guardrails: dev builds (Version "dev", i.e. every go test/go run) never probe; any failure (404, unreachable, non-redirect, non-version tag) is silent; an attempted check (whatever the outcome) writes the stamp so a broken host is not re-probed on every command; semver ordering keeps v0.2.0-rc.7 from nagging a running 0.2.0.

    Tests (11 new, cmd/update_check_test.go)

    Notice names both versions on stderr with stdout untouched; fresh binary and rc-of-running-version are quiet; probe throttled to 1/day (rewound stamp proves repeat); dev build probes zero times; five failure shapes silent; stamps are per-host (--host switch re-checks); comparator table; Location-shape table (incl. the list page, latest itself, a download path); stamp path sanity; freshness window (incl. future stamp and garbage stamp).

    Bite-proof

    • Removing the PersistentPreRunE hook fails TestStaleCLINoticeNamesBothVersions (no notice) and TestProbeIsThrottledPerHost (probes = 0 … want 1) — the check silently not running is precisely the self-concealing failure the issue describes.

    • End-to-end with real binaries (the issue's own acceptance shape, old binary against a host with a newer release): a 0.1.0 build against a host whose latest redirect names v0.2.0 prints

      rickub 0.1.0 (darwin/arm64)          # stdout, unchanged
      note: this rickub CLI is 0.1.0 but the newest release on http://… is v0.2.0 — some bugs you see may already be fixed; upgrade: http://…/rickub/cli/releases/v0.2.0   # stderr
      

      while a 0.2.0 build against the same host prints only its version line.

    On the issue's second acceptance line (rickub version identifies a build traceable to a commit): release builds are stamped cmd.Version=<version> (scripts/build-dist.sh), and every version — stable and rc — exists as a release tag in this repo, so rickub 0.2.0 (os/arch) resolves to a tag and thus a commit.

    Reference: rickub/rickub#305 (cross-repo; closing happens on that issue).

  • @ogirardot · 5d ago

    Orchestrator review (post-green, #305 + #279's wire-level tests): the update check rides the documented releases/latest Location contract (no new endpoint needed — the missing /api/v1/version is correctly filed as rickub/rickub#910 instead of smuggled in), hooks every command's PersistentPreRunE (the right call — the false reports came from agents USING the CLI, not from version), throttles once/day/host beside the config, and prints to stderr so JSON stdout stays clean. Dev builds skip; rc-of-running never nags; every failure mode is silent. 11 tests + a real-binary end-to-end (0.1.0 build warns against a v0.2.0 host; 0.2.0 stays silent); the gosec G304 round was annotated CLI-owned and re-run green (runs 61/62). The branch also carries the body-stdin acceptance tests from !4 verbatim — merging this supersedes !4. Merging.

Sign in to comment.