STAC-25142 Add omnibus DEB build and container image workflows - #446
Merged
LouisParkin merged 6 commits intoJul 30, 2026
Merged
Conversation
… STAC-25142-agent-omnibus-deb
LouisParkin
merged commit Jul 30, 2026
77780d0
into
STAC-25142-agent-lint-unit
24 of 26 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Phases 3 and 5 of the GitLab → GitHub CI migration (STAC-25142): omnibus DEB packaging and the container image builds.
Adds
.github/workflows/build-deb.ymland extendsbuild-binaries.yml:Build DEB package (omnibus, branded / StackState)build-deb.ymlbuild_debxlarge-publicDEB branding verification (no DataDog references)build-deb.ymltest_deb_renamingdocker-publicBuild agent container image (docker build, no push on PR)build-deb.ymlpre_release_main_agent_imagedocker-publicBuild cluster-agent container image (docker build, no push on PR)build-binaries.ymlpre_release_cluster_agent_imagedocker-publicThat closes out
.gitlab-ci-agent.ymlexceptsign_debandpre_release_deb— the release lane, phase 4.Each image job lives in the workflow that produces its input so it can use a plain
needs:; cross-workflow artifact hand-off would need run-id plumbing for no gain.Stacked on
STAC-25142-agent-lint-unit(#444), which is the migration integration branch — everything lands there and #444 merges once as the final cutover, so we never have to disable protections and push to GitLab.Deliberate differences from the GitLab job
deps_debis not ported. Its only downstream-consumed output wasversion.txtfrominv agent.version -u, a pure git-tag derivation that needs no upstream job — justfetch-depth: 0. Its other output (vendor.tar.gz) is consumed by nobody. Generated in-job instead, same asbuild-cluster-agentin phase 2. That removes a job, an artifact round-trip and a cache for zero loss.Warm Go module cache; omnibus/bazel caches still cold.
build-debnow runs inside the STAC-25429 Go module cache image, the same way the binary builds and unit tests do (#445, merged): this workflow calls thegodeps-cachereusable workflow and uses the image it publishes as itscontainer:, soGOMODCACHEarrives warm and the coldgo clean -modcache+inv -e deps --verbosereconcile is gone. The tag is a content hash of the module graph, so all three workflows share one image — and on a PR that leavesgo.modalone, no image is built at all. Branding is safe against a cache baked from the unbranded tree:fix_branding.shrewrites.gosources and testdata only, nevergo.mod/go.sum/go.work, so the module graph is identical either side of it.go work sync+go work vendorstill run per checkout —vendor/is what omnibus is handed as--go-mod-cache— but now offline against the warm cache.The other three GitLab caches are still absent, deliberately: omnibus
base_dir+.gems+ the omnibus git cache, the bazel install base, and the bazelrepository_cache. None of them transfer as-is:So this PR still measures a cold omnibus wall-clock. That number is what tells us what a cache backend is actually worth and which one to build (runner-local PVC vs. registry-backed vs. S3). Bazel state is pinned under
XDG_CACHE_HOMEso a cache layer can adopt those paths unchanged, andOMNIBUS_GIT_CACHE_DIRis intentionally left unset for now.Nothing is signed, pushed or published.
sign_deband the S3 publish are the release lane (phase 4) and need GPG key material. The twopre_release_*_imagejobs also pushed toquay.io/stackstate; these stop atdocker buildplus a runtime check, so the PR lane needs no write credential at all — only the read-only proxy creds already in use. On a public repo that separation is the point: validating a change and releasing it are different trust boundaries. Publishing lands in phase 4, gated on the branch rather than on the PR.Only the amd64 pipeline is ported. GitLab fans
.gitlab-ci-agent.ymlout twice from.gitlab-ci.yml(agent-x86/agent-arm). The arm64 half needs an arm64 XL runner class, which does not exist yet — onlyarm64-docker. Tracked separately.Image smoke tests bypass the entrypoints and exec the real binary's
version. The cluster-agententrypoint.shhard-exits withoutSTS_API_KEY, which a version check has no business needing.The
.omnibus↔/omnibusmove dance is dropped along with the cache. Worth noting it was already inert on GitLab: it staged the cache at/omnibuswhile the build ran with--base-dir /.omnibus.bin/stackstate-cluster-agentis copied as a directory, not flattened. It holds the binary plusdist/, and the Dockerfile relies on that: it lands at/opt/stackstate-agent/bin/stackstate-cluster-agent/andentrypoint.shputs that directory onPATHsoCMDcan execstackstate-cluster-agentby name (see the[sts]comment intasks/cluster_agent_helpers.py:42).The branding gate resolves its input explicitly.
test/renaming/test_deb.shtakes exactly one argument and rejects anything else; the GitLab job passed a raw glob and silently relied on it expanding to one file. This job counts the matches and fails with a readable message otherwise.Carried over verbatim
fix_branding.shbefore vendoring (branding rewrites import paths, sovendor/must be materialised against the rewritten tree), the/go/src/github.com/StackVista/stackstate-agentGOPATH symlink,XDG_CACHE_HOME/BAZELISK_HOME+ theuser.bazelrcwritten viatry-import %workspace%/user.bazelrc(bazelisk aborts withXDG_CACHE_HOME () must denote a directory in CI!without it),LD_LIBRARY_PATH, and--install-directory /opt/stackstate-agent(without ittasks/omnibus.pyderives paths from the unbranded/opt/datadog-agentand the post-build step targets a nonexistent directory).Secrets — provisioned, no longer blocking
.gitlab-scripts/setup_artifact_registry.shhard-exits when these are unset, which is why every run before today failed atBuild DEB package with omnibuswithERROR: Required environment variables not set:GITLAB_PACKAGE_REGISTRY_PYPI_SIMPLE_URLGITLAB_PACKAGE_REGISTRY_USERGITLAB_PACKAGE_REGISTRY_READONLY_PASSWORDadmin:org, so the running build is the confirmationEvery red run on this PR predates that provisioning (last one 2026-07-28 13:45Z), so the failures on record are stale.
Repo-level rather than org-level was the ask: org secrets default to
visibility=private, which excludes this public repo, and widening them tovisibility=all— the STAC-25350 workaround used for the read-onlyREGISTRY_*pull credentials — would expose a package-registry credential to every public repo in the org. Repo secrets are never exposed to fork PRs, and the jobs additionally skip fork PRs by condition. The read-only password is used, and credentials go topip.conf+~/.netrc, never into a URL.Validation
zizmor --collect=workflows,actions,dependabot—No findings to report(6 ignored, 14 suppressed). The added ignore is the same narrowunpinned-imagesone STAC-25429 Warm the Go module cache with a prebuilt, content-addressed CI image #445 uses for the content-addressed cache-imagecontainer.imageref.permissions: contents: read;persist-credentials: false; nopull_request_target, no PATs, nosecrets: inherit, no context interpolation inrun:.xlarge-public/docker-publicand the containerised-job pattern are proven green bylint-and-unit-tests.ymlandbuild-binaries.ymlon STAC-25142 Add GitHub Actions lint + unit-test workflow (agent CI migration phase 1) #444.docker-publicis the ARC class purpose-built for this ("Lightweight DinD runner for Docker image builds on the PUBLIC stackstate-agent repo") — docker CLI in the runner image,dockerdin a native sidecar. That prior proof did not extend to the agent image — see the runner prerequisite below.go.mod, so the cache tag is unchanged: the cache image is a hit and the tidy gate self-skips.End-to-end result on
9a2658bb10All three workflows green;
mergeStateStatusCLEAN.The DEB build passing confirms all three
GITLAB_PACKAGE_REGISTRY_*credentials resolve, and the cache-hit path confirms the content-addressed tag is stable across all three workflows.Runner prerequisite — STAC-25474
Build agent container imagedid not pass on the first attempt, and the fix was not in this PR. It failed deterministically (2/2 runs) at the final export step, after every Dockerfile layer had already built:Root cause was the
docker-publicDinD sidecar: it pinsdocker:29.4.1-dind, and Docker 29 defaults to the containerd image store on fresh installs (every DinD pod is one). That store races on large multi-layer exports — moby/moby#52431. Size-dependent, which is why the small cluster-agent image passed on the same runner class throughout while the full omnibus agent image did not.Fixed in argocd-apps#155 by pinning the legacy overlay2 graphdriver on that runner (not an engine downgrade — graph drivers are deprecated but not removed in 29.x). After that landed, the same job passed unchanged in 45s, with the export completing in 4.4s instead of deadlocking at 18.4s.
Nothing in this PR was modified to accommodate it — the workflow was correct as written. Worth knowing for anyone reading this history, and worth knowing that the other seven
tooling-mainDinD scale sets still carry the same defect.Smoke test agent imageexecuted for the first time here (it had been skipped behind the failing build) and passed:Agent 3.78.2 - Meta: git.78.2f13d10 - Commit: 2f13d10900 - Go version: go1.25.12.