Skip to content

fix(installer): stop every platform's fast path from pinning users to an old CLI (client#707) - #708

Merged
LukasWodka merged 1 commit into
developfrom
fix/707-cli-version-floor
Aug 13, 2026
Merged

fix(installer): stop every platform's fast path from pinning users to an old CLI (client#707)#708
LukasWodka merged 1 commit into
developfrom
fix/707-cli-version-floor

Conversation

@LukasWodka

@LukasWodkaLukasWodka commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Closes#707. Related: tracebloc/backend#1920 (the server-side floor, the other lever).

The problem

Once a machine is "already set up", no installer on any platform ever updated the CLI again.

ComponentUpdate mechanismStale risk
Installer scriptsre-fetched from tracebloc.io/i.sh every runnone
Chart + in-cluster imageshourly auto-upgrade CronJobnone — self-heals
CLI binary (host)only a full install run, or manual tracebloc upgradepermanent

Nothing inside a cluster can update a binary on the host, so the installer was the only automatic path — and every fast path skipped it. A field machine sat on v0.5.1 from 6 July against a current 0.10.6, on a box whose chart had meanwhile auto-upgraded 1.8.5 → 1.9.34. The user re-ran the newest installer; it exited before the CLI step.

macOS and Linux — identical (one file, no platform branch)

  • install-k8s.sh:198 — assess → healthy → hands off → exit 0
  • install-k8s.sh:241install_tracebloc_cli, the only call site, never reached

_assess_cli_present checked presence, not version. The asymmetry is the tell: a missing CLI was correctly degraded / cli-missing and got installed. Only a stale one slipped through — the single state nothing checked.

Windows — same hole, plus a worse one

functionTest-ToolsPresent {
foreach ($tin@('docker','kubectl','k3d','helm')) { ... }
}

The CLI isn't in that list at all. And completed is set purely from ClientState -eq "connected", which says nothing about the CLI, while Install-TraceblocCli is deliberately non-fatal.

So a Windows machine whose CLI install failed was still marked complete and never retried — permanently CLI-less, not merely stale. That's a distinct defect from the one seen in the field, and it's fixed here too.

Why the CLI's own nudge couldn't rescue this

It landed in v0.10.0, is nudge-only, needs an interactive TTY, and is skipped under CI or without a config dir. By definition it cannot reach anyone below v0.10.0 — exactly the population at risk. The field machine at 0.5.1 could not be told.

The fix

Both fast paths now check the version, floor 0.10.0 — the release from which the CLI maintains itself.

It is a floor, not a "must be latest": no network call per run, and the constant never needs raising. Below it → degraded / cli-outdated (bash) or fall through to Install-TraceblocCli (Windows), which upgrades once.

Both fail open on an unreadable version. That is not evidence of staleness, and reinstalling the CLI on every run would be worse than the staleness it exists to fix.

_version_lt is self-contained — no sort -V (BSD sort predates it, and this must behave identically on macOS) and no jq — and orders 0.9.9 below 0.10.0 rather than lexically.

Either fix alone leaves a platform broken, so they land together.

Test plan

988 bats + 670 Pester, 0 failures.make check green, manifest regenerated.

Mutation-real on both sides:

--- bash: cli-outdated branch removed from classify ---
not ok 21 _assess_classify: a stale CLI is degraded/cli-outdated, NEVER healthy
ok 22 _assess_classify: a current CLI still reaches healthy <- control holds
--- bash: floor neutered to 0.0.0 ---
not ok 15 _assess_cli_outdated: a CLI below the floor is outdated
--- Windows: predicate removed from the fast-path condition ---
[-] gates the fast nothing-to-do path on tools + a CURRENT CLI + running cluster + HEALTHY client

Covered on both platforms: below floor, at floor, above floor, the 9-vs-10 ordering trap, unreadable version (no churn), a CLI that errors on version, and — Windows only — a completely absent CLI no longer fast-pathing past its own install.

One existing Pester source-guard was updated deliberately: it pins the exact text of the fast-path condition, which this PR changes.

🤖 Generated with Claude Code


Note

Medium Risk
Changes installer early-exit and health classification on all platforms; behavior is bounded by a fixed floor and fail-open version parsing, with strong test coverage.

Overview
Fixes client#707: “already set up” installs could exit before touching the host CLI, leaving users on ancient binaries while the cluster auto-upgraded.

Unix (assess.sh) adds a 0.10.0 version floor (not “latest”), _version_lt / _assess_cli_outdated, and a new degraded / cli-outdated branch with an “out of date — updating” message so the normal flow runs install_tracebloc_cli. Unparseable tracebloc version output fails open to avoid reinstall churn.

Windows (install-k8s.ps1) adds Test-TraceblocCliCurrent and gates the nothing-to-do fast path on it—covering stale CLIs (not in Test-ToolsPresent) and machines marked completed after a non-fatal failed CLI install.

Tests and manifest.sha256 updated for both platforms.

Reviewed by Cursor Bugbot for commit 56fa915. Bugbot is set up for automated code reviews on this repo. Configure here.

… an old CLI
Once a machine is "already set up", no installer on any platform ever updated
the tracebloc CLI again. The cluster keeps upgrading itself hourly via the
auto-upgrade CronJob; the host binary does not, and nothing noticed. A field
machine was found on CLI v0.5.1 from 6 July against a current 0.10.6 — five
minors behind — on a box whose chart had meanwhile auto-upgraded 1.8.5 -> 1.9.34.
The user re-ran the newest installer and it exited before reaching the CLI step.
macOS and Linux (one file, no platform branch, so identical):
install-k8s.sh:198 assess -> healthy -> hands off -> exit 0
install-k8s.sh:241 install_tracebloc_cli, the ONLY call site, never reached
_assess_cli_present checked presence, not version. Note the asymmetry: a MISSING
CLI was correctly degraded/cli-missing and got installed; only a STALE one
slipped through, the single state nothing checked.
Windows had the same hole plus a worse one. Test-ToolsPresent covers
docker/kubectl/k3d/helm — the CLI is not in it at all — and `completed` is set
purely from ClientState -eq "connected", which says nothing about the CLI, while
Install-TraceblocCli is deliberately non-fatal. So a machine whose CLI install
FAILED was still marked complete and never retried: permanently CLI-less, not
merely stale.
The CLI's own nudge cannot rescue either case. It landed in v0.10.0, is
nudge-only, needs an interactive TTY, and is skipped under CI / without a config
dir — and by definition cannot reach anyone below v0.10.0, which is exactly the
population at risk.
Both fast paths now check the version, with 0.10.0 as the floor: the release from
which the CLI can keep itself current. It is a FLOOR, not a "must be latest", so
it costs no network call per run and never needs raising. Below it ->
degraded/cli-outdated (bash) / fall through to Install-TraceblocCli (Windows),
which upgrades it once.
Both fail OPEN on an unreadable version — that is not evidence of staleness, and
reinstalling the CLI on every run would be worse than the staleness.
_version_lt is self-contained: no `sort -V` (BSD sort predates it) and no jq, and
it orders 0.9.9 below 0.10.0 rather than lexically.
Either fix alone leaves a platform broken, so they land together. 988 bats + 670
Pester green; the fast-path guards on both sides are mutation-real.
Closes#707
Refs tracebloc/backend#1920
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@LukasWodkaLukasWodka self-assigned this Aug 13, 2026

@saadqbalsaadqbal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, careful fix. The floor check is numeric on both platforms, not lexical — verified 0.9.9 < 0.10.0, the 0.8.2 vs 0.8.10 pair, and that a v prefix / -rc suffix still compare as the base version; equal-or-newer never trips a reinstall or a downgrade. macOS rides the same shared assess.sh gate as Linux (install.sh -> install-k8s.sh), so "every platform" really does hold — nothing left pinned. Ran it here: bats (59) green, the Pester Test-TraceblocCliCurrent + fast-path-gate specs green, and manifest.sha256 matches both changed files. Nice avoidance of the version | head -1 SIGPIPE trap too.

One non-blocking thing: the 0.10.0 floor is hardcoded twice (assess.sh TB_CLI_MIN_VERSION, install-k8s.ps1 $script:TB_CLI_MIN_VERSION). Fine while it stays a never-raised floor, but the two can drift silently — a cross-reference comment (or one source) would be cheap insurance if it ever moves. (Also spotted in passing: PowerShell's [version] reads a 2-segment "0.10" as 0.10.-1, so it'd call that below the floor where bash treats it as 0.10.0 — moot since the CLI always prints 3-segment semver, just noting it.)

@LukasWodka
LukasWodka merged commit 8da5268 into developAug 13, 2026
49 checks passed
@LukasWodka
LukasWodka deleted the fix/707-cli-version-floor branch August 14, 2026 13:53
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Installer: no platform ever updates the CLI once a machine is 'already set up' (macOS, Linux, Windows)

2 participants

@LukasWodka@saadqbal