From 3ae6554c2186bb30ca06fba9ed7b96e572fa3532 Mon Sep 17 00:00:00 2001 From: Ahmed Abushagur Date: Tue, 5 May 2026 00:27:08 -0700 Subject: [PATCH] ci(docker): build multi-arch images (amd64 + arm64) (#3392) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci(docker): build multi-arch images (amd64 + arm64) The agent images at ghcr.io/openrouterteam/spawn-:latest were built linux/amd64 only. On Apple Silicon (arm64) hosts running --beta sandbox, OrbStack pulls the amd64 image and runs it under Rosetta. Inside the container, github-auth.sh's `apt-get update` to install gh hangs in emulation — confirmed by `[rosetta] /usr/lib/apt/methods/http` processes sleeping forever. A native arm64 ubuntu:24.04 finishes the same apt-get update + curl install in ~12s; the amd64-emulated run was still stuck after 5+ minutes. Adds docker/setup-qemu-action + docker/setup-buildx-action and sets platforms: linux/amd64,linux/arm64 on the build-push step. Builds will take longer (arm64 layer compiles under QEMU on the amd64 runner), but the resulting multi-arch manifest gives Apple Silicon users native arm64 binaries and unblocks the sandbox flow. All current Dockerfiles (claude, codex, cursor, hermes, junie, kilocode, openclaw, opencode, pi) install via npm or arch-aware curl scripts, so they're already arch-portable. * ci(docker): verify the pushed manifest contains both architectures Post-build step runs `docker buildx imagetools inspect` and greps the manifest for both linux/amd64 and linux/arm64. Catches regressions where setup-qemu/buildx gets dropped or the `platforms:` flag gets lost in a future refactor — silent single-arch publishes would be invisible until an Apple Silicon user hit the Rosetta hang again. One post-build step per matrix entry keeps the check local to the agent that was just pushed. --------- Co-authored-by: Claude --- .github/workflows/docker.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 409a7279..3ea1ea31 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -24,6 +24,10 @@ jobs: steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4 + + - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 + - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: registry: ghcr.io @@ -34,5 +38,23 @@ jobs: with: context: . file: sh/docker/${{ matrix.agent }}.Dockerfile + platforms: linux/amd64,linux/arm64 push: true tags: ghcr.io/openrouterteam/spawn-${{ matrix.agent }}:latest + + # Verify the pushed manifest actually contains both architectures. + # Catches regressions where setup-qemu/buildx gets dropped or the + # platforms flag gets lost in a future refactor. + - name: Verify multi-arch manifest + run: | + set -euo pipefail + image="ghcr.io/openrouterteam/spawn-${{ matrix.agent }}:latest" + echo "Inspecting $image" + manifest="$(docker buildx imagetools inspect "$image")" + echo "$manifest" + for arch in linux/amd64 linux/arm64; do + if ! grep -qF "$arch" <<< "$manifest"; then + echo "::error::$image is missing $arch in the published manifest" + exit 1 + fi + done