Skip to content

ci: split GPU builds per-arch on native runners (fix runner disk exhaustion, keep arm64)#46

Merged
cboettig merged 2 commits into
masterfrom
ci/split-gpu-multiarch-native-runners
Jun 16, 2026
Merged

ci: split GPU builds per-arch on native runners (fix runner disk exhaustion, keep arm64)#46
cboettig merged 2 commits into
masterfrom
ci/split-gpu-multiarch-native-runners

Conversation

@cboettig

Copy link
Copy Markdown
Member

Problem

The GPU image builds run out of disk on the GitHub-hosted runner. build-cuda.yml and build-cuda-spatial.yml build linux/amd64,linux/arm64 in a single job — the arm64 leg under QEMU emulation — so two full image trees of a large CUDA + R + RStudio (+ spatial) stack land on one ~14 GB runner. The minimal rm -rf android dotnet ghc cleanup isn't enough, and the CUDA-Spatial build fails.

Approach (keep arm64 — don't drop it)

arm64 is a first-class target here (NVIDIA Spark / Grace, Apple Silicon users). Rather than drop it, split the multi-arch build so each architecture builds on its own native runner:

  • Matrix build job: linux/amd64 on ubuntu-latest, linux/arm64 on ubuntu-24.04-arm (native — no QEMU, faster, and each runner only holds one arch → fits disk). Each pushes by digest to GHCR.
  • Merge job: docker buildx imagetools create assembles a multi-arch manifest per tag on GHCR, then mirrors each tag to Docker Hub by copying the GHCR manifest. No leftover per-arch tags in the registry; :latest et al. stay multi-arch.

Also bumps action versions (build-push-action@v6, login-action@v3, checkout@v4) and adds CodeQL to the disk-free step.

Validation needed before merge

Workflows can only be fully verified by running. Worth confirming on a CI run:

  • ubuntu-24.04-arm hosted runners are enabled for the org (free for public repos; minutes otherwise).
  • imagetools create assembles + mirrors all tags (base image fans out to latest, cuda13.0-py3.12-rapids25.12, cuda13.0-py3.12, cuda13.0).
  • Both arches land in the final manifest (docker buildx imagetools inspect).

Same per-arch split could be applied to the CPU workflows (build-ml*.yml) later to cut their ~1h QEMU build time — left out here to keep this focused on the failing GPU builds.

…haustion

The single-runner amd64+arm64 CUDA builds (arm64 under QEMU) ran out of
disk on the large CUDA image. Build each arch on its own native runner
(amd64 on ubuntu-latest, arm64 on ubuntu-24.04-arm -- no QEMU), push by
digest to GHCR, then assemble one multi-arch manifest per tag and mirror
it to Docker Hub. Keeps arm64 a first-class target (NVIDIA Spark, Apple
Silicon) instead of dropping it.

Applies to build-cuda.yml and build-cuda-spatial.yml.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Replace the cross-registry Docker Hub copy (400 Bad Request) with the
pattern validated on build-ml: push each per-arch image by digest to both
registries, record each registry's own digest, assemble the multi-arch
manifest natively in each. Applies to build-cuda.yml and
build-cuda-spatial.yml.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@cboettig cboettig merged commit 49e2c38 into master Jun 16, 2026
8 of 9 checks passed
@cboettig cboettig deleted the ci/split-gpu-multiarch-native-runners branch June 16, 2026 04:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant