From 88025555b9d6dbf3d1e527c6ce0d20f6cc265580 Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Mon, 10 Aug 2026 10:49:50 -0400 Subject: [PATCH 1/5] Make controller-gen/kustomize/golangci-lint version checks reliable go-install-tool-branch only installs when the binary is missing, never verifying the pinned version against what's already on disk. Once a binary lands in bin//, it's reused forever across branch switches and version bumps since bin/ is gitignored and nothing else resets it. kustomize and controller-gen's targets also weren't fully .PHONY (only the wrapper name was, not the binary path), so Make's own mtime-based staleness check could skip their recipe entirely before any version check ran. Introduce go-install-tool-versioned, which compares a sidecar .version marker file against the pinned version instead of introspecting the binary's own --version output. Binary introspection isn't reliable for every tool installed this way: kustomize's `version` command depends on ldflags its own release process sets, which `go install` doesn't set, so identically-installed kustomize binaries were observed reporting "(devel)", an unexpanded `$Format:%H$` git-archive placeholder, or a correct version string depending on unrelated build-time factors. Co-authored-by: Claude Signed-off-by: Tiger Kaovilai --- Makefile | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 788da9dfb10..727aadda942 100644 --- a/Makefile +++ b/Makefile @@ -214,12 +214,7 @@ GOLANGCI_LINT = $(LOCALBIN)/$(BRANCH_VERSION)/golangci-lint .PHONY: golangci-lint $(GOLANGCI_LINT) golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary. $(GOLANGCI_LINT): $(LOCALBIN) - @if [ -f $(GOLANGCI_LINT) ] && $(GOLANGCI_LINT) --version | grep -q $(GOLANGCI_LINT_VERSION); then \ - echo "golangci-lint $(GOLANGCI_LINT_VERSION) is already installed"; \ - else \ - echo "Installing golangci-lint $(GOLANGCI_LINT_VERSION)"; \ - $(call go-install-tool-branch,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION)); \ - fi + $(call go-install-tool-versioned,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION),$(GOLANGCI_LINT_VERSION)) @if [ -L "$(LOCALBIN)/golangci-lint" ]; then \ unlink "$(LOCALBIN)/golangci-lint"; \ fi @@ -303,19 +298,19 @@ KUSTOMIZE ?= $(LOCALBIN)/$(BRANCH_VERSION)/kustomize CONTROLLER_GEN ?= $(LOCALBIN)/$(BRANCH_VERSION)/controller-gen ENVTEST ?= $(LOCALBIN)/setup-envtest -.PHONY: kustomize +.PHONY: kustomize $(KUSTOMIZE) kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. If wrong version is installed, it will be removed before downloading. $(KUSTOMIZE): $(LOCALBIN) - $(call go-install-tool-branch,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5@$(KUSTOMIZE_VERSION)) + $(call go-install-tool-versioned,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5@$(KUSTOMIZE_VERSION),$(KUSTOMIZE_VERSION)) @if [ -L "$(LOCALBIN)/kustomize" ]; then \ unlink "$(LOCALBIN)/kustomize"; \ fi @ln -sf "$(LOCALBIN)/$(BRANCH_VERSION)/kustomize" "$(LOCALBIN)/kustomize" -.PHONY: controller-gen +.PHONY: controller-gen $(CONTROLLER_GEN) controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. If wrong version is installed, it will be overwritten. $(CONTROLLER_GEN): $(LOCALBIN) - $(call go-install-tool-branch,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)) + $(call go-install-tool-versioned,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION),$(CONTROLLER_TOOLS_VERSION)) @if [ -L "$(LOCALBIN)/controller-gen" ]; then \ unlink "$(LOCALBIN)/controller-gen"; \ fi @@ -532,6 +527,29 @@ rm -rf $$TMP_DIR ;\ } endef +# go-install-tool-versioned installs $2 to branch-specific path $1, but only if $1 is missing +# or $1.version doesn't match the pinned version $3. Uses a sidecar marker file instead of +# introspecting the binary's own --version output, because that output is unreliable for some +# tools when installed via `go install` (e.g. kustomize reports "(devel)" or an unexpanded +# `$$Format:%H$$` placeholder instead of its real version, depending on build-time factors). +define go-install-tool-versioned +@if [ -f $(1) ] && [ -f $(1).version ] && [ "$$(cat $(1).version)" = "$(3)" ]; then \ + echo "$(notdir $(1)) $(3) is already installed" ;\ +else \ + set -e ;\ + mkdir -p $(dir $(1)) ;\ + rm -f $(1) $(1).version ;\ + TMP_DIR=$$(mktemp -d) ;\ + cd $$TMP_DIR ;\ + go mod init tmp ;\ + echo "Installing $(notdir $(1)) $(3)" ;\ + GOBIN=$(dir $(1)) go install -a -mod=mod $(2) ;\ + cd - >/dev/null ;\ + rm -rf $$TMP_DIR ;\ + echo "$(3)" > $(1).version ;\ +fi +endef + YQ = $(LOCALBIN)/yq yq: ## Download yq locally if necessary. # 4.28.1 is latest with go 1.17 go.mod From a70d9a89778e4dfa8f3084260c5dc6cdcee40b22 Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Wed, 12 Aug 2026 00:13:03 -0400 Subject: [PATCH 2/5] Remove setup-envtest if it cannot execute on this platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Folds in the fix from #2152 (same author, same theme: harden Makefile tool-binary caching under bin/). A containerized Make target (e.g. podman/docker build with a different GOARCH) can write a linux binary into the shared bin/ directory, replacing the native host binary `make test` needs — and since setup-envtest isn't branch-scoped like the other three tools, that binary is shared across every branch checkout too. #2152's own check used `$(ENVTEST) --help`'s exit code as the "is this binary compatible" signal, but that's unreliable the same way relying on kustomize's --version output was: setup-envtest's own --help exits 2 by its own convention even on a perfectly good binary, so that check would have triggered a reinstall on every single invocation, permanently defeating the cache. Verified by cross-compiling a real linux/amd64 setup-envtest and running it on this darwin/arm64 host: the shell reports exit code 126 specifically (POSIX "found but cannot execute" / exec format error) — check that instead of any nonzero exit. Also added $(ENVTEST) to the .PHONY line, matching the fix already applied to controller-gen/kustomize in the previous commit: without it, Make's own mtime-based staleness check can skip the recipe (and therefore this check) entirely once the binary file exists. Closes #2152 Co-authored-by: Claude Signed-off-by: Tiger Kaovilai --- Makefile | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 727aadda942..0239a172f0e 100644 --- a/Makefile +++ b/Makefile @@ -316,9 +316,23 @@ $(CONTROLLER_GEN): $(LOCALBIN) fi @ln -sf "$(LOCALBIN)/$(BRANCH_VERSION)/controller-gen" "$(LOCALBIN)/controller-gen" -.PHONY: envtest +# Remove setup-envtest if it exists but cannot execute on this platform. +# This can happen when a containerized Make target (e.g. podman/docker build +# with a different GOARCH) writes a linux binary into the shared bin/ directory, +# replacing the native host binary needed by `make test`. +# Checked via exit code 126 specifically (POSIX "found but cannot execute" / +# exec format error) rather than any nonzero exit, since setup-envtest's own +# --help exits 2 by its own convention on a perfectly working binary. +.PHONY: envtest $(ENVTEST) envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. $(ENVTEST): $(LOCALBIN) + @if [ -f $(ENVTEST) ]; then \ + $(ENVTEST) --help >/dev/null 2>&1; \ + if [ $$? -eq 126 ]; then \ + echo "Removing incompatible setup-envtest binary (wrong architecture)"; \ + rm -f $(ENVTEST); \ + fi; \ + fi $(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@v0.0.0-20250308055145-5fe7bb3edc86) .PHONY: operator-sdk From 48c32f2048fdc376d7074dfe57fbfe65fe08dc7e Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Wed, 12 Aug 2026 09:51:55 -0400 Subject: [PATCH 3/5] Extend arch-check to controller-gen/kustomize/golangci-lint too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The version-marker check alone isn't enough: a binary can have a correct .version marker but still be the wrong architecture, e.g. if a containerized build with a different GOARCH bind-mounts the host's bin/ directory (this Makefile documents exactly that workflow for `make test`: `docker run --platform linux/amd64 -v $PWD:$PWD ...`). Anything that does `go install` in there writes onto the host's real bin/ tree since it's the same mounted path, not a copy. That's not envtest-specific — it can happen to any of these four cached tool binaries. go-install-tool-versioned now also probes `$(1) --version` and checks specifically for exit code 126 (POSIX "found but cannot execute" / exec format error), same technique as the envtest fix. Verified all three tools (controller-gen, kustomize, golangci-lint) correctly detect and repair a wrong-arch binary even when its .version marker already matches the pinned version: cross-compiled a real linux/amd64 binary for each, copied it over the working native binary, confirmed each was detected and replaced. Co-authored-by: Claude Signed-off-by: Tiger Kaovilai --- Makefile | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 0239a172f0e..0dde430cf7f 100644 --- a/Makefile +++ b/Makefile @@ -541,15 +541,25 @@ rm -rf $$TMP_DIR ;\ } endef -# go-install-tool-versioned installs $2 to branch-specific path $1, but only if $1 is missing -# or $1.version doesn't match the pinned version $3. Uses a sidecar marker file instead of -# introspecting the binary's own --version output, because that output is unreliable for some -# tools when installed via `go install` (e.g. kustomize reports "(devel)" or an unexpanded -# `$$Format:%H$$` placeholder instead of its real version, depending on build-time factors). +# go-install-tool-versioned installs $2 to branch-specific path $1, but only if $1 is missing, +# $1.version doesn't match the pinned version $3, or $1 exists but cannot execute on this +# platform (checked via exit code 126, POSIX "found but cannot execute" / exec format error — +# this can happen when a containerized build with a different GOARCH bind-mounts the host's +# bin/ directory, e.g. `docker run --platform linux/amd64 -v $$PWD:$$PWD ... make manifests`). +# Uses a sidecar marker file for the version check instead of introspecting the binary's own +# --version output, because that output is unreliable for some tools when installed via +# `go install` (e.g. kustomize reports "(devel)" or an unexpanded `$$Format:%H$$` placeholder +# instead of its real version, depending on build-time factors). define go-install-tool-versioned -@if [ -f $(1) ] && [ -f $(1).version ] && [ "$$(cat $(1).version)" = "$(3)" ]; then \ +@ARCH_OK=1 ;\ +if [ -f $(1) ]; then \ + $(1) --version >/dev/null 2>&1 ;\ + if [ $$? -eq 126 ]; then ARCH_OK=0 ; fi ;\ +fi ;\ +if [ "$$ARCH_OK" = "1" ] && [ -f $(1) ] && [ -f $(1).version ] && [ "$$(cat $(1).version)" = "$(3)" ]; then \ echo "$(notdir $(1)) $(3) is already installed" ;\ else \ + if [ "$$ARCH_OK" = "0" ]; then echo "$(notdir $(1)) exists but cannot execute on this platform, removing and re-downloading" ; fi ;\ set -e ;\ mkdir -p $(dir $(1)) ;\ rm -f $(1) $(1).version ;\ From b86c89ee55deb43197acab11e34a17df1900da1c Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Wed, 12 Aug 2026 10:28:47 -0400 Subject: [PATCH 4/5] Fix a real crash: exit-126 arch check aborts under -e in modern Make MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An independent second-opinion review caught a severe bug in the previous commit: the exit-126 probe (`$(1) --version`, then a separate `if [ $? -eq 126 ]`) is a bare command outside any &&/||/if guard. Under `set -e` — which this Makefile's `.SHELLFLAGS = -ec` enables, honored by GNU Make 3.82+ — a bare failing command aborts the whole recipe immediately, before the exit-code check ever runs. My local macOS Make (3.81) silently ignores .SHELLFLAGS, so none of my testing could have caught this. Confirmed for real: installed GNU Make 4.4.1 via Homebrew and reproduced the crash directly — `make kustomize` died with "Error 1" every time the binary already existed, because kustomize's own `--version` exits 1 by its own convention even on a perfectly healthy binary (same root cause class as the setup-envtest --help issue already fixed: a tool's own nonzero-on-success exit code was being misread as "broken"). Replaced the whole exit-code-probe approach with `go version -m`, which reads a binary's embedded module version and GOOS/GOARCH directly from its build info, without executing it at all. This is strictly better, not just a patch: - No execution means no exit-code heuristic to get wrong, and no -e hazard, for any of these four tools. - No execution also closes a gap the review surfaced: exit-126 detection cannot work at all inside a container with qemu-user-static/binfmt_misc registered (standard in multi-arch CI/build images), since a wrong-arch binary just runs under emulation and returns its own exit code instead of an exec-format-error — defeating the check silently in exactly the environments it was meant to protect. - Drops the sidecar `.version` marker file entirely — go version -m reads the real, authoritative module version already embedded in the binary, so there's nothing separate left to go stale or desync from a copied/moved binary. envtest's bespoke arch-only check (added in the previous commit) is replaced outright by a plain call to the same go-install-tool-versioned macro used by the other three tools, rather than patched in place — one verified mechanism instead of two. Verified end-to-end with GNU Make 4.4.1 specifically (not just the macOS-default 3.81, which cannot exercise this class of bug): fresh install, idempotent re-run (previously the exact crash case for kustomize/envtest), and wrong-arch detection+repair, for all four tools. `make generate manifests bundle` zero diff, `make test` fully green. Co-authored-by: Claude Signed-off-by: Tiger Kaovilai --- Makefile | 66 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index 0dde430cf7f..0c676dfb4b2 100644 --- a/Makefile +++ b/Makefile @@ -316,24 +316,16 @@ $(CONTROLLER_GEN): $(LOCALBIN) fi @ln -sf "$(LOCALBIN)/$(BRANCH_VERSION)/controller-gen" "$(LOCALBIN)/controller-gen" -# Remove setup-envtest if it exists but cannot execute on this platform. -# This can happen when a containerized Make target (e.g. podman/docker build -# with a different GOARCH) writes a linux binary into the shared bin/ directory, -# replacing the native host binary needed by `make test`. -# Checked via exit code 126 specifically (POSIX "found but cannot execute" / -# exec format error) rather than any nonzero exit, since setup-envtest's own -# --help exits 2 by its own convention on a perfectly working binary. +# Uses go-install-tool-versioned (see its doc comment above) instead of a bespoke arch check +# here: an earlier version of this check ran `$(ENVTEST) --help` and treated any nonzero exit +# as "wrong architecture" — but setup-envtest's own --help exits 2 by its own convention even +# on a perfectly healthy binary, which under this Makefile's `.SHELLFLAGS = -ec` aborts the +# whole recipe (confirmed with real GNU Make 4.4.1) rather than being caught, so it was +# unconditionally reinstalling setup-envtest on every single invocation. .PHONY: envtest $(ENVTEST) envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. $(ENVTEST): $(LOCALBIN) - @if [ -f $(ENVTEST) ]; then \ - $(ENVTEST) --help >/dev/null 2>&1; \ - if [ $$? -eq 126 ]; then \ - echo "Removing incompatible setup-envtest binary (wrong architecture)"; \ - rm -f $(ENVTEST); \ - fi; \ - fi - $(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@v0.0.0-20250308055145-5fe7bb3edc86) + $(call go-install-tool-versioned,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@v0.0.0-20250308055145-5fe7bb3edc86,v0.0.0-20250308055145-5fe7bb3edc86) .PHONY: operator-sdk OPERATOR_SDK ?= $(LOCALBIN)/$(BRANCH_VERSION)/operator-sdk @@ -542,27 +534,38 @@ rm -rf $$TMP_DIR ;\ endef # go-install-tool-versioned installs $2 to branch-specific path $1, but only if $1 is missing, -# $1.version doesn't match the pinned version $3, or $1 exists but cannot execute on this -# platform (checked via exit code 126, POSIX "found but cannot execute" / exec format error — -# this can happen when a containerized build with a different GOARCH bind-mounts the host's -# bin/ directory, e.g. `docker run --platform linux/amd64 -v $$PWD:$$PWD ... make manifests`). -# Uses a sidecar marker file for the version check instead of introspecting the binary's own -# --version output, because that output is unreliable for some tools when installed via -# `go install` (e.g. kustomize reports "(devel)" or an unexpanded `$$Format:%H$$` placeholder -# instead of its real version, depending on build-time factors). +# doesn't have the pinned module version $3 embedded in it, or was built for a different +# GOOS/GOARCH than this host. Uses `go version -m` to read the binary's embedded build info +# directly (module version, GOOS, GOARCH) instead of executing it or trusting a sidecar marker +# file — this avoids two real failure modes found in earlier attempts at this check: +# - Introspecting the binary's own --version/--help output is unreliable: some tools report +# a version string that depends on ldflags their own release process sets, which `go +# install` doesn't set (e.g. kustomize reporting "(devel)" or an unexpanded `$$Format:%H$$` +# placeholder), and some tools exit nonzero on --version even when perfectly healthy (e.g. +# kustomize exits 1, setup-envtest's --help exits 2) — so a naive "nonzero exit means +# broken" check is wrong, and worse, a bare failing probe command under `set -e`/`-o +# pipefail` (this Makefile's .SHELLFLAGS, honored by GNU Make 3.82+ — silently ignored by +# the ancient Make 3.81 macOS ships, which is why this went unnoticed locally) aborts the +# entire recipe rather than being caught. Verified directly against real GNU Make 4.4.1: +# the previous exit-code-126 version of this macro reliably crashed `make kustomize` +# with "Error 1" every time the binary already existed. +# - Actually executing the binary to test compatibility (this macro's own earlier approach, +# and the same technique in #2152) can't detect a wrong-arch binary at all in a container +# with qemu-user-static/binfmt_misc registered (common in multi-arch CI/build images): +# the foreign-arch binary runs under emulation and returns its own exit code, not an +# exec-format-error, defeating the whole check silently in exactly the environments where +# it matters most. +# `go version -m` reads the embedded build info without ever executing the binary, sidestepping +# both problems at once. define go-install-tool-versioned -@ARCH_OK=1 ;\ -if [ -f $(1) ]; then \ - $(1) --version >/dev/null 2>&1 ;\ - if [ $$? -eq 126 ]; then ARCH_OK=0 ; fi ;\ -fi ;\ -if [ "$$ARCH_OK" = "1" ] && [ -f $(1) ] && [ -f $(1).version ] && [ "$$(cat $(1).version)" = "$(3)" ]; then \ +@BUILDINFO="$$(go version -m $(1) 2>/dev/null)" || BUILDINFO="" ;\ +MOD_VERSION="$$(printf '%s\n' "$$BUILDINFO" | awk '$$1=="mod"{print $$3; exit}')" ;\ +if [ -n "$$BUILDINFO" ] && [ "$$MOD_VERSION" = "$(3)" ] && printf '%s\n' "$$BUILDINFO" | grep -qF "GOOS=$$(go env GOOS)" && printf '%s\n' "$$BUILDINFO" | grep -qF "GOARCH=$$(go env GOARCH)"; then \ echo "$(notdir $(1)) $(3) is already installed" ;\ else \ - if [ "$$ARCH_OK" = "0" ]; then echo "$(notdir $(1)) exists but cannot execute on this platform, removing and re-downloading" ; fi ;\ set -e ;\ mkdir -p $(dir $(1)) ;\ - rm -f $(1) $(1).version ;\ + rm -f $(1) ;\ TMP_DIR=$$(mktemp -d) ;\ cd $$TMP_DIR ;\ go mod init tmp ;\ @@ -570,7 +573,6 @@ else \ GOBIN=$(dir $(1)) go install -a -mod=mod $(2) ;\ cd - >/dev/null ;\ rm -rf $$TMP_DIR ;\ - echo "$(3)" > $(1).version ;\ fi endef From a87381bb36d7e0d9a885314294950138a5cfd884 Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Wed, 12 Aug 2026 11:58:14 -0400 Subject: [PATCH 5/5] Rewrite comments to describe current design, not review history Both go-install-tool-versioned's doc comment and the envtest section's note narrated the debugging process that led here (earlier attempts, "confirmed with real GNU Make 4.4.1", "the previous exit-code-126 version... reliably crashed", a specific past PR reference) rather than just stating why the current code is shaped this way. Keeps the durable WHY (unreliable tool self-report, the set -e hazard as a standing fact about this Makefile, the qemu/binfmt_misc blind spot) as present-tense design rationale instead. Co-authored-by: Claude Signed-off-by: Tiger Kaovilai --- Makefile | 47 +++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index 0c676dfb4b2..568c9e14a38 100644 --- a/Makefile +++ b/Makefile @@ -316,12 +316,8 @@ $(CONTROLLER_GEN): $(LOCALBIN) fi @ln -sf "$(LOCALBIN)/$(BRANCH_VERSION)/controller-gen" "$(LOCALBIN)/controller-gen" -# Uses go-install-tool-versioned (see its doc comment above) instead of a bespoke arch check -# here: an earlier version of this check ran `$(ENVTEST) --help` and treated any nonzero exit -# as "wrong architecture" — but setup-envtest's own --help exits 2 by its own convention even -# on a perfectly healthy binary, which under this Makefile's `.SHELLFLAGS = -ec` aborts the -# whole recipe (confirmed with real GNU Make 4.4.1) rather than being caught, so it was -# unconditionally reinstalling setup-envtest on every single invocation. +# Uses go-install-tool-versioned (see its doc comment below) for both the version and +# architecture check, rather than a bespoke arch-only check here. .PHONY: envtest $(ENVTEST) envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. $(ENVTEST): $(LOCALBIN) @@ -535,28 +531,23 @@ endef # go-install-tool-versioned installs $2 to branch-specific path $1, but only if $1 is missing, # doesn't have the pinned module version $3 embedded in it, or was built for a different -# GOOS/GOARCH than this host. Uses `go version -m` to read the binary's embedded build info -# directly (module version, GOOS, GOARCH) instead of executing it or trusting a sidecar marker -# file — this avoids two real failure modes found in earlier attempts at this check: -# - Introspecting the binary's own --version/--help output is unreliable: some tools report -# a version string that depends on ldflags their own release process sets, which `go -# install` doesn't set (e.g. kustomize reporting "(devel)" or an unexpanded `$$Format:%H$$` -# placeholder), and some tools exit nonzero on --version even when perfectly healthy (e.g. -# kustomize exits 1, setup-envtest's --help exits 2) — so a naive "nonzero exit means -# broken" check is wrong, and worse, a bare failing probe command under `set -e`/`-o -# pipefail` (this Makefile's .SHELLFLAGS, honored by GNU Make 3.82+ — silently ignored by -# the ancient Make 3.81 macOS ships, which is why this went unnoticed locally) aborts the -# entire recipe rather than being caught. Verified directly against real GNU Make 4.4.1: -# the previous exit-code-126 version of this macro reliably crashed `make kustomize` -# with "Error 1" every time the binary already existed. -# - Actually executing the binary to test compatibility (this macro's own earlier approach, -# and the same technique in #2152) can't detect a wrong-arch binary at all in a container -# with qemu-user-static/binfmt_misc registered (common in multi-arch CI/build images): -# the foreign-arch binary runs under emulation and returns its own exit code, not an -# exec-format-error, defeating the whole check silently in exactly the environments where -# it matters most. -# `go version -m` reads the embedded build info without ever executing the binary, sidestepping -# both problems at once. +# GOOS/GOARCH than this host. Uses `go version -m` to read a binary's embedded build info +# (module version, GOOS, GOARCH) instead of executing it or trusting a sidecar marker file: +# - A binary's own --version/--help output is not a reliable version or health signal. It +# can depend on ldflags a tool's own release process sets, which `go install` doesn't set +# (e.g. kustomize can report "(devel)" or an unexpanded `$$Format:%H$$` placeholder instead +# of its real version), and some tools exit nonzero on --version even when perfectly +# healthy (kustomize exits 1, setup-envtest's --help exits 2) — so "nonzero exit means +# broken" is the wrong signal. It's also dangerous under this Makefile's +# `.SHELLFLAGS = -ec` (enables `set -e`, honored by GNU Make 3.82+ but silently ignored by +# the Make 3.81 macOS ships): a bare probe command that exits nonzero aborts the whole +# recipe unless it's wrapped in an `if`/`||` guard. +# - Executing the binary to test compatibility can't detect a wrong-arch binary at all +# inside a container with qemu-user-static/binfmt_misc registered (common in multi-arch +# CI/build images): the foreign-arch binary runs under emulation and returns its own exit +# code rather than an exec-format-error. +# Reading embedded build info sidesteps both: no execution means no exit-code heuristic to +# get wrong and no qemu blind spot. define go-install-tool-versioned @BUILDINFO="$$(go version -m $(1) 2>/dev/null)" || BUILDINFO="" ;\ MOD_VERSION="$$(printf '%s\n' "$$BUILDINFO" | awk '$$1=="mod"{print $$3; exit}')" ;\