STAC-25498 Add the arm64 build lane to the GitHub Actions pipeline - #451
Conversation
GitLab fans .gitlab-ci-agent.yml out twice from .gitlab-ci.yml (agent-x86 / agent-arm) with per-arch variables. Only the amd64 half had been ported. The arm64-xlarge-public ARC scale set landing on argocd-apps main (STAC-25492) removes the blocker, so the fan-out becomes an `arch` matrix here. Make the Go dependency cache image arch-aware. The metadata script hashed only the module graph plus BASE_IMAGE_TAG, and both datadog_build images share tag 7af9194f -- so the two arches would have computed the SAME cache tag and one arch's image would have satisfied the other's existence check. Fold the base image NAME into the hash and the arch into the tag, making that collision impossible by construction. godeps-cache.yml takes a required `arch` input, selects datadog_build_linux_x64 vs datadog_build_linux_arm64, and builds each arch NATIVELY on a runner of that architecture -- QEMU/binfmt would make the Dockerfile's module extraction unusably slow. The two arches are independent images rather than a multi-arch manifest: consumers reference them from `container.image`, which resolves against the runner's own architecture anyway. The metadata job stays on amd64, since hashing files and calling `docker manifest inspect` are arch-independent. build-binaries.yml and build-deb.yml matrix over arch, with `fail-fast: false` so an arm64 regression cannot abort the amd64 leg that has been green for weeks. Matrix legs upload artifacts concurrently and actions/upload-artifact v4 rejects a second upload to an existing name, so the cluster-agent and DEB artifacts are now per-arch. Cache-image stagger (STAC-25494) keeps one designated builder per arch: lint-and-unit-tests owns amd64, build-binaries owns arm64, everyone else waits. Both arches run on pull requests, matching GitLab, where agent-x86 and agent-arm shared the same commit-or-MR rule. Of the GitLab per-arch variables only ARCH carries over; see the build-deb.yml header for why PACKAGE_ARCH / DD_PKG_ARCH / STS_PKG_ARCH are not needed and why DOCKER_ARCH (aarch64, not arm64) matters only to the publishing lane. Lint and unit tests deliberately gain no arm64 lane: each suite runs once on the path to master. Validated with actionlint (only the expected unknown-self-hosted-label notes), zizmor (no findings) and shellcheck (clean). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
First CI run — arm64 lane is live and green
What that confirms end to end:
Both arches rebuilt their cache image on this run, as expected — the tag scheme changed (base image name in the hash, arch in the tag), so no pre-existing image matched. One-time cost. Still running: |
…into the arm64 lane
Merging STAC-25461 (PR #449) into this branch produced no textual conflict but a broken workflow: the new `cerberus-notify` job in build-binaries.yml and build-deb.yml declares `needs: godeps-cache`, and this branch splits that job into godeps-cache-amd64 / godeps-cache-arm64. Both files failed actionlint with "needs job godeps-cache which does not exist in this workflow". List both per-arch jobs instead. That also preserves the intent recorded in the STAC-25461 comment -- `needs` lists every job, not just the leaves, so an early cache failure that skips its dependents is still reported to Slack. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rebased on the integration branch — and it needed a fixMerged #449 added a terminal needs:
- godeps-cacheThis PR splits that job into Fixed in 41f575b by listing both per-arch jobs. That also preserves #449's stated intent — Worth noting as a merge-order hazard for the remaining migration PRs: a semantically clean Side effect: arm64 now covers the release branch too#449 also added Re-validated after the merge: |
Jira: STAC-25498 (sub-task of STAC-25142)
Ports the GitLab
agent-armlane. GitLab fans.gitlab-ci-agent.ymlout twice from.gitlab-ci.yml(agent-x86/agent-arm) with per-arch variables; only the amd64 half had been ported. Thearm64-xlarge-publicARC scale set landing onargocd-appsmain (STAC-25492) removes the blocker, so that fan-out becomes anarchmatrix.This is a hard prerequisite for the arm64 half of STAC-25457 —
merge_docker_manifest_*cannot build a multi-arch manifest from one architecture.The cache-collision bug this had to fix first
agent-godeps-cache-metadata.shhashed the module graph plusBASE_IMAGE_TAG. Bothdatadog_build_linux_x64anddatadog_build_linux_arm64carry the same tag7af9194f, so the two arches would have computed an identical cache tag — and one arch's image would have silently satisfied the other's existence check, handing arm64 jobs an amd64 module cache.Fixed by folding the base image name into the hash and the arch into the tag (
godeps-<arch>-<hash>), which makes the collision impossible by construction and keeps the arch readable off the ref.What changed
.github/scripts/agent-godeps-cache-metadata.shBASE_IMAGE_NAME+ARCH; hashesbase:<name>:<tag>; tag isgodeps-<arch>-<hash>.github/workflows/godeps-cache.ymlarchinput; selects the base image; builds natively per arch.github/workflows/build-binaries.ymlarchmatrix onbuild-agent,build-cluster-agent,build-cluster-agent-image; per-arch artifacts.github/workflows/build-deb.ymlarchmatrix onbuild-deb,test-deb-renaming,build-agent-image; per-arch artifacts.github/workflows/lint-and-unit-tests.ymlarch: amd64on its cache call (no arm64 lane, by design)Design notes
container.image, which resolves against the runner's own architecture anyway.fail-fast: falseeverywhere. An arm64 regression must not abort the amd64 leg; amd64 has been green for weeks and during arm64 bring-up its result is the signal.actions/upload-artifactv4 rejects a second upload to an existing name, so a shared name would have failed the arm64 leg outright.lint-and-unit-testsowns amd64 (delay 0),build-binariesowns arm64 (delay 0); every other caller waits 900s.test-deb-renamingstays on amd64 for both legs.ar+ grep read the arm64.debfine, so burning a scarce arm64 XL runner on a grep would buy nothing.agent-x86andagent-armshared the same commit-or-MR rule.ARCHcarries over.PKG_ARCH_SUFFIXis the same value and had exactly one use (selecting the built.deb).PACKAGE_ARCH/DD_PKG_ARCH/STS_PKG_ARCHare set bybuild_debbut nothing in the StackState omnibus path reads them, and omnibus derives the package architecture from the native build host.DOCKER_ARCHis deliberately not ported — its only consumer ispublish_image.sh. Note for STAC-25457: on arm64 it isaarch64, notarm64, so it cannot simply be aliased tomatrix.arch.Not in scope
Lint and unit tests gain no arm64 lane — GitLab ran them in both child pipelines, but the directive is to run each suite once on the path to master.
Validation
actionlintv1.7.7 — only the expected unknown-self-hosted-label notes (docker-public,xlarge-public,arm64-xlarge-public); no expression,needsor matrix errorszizmorv1.28.0 — no findingsshellcheck— cleanargocd-appsmain:runnerScaleSetName: arm64-xlarge-public,runnerGroup: public,nodeSelector kubernetes.io/arch: arm64, DinD sidecar present