From 5a3798190eb690b4ccbd592d838901ca53c853f4 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Tue, 29 Sep 2026 23:43:30 -0400 Subject: [PATCH] Refresh the toolchain images' golang pin to 1.26.6 and gate it in CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit go.mod's `go` directive moved to 1.26.6 without the pinned golang digest in images/toolchain-go and images/toolchain-claude moving with it. Under the golang image's GOTOOLCHAIN=local that is fatal — `go mod download` in toolchain-claude's shim stage refuses to run — so `mage desktop:devapp` broke with every test suite green, because no suite runs a docker build. - Repin both Dockerfiles to golang:1.26.6-bookworm (still bookworm: the toolchain payloads resolve libc from the sandbox rootfs) and bump toolchain-go's goprobe module directive, which exists to prove the shipped toolchain can build a module declaring the repo's directive. - Add `mage build:toolchains`: builds every apimage.Toolchains overlay for the docker daemon's native platform, exporting nothing — a build check cheap enough for CI. New toolchain-images CI job runs it. - Refresh config/toolchains/go.yaml's measured-size comment (306964 KB on 1.26.6; the sizeBytes headroom absorbs it, as designed). --- .github/workflows/ci.yaml | 20 +++++++++++++++++ config/toolchains/go.yaml | 2 +- images/toolchain-claude/Dockerfile | 8 +++---- images/toolchain-go/Dockerfile | 12 +++++----- magefiles/magefile.go | 35 ++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e480e5ec..257c6dd5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -100,3 +100,23 @@ jobs: go-version-file: go.mod - run: go install github.com/magefile/mage@v1.17.2 && echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" - run: mage fmt:check + + # Builds the toolchain overlay images (go, node, claude) for the runner's + # native platform. This is the only job that runs a docker build, and it + # exists because the test suites cannot see docker-build-only breakage: + # toolchain-go and toolchain-claude pin a golang digest that must stay >= + # go.mod's `go` directive, and a go.mod bump without a pin refresh broke + # `mage desktop:devapp` once with every suite green. See build:toolchains' + # doc comment for why native-platform coverage suffices for that invariant. + toolchain-images: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v6 + - name: Free disk space + run: .github/free-disk-space.sh + - uses: actions/setup-go@v7 + with: + go-version-file: go.mod + - run: go install github.com/magefile/mage@v1.17.2 && echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" + - run: mage build:toolchains diff --git a/config/toolchains/go.yaml b/config/toolchains/go.yaml index 292aa5d1..d8e483ec 100644 --- a/config/toolchains/go.yaml +++ b/config/toolchains/go.yaml @@ -32,7 +32,7 @@ spec: # SizeBytes MUST be the on-disk usage (du -sk * 1024), NOT apparent size # (du -sb). The kubelet enforces emptyDir SizeLimit against allocated blocks. # Measured via: docker run --rm --entrypoint /bin/sh ap-toolchain-go:dev -c - # 'du -sk /opt/ap-toolchains/go' → 306584 KB = 313,942,016 bytes on Go 1.26.1. + # 'du -sk /opt/ap-toolchains/go' → 306964 KB = 314,331,136 bytes on Go 1.26.6. # Held at 350000000 (SizeLimit 385,000,000, ~71MB spare) so a routine patch # bump doesn't require re-tuning; over-estimating only inflates # ephemeral-storage, while under-estimating evicts the pod mid-copy. diff --git a/images/toolchain-claude/Dockerfile b/images/toolchain-claude/Dockerfile index ebaf2714..a6f2f1b3 100644 --- a/images/toolchain-claude/Dockerfile +++ b/images/toolchain-claude/Dockerfile @@ -50,12 +50,12 @@ # comment for why: avoids paying qemu emulation for the compile itself). # # Pinned digest, same pin as images/toolchain-go/Dockerfile's builder stage — -# this repo's go.mod declares `go 1.26.1`, and reusing an already-verified +# this repo's go.mod declares `go 1.26.6`, and reusing an already-verified # digest here avoids fetching a second, unverified one for a pin whose only # real requirement is "new enough to compile the module". Refresh with: -# docker pull golang:1.26.1-bookworm -# docker image inspect golang:1.26.1-bookworm --format '{{index .RepoDigests 0}}' -FROM --platform=$BUILDPLATFORM golang@sha256:ab3d6955bbc813a0f3fdf220c1d817dd89c0b3f283777db8ece4a32fe7858edd AS shim +# docker pull golang:1.26.6-bookworm +# docker image inspect golang:1.26.6-bookworm --format '{{index .RepoDigests 0}}' +FROM --platform=$BUILDPLATFORM golang@sha256:116d58cbd88c1297624acc6e967a060012422bacf9930927e23fb719189c6f36 AS shim ARG TARGETARCH WORKDIR /src ENV GOFLAGS=-trimpath diff --git a/images/toolchain-go/Dockerfile b/images/toolchain-go/Dockerfile index 09200f28..76f801c7 100644 --- a/images/toolchain-go/Dockerfile +++ b/images/toolchain-go/Dockerfile @@ -11,17 +11,17 @@ # `GLIBC_2.xx not found` at exec time, far from its cause. # # The Go version must be >= the highest `go` directive of any repo an agent is -# expected to build. Both this repo and the first consumer declare `go 1.26.1`, +# expected to build. Both this repo and the first consumer declare `go 1.26.6`, # and GOTOOLCHAIN=local (below, and on the SpiceboxToolchain CR) forbids the # `go` command from downloading a newer toolchain — so an overlay older than the # module's `go` directive fails the build outright: -# go: go.mod requires go >= 1.26.1 (running go 1.24.5; GOTOOLCHAIN=local) +# go: go.mod requires go >= 1.26.6 (running go 1.26.1; GOTOOLCHAIN=local) # That is the intended, legible failure. Keep this ahead of the repos, not behind. # # Pinned digest. Refresh with: -# docker pull golang:1.26.1-bookworm -# docker image inspect golang:1.26.1-bookworm --format '{{index .RepoDigests 0}}' -FROM golang@sha256:ab3d6955bbc813a0f3fdf220c1d817dd89c0b3f283777db8ece4a32fe7858edd AS build +# docker pull golang:1.26.6-bookworm +# docker image inspect golang:1.26.6-bookworm --format '{{index .RepoDigests 0}}' +FROM golang@sha256:116d58cbd88c1297624acc6e967a060012422bacf9930927e23fb719189c6f36 AS build ENV TC=/opt/ap-toolchains/go ENV GOTOOLCHAIN=local @@ -43,7 +43,7 @@ RUN GOROOT="${TC}" "${TC}/bin/go" version && "${TC}/tools/bin/gopls" version # thing cannot. Under GOTOOLCHAIN=local an older Go fails here at BUILD time # instead of failing an agent's `go build` at session time. RUN mkdir -p /tmp/goprobe && cd /tmp/goprobe \ - && printf 'module goprobe\n\ngo 1.26.1\n' > go.mod \ + && printf 'module goprobe\n\ngo 1.26.6\n' > go.mod \ && printf 'package main\n\nfunc main() {}\n' > main.go \ && GOROOT="${TC}" GOTOOLCHAIN=local "${TC}/bin/go" build ./... \ && cd / && rm -rf /tmp/goprobe diff --git a/magefiles/magefile.go b/magefiles/magefile.go index 208e39cd..fe6faa6c 100644 --- a/magefiles/magefile.go +++ b/magefiles/magefile.go @@ -22,6 +22,7 @@ import ( "github.com/authzed/openagentprimitives/pkg/gen/auditgen" "github.com/authzed/openagentprimitives/pkg/gen/claudeexec" + "github.com/authzed/openagentprimitives/pkg/platform/apimage" "github.com/authzed/openagentprimitives/test/envtestreap" "github.com/authzed/openagentprimitives/test/suitelock" "github.com/authzed/openagentprimitives/test/testparallel" @@ -107,6 +108,40 @@ func (Build) Oap() error { return sh.RunV("go", "build", "-o", "bin/oap", "./cmd/oap") } +// Toolchains builds every toolchain overlay image (apimage.Toolchains) for the +// docker daemon's NATIVE platform, exporting nothing (--output=type=cacheonly, +// same shape as desktop:images' GoBuilder prebuild). It exists as a build +// CHECK cheap enough for CI, not a bake: toolchain-go and toolchain-claude pin +// a golang digest that must stay >= this repo's go.mod `go` directive, and +// under GOTOOLCHAIN=local a stale pin fails these builds outright (toolchain- +// go's goprobe stage; toolchain-claude's shim stage compiling this module) — +// a drift `mage test:*` can never see, since it only surfaces inside a docker +// build. Shipped `mage desktop:devapp` broken once; this target is the gate. +// +// Native platform, not desktopPlatform: the pinned digest is one multi-arch +// manifest list carrying a single Go version, so the invariant is arch- +// independent, and building natively (amd64 in CI, arm64 on Apple Silicon) +// avoids paying qemu emulation for payload stages only the real desktop bake +// needs as arm64. +func (Build) Toolchains() error { + if err := desktopRequireTools("docker"); err != nil { + return err + } + for _, im := range apimage.Toolchains { + fmt.Printf("==> build:toolchains: docker buildx build %s (native platform, dockerfile=%q, context=%q)\n", + im.Name, im.Dockerfile, im.Context) + args := []string{"buildx", "build", "--output=type=cacheonly"} + if im.Dockerfile != "" { + args = append(args, "-f", im.Dockerfile) + } + args = append(args, im.Context) + if err := sh.RunV("docker", args...); err != nil { + return fmt.Errorf("build:toolchains: build %s: %w", im.Name, err) + } + } + return nil +} + // Web builds / serves / drift-checks the browser UI bundles under web/. type Web mg.Namespace