Repository navigation
chore(ci): build and test every arm64 target - #682
Merged
Merged
Conversation
added 3 commits
August 25, 2026 14:15
Two gaps, both on the push path. Nothing in CI compiled for arm64. quality-gate ran `make build` (host only) and `make build-all`, which sweeps GOOS at a fixed GOARCH, while goreleaser ships linux, darwin, and windows across amd64 and arm64. An arm64-only break therefore surfaced at release rather than at review. ALL_PLATFORMS already named all six and `make build PLATFORM=all` already produced them; CI simply never asked. The codebase is pure Go — zero `import "C"` — so one host links the whole matrix with GOOS/GOARCH alone, ~41s against ~13s host-only. build-all is dropped rather than kept. `build PLATFORM=all` covers the 120 of 122 packages reachable from ./cmd across all six pairs instead of three GOOS at the host's arch, and vet-all still type-checks all 122 including test files, which `go build ./...` never did. The two packages outside cmd's reach, pkg/op/provider/elevator and pkg/op/server, keep their per-GOOS coverage. The Makefile target remains for local use. Linux and Windows arm64 were never executed. Both matrices ran ubuntu-latest, macos-latest, and windows-latest — three of the five runnable pairs; darwin/arm64 was always covered because macos-latest is Apple Silicon. arm64 standard runners reached GA for private repositories on 2026-01-29 and are free-tier eligible, so the blocker present when platform-test-matrix.md was written is gone. Both jobs now run five legs. PLATFORM gains `host` beside `all`. The name is `host` rather than `current` or `local` because CROSS is already defined here as target != host, so PLATFORM=host names the selection that makes CROSS empty — and every HOST_ variable in this file comes from Go's own GOHOSTOS/GOHOSTARCH. PLATFORM stays empty by default: a non-empty default is never overridden by a target, so dist's default would become unreachable and releases would go host-only without announcing it. The defaults moved to the call sites as keywords. Three constraints are recorded where they bind rather than in the plan alone. There is no -latest alias for arm64, so ubuntu-24.04-arm is pinned — it is what ubuntu-latest resolves to today, and ubuntu-26.04-arm is a preview image; matching versions means the new leg varies architecture alone. Go's race detector does not support windows/arm64, so that leg runs `make test` — the full suite, without race detection. And windows-latest is Windows Server 2025 while windows-11-arm is a client OS, an asymmetry the platform imposes because no Windows Server arm64 runner exists. platform-test-matrix.md is updated in step: its phase 4 ruleset change must now name five contexts per job. Requiring three of five would leave both arm64 legs advisory while the rest gate. Closes #681
The first run of the five-leg matrix reported contexts like
`test (windows-11-arm, false)`. Without an explicit job name GitHub composes
the context from every matrix value, so the runner image and the race flag
both leaked into a string the ruleset has to match exactly — and adding any
further matrix key would rename all five contexts at once.
Both jobs now set `name: <job> (${{ matrix.platform }})` and carry a platform
key, so the context is the platform descriptor and nothing else:
test (darwin-arm64), test (linux-amd64), test (linux-arm64),
test (windows-amd64), test (windows-arm64), and the same five for scenario.
These match ALL_PLATFORMS and the build/<goos>-<goarch> directories, which is
the vocabulary the rest of the build already speaks. The runner label stays in
runs-on where it belongs: whether linux/arm64 comes from ubuntu-24.04-arm or a
later image is not something a required-check name should encode. It also
hides the one asymmetry the platform forces on us — windows-latest is Windows
Server 2025 while windows-11-arm is a client OS — behind a descriptor that
says only what the binary targets.
platform-test-matrix.md phase 4 carried the wrong strings, written before the
first run showed what GitHub actually emits. Corrected, with the mechanism
recorded so the next person does not rediscover it from a blocked merge: a
required context whose name never arrives blocks every merge rather than none.
Both windows-arm64 legs failed, and all four failures shared one cause:
git [init --quiet --initial-branch=main]: exit status 128
fatal: unable to access 'NUL': Invalid argument
TestRepo_Add_ClonesURL_DefaultHome, TestRepo_Add_ClonesURL_PositionalDestination,
TestWritDeployScenario_Harness, and TestWritDeployScenario_Deploy each die at the
same line: two test helpers pointed git's global and system config at
os.DevNull, which is "NUL" on Windows, and the git build on the windows-11-arm
runner image refuses to open it as a config path.
The identical command succeeds on windows-latest, so this is a property of that
image's git rather than of the architecture — which is exactly why it stayed
hidden until windows/arm64 joined the matrix, and why it is worth having found.
What the helpers actually want is a config git can open and find nothing in.
The null device was a convenient stand-in for that, and it is the one form
whose semantics vary by platform and by git build. An empty regular file in the
test's temp directory is the same thing with no special behavior anywhere.
Both call sites now share an isolatedGitEnv helper carrying the explanation, so
the next person reaching for os.DevNull sees why it is not used here.
Rejected alternatives: a nonexistent config path works today but depends on how
each git version treats an unreadable config; `git -c` overrides individual keys
without stopping the global config being read, which is whack-a-mole against
core.hooksPath; and setting HOME covers global config but not GIT_CONFIG_SYSTEM.
Verified on darwin/arm64: TestWritDeployScenario_Harness, _Deploy,
TestSelfInstallScenario (lore, star, writ), and TestRepo_Add_ClonesURL_* all
pass; gofmt and go vet clean. That proves the change breaks nothing here. It
cannot prove it fixes windows/arm64 — only that leg can, which is why this
commit is pushed rather than merged.
David-Noble-at-work
pushed a commit
that referenced
this pull request
Aug 26, 2026
One conflict, in pkg/op/provider/function/provider.go. Both sides were right about different things: develop carried #676's sealing of function.Resource, and this branch had added +devlore:claim=deterministic to Call afterward. The claim is kept; develop had nothing at that position, having been squashed before it existed. Everything else auto-merged, including the two files most likely to break quietly: .github/workflows/ci.yaml #682's arm64 build-and-test matrix alongside this branch's go-version 1.27 and golangci-lint v2.13.1. All three go-version sites read 1.27, including the matrix jobs #682 added. Makefile #682's build-system work alongside this branch's GOLANGCI_LINT_VERSION pin, the golangci-lint-pinned prerequisite, and lint routing through star. Verified rather than assumed: make check exits 0 -- 104 packages, no lint issues -- and every claim still holds against host, darwin, linux, and windows build tags.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #681
Two build/CI chores. No production code changes.
1. Nothing on the push path compiled for arm64
quality-gateranmake build(host only) plusmake build-all, which sweeps GOOS at afixed GOARCH. goreleaser ships all six pairs, so an arm64-only break surfaced at release
rather than at review.
ALL_PLATFORMSalready listed all six andmake build PLATFORM=allalready produced them —CI never asked. Now it does.
build-allis dropped, and I checked what that costs.build PLATFORM=alllinks the120 of 122 packages reachable from
./cmd; the two outside its reach arepkg/op/provider/elevatorandpkg/op/server. Butvet-allstays and type-checks all 122per GOOS including test files, which
go build ./...never did — so those two keep theircoverage, and
build-allwas largely redundant with the step below it. The Makefile targetremains for local use.
2. Linux and Windows arm64 were never executed
macos-latestmake test-raceubuntu-latestmake test-raceubuntu-24.04-armmake test-racewindows-latestmake test-racewindows-11-armmake testdarwin/arm64 was covered all along —
macos-latestis Apple Silicon. The gap was Linux andWindows arm64, unblocked by arm64 runners reaching GA for private repositories on 2026-01-29.
PLATFORM=hostNew keyword beside
all. Namedhostrather thancurrentorlocalbecauseCROSSisalready defined in this Makefile as target ≠ host — so
PLATFORM=hostnames the oneselection that makes
CROSSempty, and everyHOST_variable here comes from Go'sGOHOSTOS/GOHOSTARCH.PLATFORMstays empty by default.PLATFORM ?= hostwould have been the obvious way towrite it and would have silently broken
dist: a non-empty default is never overridden by atarget, so
dist's default becomes unreachable and releases go host-only without saying so.The defaults now live at the call sites as keywords —
$(call select,host)for build,$(call select,all)for dist.Three constraints, recorded where they bind
-latestalias exists for arm64.ubuntu-24.04-armis pinned becauseubuntu-lateststill resolves to Ubuntu 24.04 and
ubuntu-26.04-armis a preview image. Matchingversions means the arm64 leg varies architecture alone; vary the OS release too and a failure
has two candidate causes.
make test— the fullsuite, only race detection absent.
linux/arm64is supported and runs-raceunchanged.windows-latestis Windows Server 2025,windows-11-armis a client OS, and no Windows Server arm64 runner exists. The platform'sasymmetry, not a choice made here — worth knowing before a Windows leg diverges.
platform-test-matrix.mdupdated in stepIts phase 4 (the ruleset change on
12426847) must now require five contexts per job, notthree, and the five names are written out there. Requiring three of five would leave both arm64
legs advisory while the rest gate — a gate that looks complete and is not.
Added a warning that wasn't there: the
testjob now usesmatrix.include, and GitHub composescheck names from matrix values. A required context whose name does not match exactly never
arrives, which blocks every merge rather than none. Verify the strings against a real run
before writing them into the ruleset.
Historical "three" references in that plan are deliberately untouched — the three
[build failed]packages, the three uncompilable test files, the three-GOOS analysis sweep. Those are findings and
a still-correct GOOS count, not stale platform arithmetic.
Test plan
build→darwin/arm64;build PLATFORM=host→darwin/arm64;build PLATFORM=linux/arm64→linux/arm64;build PLATFORM=all→ allsix;
dist→ all six;dist PLATFORM=host→darwin/arm64ci.yamlparses; five legs on both jobs;raceflag drives the two conditional stepsbuild-allaccounted for (120/122 +vet-allover 122)test (ubuntu-24.04-arm)andtest (windows-11-arm)have never run. Per the plan's phase 3, their first results aretriage data — failures there are findings to file, not automatically blockers.
windows-11-armsymlink behavior unverified. platform-test-matrix flags symlinks as theWindows risk; an arm64 image is a fresh instance of that question.