Test build containers
Builds the management node image on a pull request that touches it, and on the merge queue. Paths-filtered to containers/**, .goreleaser.yaml, the collection, cmd/**, internal/zarfmod/**, and the workflow itself.
This is a test rather than a packaging check. The smoke-check RUN block in containers/ansible/Dockerfile is the only place in the tree where the collection, the installed module files, a zarf and an ansible-core exist at once, so it is the only place the argv dispatch contract is checked end to end: every module file name must be a link to the same binary, a module file invoked under a zarf_ name it does not answer as must exit non-zero, one given parameters it cannot read must still write one JSON object and exit 0, check mode must report the task as skipped, a deploy against a bad kubeconfig must come back with failed and a zarf.exitCode, and zarf_kubectl must return the vendored kubectl’s output in zarf.output. Each of those fails the image build.
The Dockerfile cannot be built with a plain docker build: it COPYs the nfpm-produced *.rpm out of a ${TARGETPLATFORM} directory that only GoReleaser stages. So the job runs goreleaser release --snapshot --clean --skip=sign,sbom. --snapshot skips publish, validate and announce – nfpm still builds the rpm and the dockers_v2 pipe still runs buildx build – which is why the job needs no registry login and no packages: write. --skip=sign,sbom avoids failing on the cosign key the workflow has no reason to hold.
QEMU and Buildx are installed because the pipe builds linux/amd64 and linux/arm64 in one pass, and ansible-core because GoReleaser’s before hook shells out to ansible-galaxy for the collection tarball.
The job sets GOTMPDIR, and has to. The snapshot links zarf’s dependency tree into a binary of around 269MB and builds it for amd64, arm64 and riscv64 at once, which puts more than 8GB of scratch in the Go compiler’s temporary directory – and /tmp on the hosted runner image is a 7.9GB tmpfs rather than part of the 145GB root filesystem, so the build dies reporting disk quota exceeded against /tmp/go-build while df reports around 88GB free on /. That is the trap: the message names a quota, the obvious reading is the disk, and freeing disk space changes nothing. Pointing GOTMPDIR at $RUNNER_TEMP moves the scratch onto the work volume where the free space is – exported through $GITHUB_ENV, because the runner context a job-level env: block would need is not available there and a workflow that references it does not load. The step’s df covers every mount rather than / alone, so the next failure of this kind names the filesystem that ran out. release.yaml builds the same artifacts for real and does the same thing for the same reason.
scan-lint.yaml runs hadolint over the same Dockerfile. That checks syntax and never builds, so a base image bump that breaks the build is caught here and nowhere else.