Skip to content

fix(#429): macOS installs pinned kubectl/k3d/helm via the shared verified path (not bare brew) - #521

Merged
shujaatTracebloc merged 2 commits into
developfrom
fix/429-macos-pinned-tools
Jul 31, 2026
Merged

fix(#429): macOS installs pinned kubectl/k3d/helm via the shared verified path (not bare brew)#521
shujaatTracebloc merged 2 commits into
developfrom
fix/429-macos-pinned-tools

Conversation

@shujaatTracebloc

@shujaatTracebloc shujaatTracebloc commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

#429 — macOS installed CLI tools via bare brew: version pins inoperative, no checksums

On macOS, kubectl/k3d/helm came from bare brew install, which:

  1. Silently ignored the K3D_VERSION/HELM_VERSION pins — brew floats to latest, so Macs ran different, chart-untested tool versions than the pinned Linux installs (and than the docs claim).
  2. Had no checksum of our own (delegated to brew).

Fix — one pinned, verified path across OSes

Both setup-macos.sh and setup-linux.sh are always sourced, so install_macos_cli_tools now routes through the same install_kubectl / install_k3d / install_helm (setup-linux.sh) that Linux uses — after setting OS_DL=darwin and a macOS tools target (/usr/local/bin, on the default login PATH on both Intel and Apple Silicon; no PATH-persistence dance).

The three fetchers are made OS-aware via ${OS_DL:-linux}Linux (and every bats fetch test that leaves OS_DL unset) stays byte-identical; only the macOS runtime sets darwin. brew still delivers Docker Desktop / colima unchanged.

Portable checksum (common.sh_verify_sha256)

GNU sha256sum on Linux; shasum -a 256 on macOS — which ships a BSD /sbin/sha256sum (Darwin 1.0) that lacks GNU --check. A type -t guard honors the bats mocks' sha256sum shell-function, so the existing Linux fetch tests keep passing on macOS dev boxes.

Execute-gate preserved (#411)

Each shared installer ends in assert_tool_runs, so a broken/wrong-arch binary fails the System tools step loudly rather than printing a false success. The drift-check contract now accepts macOS delegating to the gated install_<tool>.

Acceptance criteria

  • ✅ Fresh macOS install yields exactly the pinned k3d/helm versions (shared pinned path).
  • ✅ A broken binary fails Step "System tools" loudly (assert_tool_runs in each installer).

Tests / gates

  • New scripts/tests/setup-macos.bats: OS_DL=darwin fetch+verify for all three tools, _verify_sha256 portability (match/mismatch/empty + shasum fallback), and install_macos_cli_tools delegation with no bare brew.
  • +2 check-drift.bats self-tests for the delegation contract.
  • shellcheck --severity=error, check-style, check-drift all clean; full setup-linux.bats (132) green; manifest.sha256 regenerated (R8).
  • Pre-existing macOS-only failures (validate_config, early-bailout) confirmed unrelated (fail on clean develop).

Closes #429


Note

Medium Risk
Changes how production macOS installs place privileged binaries under /usr/local/bin and rely on sudo; wrong-arch or checksum failures should fail at System tools, but this is a meaningful install-path shift across OSes.

Overview
macOS CLI tools no longer come from floating brew install calls. install_macos_cli_tools sets OS_DL=darwin, installs into /usr/local/bin with sudo, and reuses the Linux install_kubectl / install_k3d / install_helm path so K3D_VERSION and HELM_VERSION pins and checksum verification match Linux.

Shared plumbing adds _verify_sha256 in common.sh (GNU sha256sum vs macOS shasum, fail-closed). The kubectl/k3d/helm fetchers in setup-linux.sh pick assets via ${OS_DL:-linux} and verify through that helper; Linux behavior stays the default when OS_DL is unset.

Drift checks treat macOS install_<tool> delegation as satisfying execute-gate parity. New setup-macos.bats covers portable checksums, darwin download URLs, and macOS installer delegation. manifest.sha256 is updated for touched scripts.

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

…fied path (not bare brew)

macOS installed the CLI tools with bare `brew install kubectl/k3d/helm`, which
floated to latest and SILENTLY ignored the K3D_VERSION/HELM_VERSION pins — so Macs
ran different, chart-untested tool versions than the pinned Linux installs (and than
the docs claim), with no checksum of our own.

Route macOS through the SAME pinned, checksum-verified direct-download path as Linux.
Both setup-*.sh are always sourced, so install_macos_cli_tools now calls the shared
install_kubectl/install_k3d/install_helm (setup-linux.sh) after setting OS_DL=darwin
and a macOS tools target (/usr/local/bin, on the default PATH on Intel + Apple
Silicon). The fetchers are made OS-aware via ${OS_DL:-linux} — Linux (and every bats
fetch test that leaves OS_DL unset) stays byte-identical.

- common.sh: portable _verify_sha256 — GNU sha256sum on Linux, shasum -a 256 on
  macOS (which ships a BSD /sbin/sha256sum that lacks GNU --check). A `type -t`
  guard honors the bats mocks' sha256sum shell-function so the Linux fetch tests
  keep passing on macOS dev boxes.
- Execute-gate (#411) is preserved: each shared installer ends in assert_tool_runs,
  so a broken/wrong-arch binary fails the "System tools" step loudly. Updated the
  drift-check contract to accept macOS delegating to the gated install_<tool>.
- brew still delivers Docker Desktop / colima (install_docker_desktop) unchanged.

Tests: new scripts/tests/setup-macos.bats (OS_DL=darwin fetch/verify for all three
tools + _verify_sha256 portability + install_macos_cli_tools delegation, no bare
brew); +2 check-drift self-tests for the delegation contract. shellcheck/style/drift
clean; manifest regenerated.

Closes #429

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@shujaatTracebloc shujaatTracebloc self-assigned this Jul 31, 2026
@shujaatTracebloc
shujaatTracebloc marked this pull request as ready for review July 31, 2026 14:10
…ed-tools

# Conflicts:
#	scripts/manifest.sha256
@shujaatTracebloc
shujaatTracebloc merged commit cf9e727 into develop Jul 31, 2026
37 checks passed
@shujaatTracebloc
shujaatTracebloc deleted the fix/429-macos-pinned-tools branch July 31, 2026 14:26

@saadqbal saadqbal 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.

Nice PR — the shared pinned/verified path plus keeping the darwin selectors behind OS_DL:-linux (so Linux + the fetch bats stay byte-identical) is the right shape, and the drift/self-tests + setup-macos.bats cover it well. One small nit inline; not a blocker.

# this only moves the version-pinned CLI tools onto the shared path. Each installer
# ends in the execute-gate (#411, assert_tool_runs), so a broken/wrong-arch binary
# fails the "System tools" step loudly rather than printing a false success.
OS_DL="darwin"

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.

Nit: OS_DL / TB_TOOLS_DIR / TB_TOOLS_SUDO are set as globals here and leak past this function. local them — bash dynamic scope still reaches install_kubectl/k3d/helm, and you get the module-scope defaults (TB_TOOLS_SUDO="sudo", etc.) restored for free on return instead of leaving OS_DL=darwin set for the rest of the run.

LukasWodka added a commit that referenced this pull request Jul 31, 2026
develop advanced between resolving the first merge and pushing it: #521 (macOS
installs pinned kubectl/k3d/helm via the shared verified path) and #522 (SIGPIPE
under pipefail made the chart guard skip a real chart change). Both touch
scripts/, so the install-k8s.ps1 hash line in scripts/manifest.sha256 collided
again — the fifth time today.

Only the manifest conflicted. Neither PR touches scripts/lib/preflight.sh
(they changed setup-macos.sh, gpu-nvidia.sh, install-client-helm.sh), so there is
no semantic overlap with this branch's memory work; re-verified that
_pf_total_mem_kb is still undefined and that no file carries conflict markers.

Gates re-run on the merged tree, not carried over from the previous merge:
bats scripts/tests/*.bats -> plan 692, ok 692, not ok 0 (complete TAP run; the
suite grew from 683 because #521 added setup-macos.bats);
shellcheck --severity=error over the CI file set -> rc=0; Pester -> 403 passed /
0 failed; check-style clean; check-drift no drift; gen-manifest.sh --check current.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
shujaatTracebloc added a commit that referenced this pull request Jul 31, 2026
…h VZ/Rosetta (#524)

* fix(#433): verify amd64 emulation on Apple Silicon + start colima with VZ/Rosetta

The client images are amd64-only. On Apple Silicon the installer merely printed a
note and proceeded, ASSUMING Docker Desktop's emulation works — so if "Use Rosetta
for x86_64/amd64 emulation" is off (or colima lacks it), the images crash-loop with
an exec-format error minutes later, with no preflight/setup catch. The headless
colima path was worse: `colima start` passed no arch/Rosetta flags, so an Apple
Silicon Mac got an arm64 VM running amd64 images under slow QEMU or not at all.

- assert_amd64_emulation (setup-macos.sh): post-Docker smoke — force-run a tiny amd64
  binary (`docker run --rm --platform linux/amd64 busybox:1.36 true`) once Docker is
  up, and HARD-FAIL naming the exact Docker Desktop setting + the colima remedy, so
  the problem is caught at setup, never as a crash-looping pod. Wired into install_macos
  right after Docker is confirmed ready. Intel Macs skip it (native amd64);
  TRACEBLOC_ALLOW_ARM64 is the escape hatch; image overridable via TB_AMD64_SMOKE_IMAGE.
- _install_docker_colima: on Apple Silicon + macOS 13+ (VZ), start colima with
  `--vm-type vz --vz-rosetta` for Rosetta-accelerated amd64 (matches Docker Desktop's
  Rosetta setting); older macOS keeps the QEMU default. bash-3.2-safe: the arg vector
  is never empty. New _macos_supports_vz helper (TB_MACOS_VER-overridable).
- _pf_arch (preflight.sh): the macOS note now NAMES the Rosetta setting and says the
  real check runs once Docker is up — instead of "assume it works".

Tests: new scripts/tests/setup-macos-arch.bats (VZ detection, colima flag matrix,
smoke pass/fail/skip/override) + a preflight.bats assertion on the named setting.
Separate test file from setup-macos.bats to avoid a file-add clash with #429/#521.
shellcheck/style/drift clean; manifest regenerated; preflight.bats (82) green.

Closes #433

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(#433): guard colima VZ flags on existing VMs + time-bound the amd64 smoke (Bugbot)

Two Bugbot findings on the Apple Silicon work:

1. (High) colima refuses to change vmType on an EXISTING instance, so unconditionally
   appending --vm-type vz --vz-rosetta aborted `colima start` on a prior QEMU VM (from
   an earlier install or reboot) with a generic failure. Only request VZ+Rosetta on a
   FRESH start now (new _colima_instance_exists via `colima list --json`); a pre-existing
   VM starts as-is, and if its amd64 emulation is broken the post-Docker smoke already
   names the `colima delete && colima start --vm-type vz --vz-rosetta` recreate remedy.

2. (Medium) assert_amd64_emulation ran `docker run` via unbounded spin_cmd — a wedged
   daemon or stuck pull could hang a headless install forever. Switched to
   spin_cmd_bounded (TB_AMD64_SMOKE_TIMEOUT, default 120s); a 124 timeout falls through
   to the same remediation, per the installer's every-docker-call-is-bounded rule.

Tests: +existing-VM colima test (no VZ flags), + bounded-smoke assertion; 11/11 in
setup-macos-arch.bats. shellcheck/style/drift clean; manifest regenerated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor

/fr-pass

Sign up for free to 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.

4 participants