ci: catch cross-platform build breaks before release#433
Conversation
CI builds one platform (linux/amd64) while release.yml ships six. The repo has platform-gated source - shell_windows.go, procattr_windows.go and their _unix twins - that CI never compiles, so a signature change to shellCommand or configureProcessGroup compiles green on main and breaks at tag time, after the tag is public. Add a cross-compile matrix job covering the five targets the test job does not, mirroring the shape release.yml:11-29 already runs on this same runner pool. fail-fast: false so a failure names the target. The job trusts the workspace the same way the test job does. The container runs as root over a checkout owned by another uid, so git reports dubious ownership and Go's VCS stamping - which runs when building main packages - fails the build with "error obtaining VCS status: exit status 128". Marking the checkout safe keeps stamping on and consistent with the test job and the release builds, rather than papering over it with -buildvcs=false. Also add two cheap gates the repo lacked: gofmt -s drift (make fmt rewrites and can never fail CI) and go mod tidy drift (make check mutates, so it cannot gate either). Both print the remedy. All six targets build clean today - this is a missing guard, not a fix.
|
🔍 OpenCodeReview found 2 issue(s) in this PR.
|
| include: | ||
| - {goos: linux, goarch: arm64} | ||
| - {goos: darwin, goarch: amd64} | ||
| - {goos: darwin, goarch: arm64} | ||
| - {goos: windows, goarch: amd64} | ||
| - {goos: windows, goarch: arm64} |
There was a problem hiding this comment.
The cross-compile matrix is missing linux/amd64. While the test job builds for the native platform (presumably linux/amd64), having it in the cross-compile matrix ensures consistent coverage and makes the matrix self-contained. If the intent is to rely on the test job for linux/amd64, consider adding a comment explaining why it's excluded here.
| - name: Build ${{ matrix.goos }}/${{ matrix.goarch }} | ||
| env: | ||
| GOOS: ${{ matrix.goos }} | ||
| GOARCH: ${{ matrix.goarch }} | ||
| CGO_ENABLED: '0' | ||
| run: go build -o /dev/null ./... |
There was a problem hiding this comment.
The cross-compile job runs go build which will download dependencies each time on self-hosted runners. Consider adding Go module caching (e.g., using actions/cache for the Go module cache directory) to speed up builds and reduce network usage, similar to what you might want for the test job as well.
…ut (#439) - Change Makefile fmt/check targets from `go fmt` to `gofmt -s -w .` to match the CI gate introduced in #433, preventing drift where local `make fmt` passes but CI fails on simplification opportunities. - Reduce cross-compile job timeout from 20 to 10 minutes, since each leg completes in ~16 seconds on self-hosted runners.
Description
CI builds one platform.
ci.yml:52isgo build -o /dev/null ./cmd/opencodereviewinsidecontainer: golang:1.26.5, i.e. linux/amd64.release.yml:15-29cross-compiles six, and onlyfires on
push: tags: ['v*'].That gap has teeth because the repo carries platform-gated source CI never compiles:
A signature change to
shellCommandorconfigureProcessGroupcompiles green onmainandbreaks at tag time, after the tag is already public. All six targets build clean today, so this
is a missing guard rather than a live bug.
This adds a
cross-compilematrix job covering the five targetstestdoes not.linux/amd64is excluded because
vetandtest -racealready compile all 23 packages there.Verification
A demonstration of the gap. Appending
var _ = thisSymbolDoesNotExisttoshell_windows.go:go build -o /dev/null ./cmd/opencodereview— today'sBuildstepgo build -o /dev/null ./...— linux/amd64, whole treego vet ./...GOOS=windows GOARCH=amd64 go build ./...— new legGOOS=darwin GOARCH=arm64 go build ./...— new legThe first three rows are the argument: a break that ships broken binaries is invisible to every
check this repo runs today.
The job needs the same
Trust workspacestep astest:go buildstamps VCS metadata into mainpackages, and git refuses a dubiously-owned checkout with
error obtaining VCS status: exit status 128. I did not reach for-buildvcs=false, since the repo already solves this the other way andmatching it keeps stamping consistent with the release builds.
On cost, this PR's own checks answer it: the five legs ran on your
self-hostedpool in15-16 seconds each, in parallel. That is cheaper than
release.yml:11-29, which already runsa near-identical 6-way matrix on the same pool at roughly 35s per leg.
Also in this PR: gofmt and go mod tidy gates
Two steps added to the existing
testjob inci.yml. Both are gates the repo cannot currentlyenforce, because the Makefile targets mutate rather than fail:
gofmtdrift. CI runsgo vetonly;make fmtrewrites files and never fails.go mod tidydrift. No check exists.Makefile:67runs tidy but mutates.Both print their remedy via
::error::so it lands as a PR annotation. I falsified both ratherthan trusting a clean tree: an unformatted file trips the first, and importing
github.com/atotto/clipboard(currently indirect) forces tidy to promote it and trips the second.gofmt -s -l .is empty today, so-sadds no churn.Limitations
I could not run the job on
self-hostedrunners before opening this, since my fork has none, soI approximated by building in the same image as root over a foreign-owned checkout — which is
what caught the VCS-stamping failure. That gap is now closed: the checks on this PR are the job's
first real execution, and all five legs pass.
The tidy gate reaches
proxy.golang.org, so a proxy outage turns a green PR red.ci.yml:33already has that property, so it adds no new class of failure.
timeout-minutes: 20on the newjob is a guess rather than a measurement.
One divergence worth naming: the gate uses
gofmt -sbutMakefile:61runs$(GO) fmt, whichhas no
-s. They agree on today's tree. I left the Makefile alone deliberately.Type of Change
How Has This Been Tested?
Windows legs failed and named the file and line
go vet ./...exits 1 on a non-cmd break)EXIT=1on VCS stamping withoutTrust workspace,EXIT=0with itGOCACHE— all clean todayactionlintv1.7.12 — exit 0cross-compilelegs pass on this PR's own checks, on the realself-hostedpoolChecklist
AI assistance: Claude Code helped research and verify this change. I reviewed the full diff
and take responsibility for it.