feat(gcp-pipeline): build each platform on a native runner and merge the manifest - #71
Open
MaximusHaximus wants to merge 2 commits into
Open
feat(gcp-pipeline): build each platform on a native runner and merge the manifest#71MaximusHaximus wants to merge 2 commits into
MaximusHaximus wants to merge 2 commits into
Conversation
…the manifest Building linux/arm64 under QEMU on the amd64 runner made a typical service's TypeScript compile ~8x slower than native (471s vs 58s on identical source) and left the finished amd64 image waiting ~9 minutes for it on every release. Every web-apps namespace schedules onto arm64 (C4A) nodes, so the arm64 image is the one production runs and cannot be dropped. Each platform in `platforms` now builds on a runner of its own architecture (`runner_amd64`, `runner_arm64` inputs; arm64 defaults to GitHub's `ubuntu-24.04-arm`), pushes by digest, and a final job merges the digests into one tagged multi-platform manifest. Tags are applied only after every platform succeeds, so a failed leg leaves the tag unpublished instead of half-published. Build provenance is resolved once so all platforms stamp the same GIT_SHA/BUILT_AT. Cache scope is per image and platform so parallel legs and sibling images do not overwrite each other's cache index. Callers need no changes; the inputs and defaults they already use are unchanged. Claude-Session: https://claude.ai/code/session_01BVWnz2gcXRyRoA9vefSFXM
MaximusHaximus
marked this pull request as ready for review
September 10, 2026 21:14
MaximusHaximus
marked this pull request as draft
September 10, 2026 21:16
…release Code scanning flags each `uses:` pinned to a mutable tag on this file (actions/unpinned-tag). Every third-party action now references the commit of its current release with the version alongside, and the releases are current majors: checkout v7.0.1, setup-buildx v4.3.0, google-github-actions/auth v3.0.0, metadata-action v6.2.0, build-push-action v7.3.0, upload-artifact v7.0.1, download-artifact v8.0.1. All run on Node 24, which GitHub-hosted runners provide. Each input and output this workflow relies on was checked against the new version's action.yml: auth keeps token_format, workload_identity_provider and service_account; build-push keeps outputs, digest, labels, build-args, cache-from/to and platforms; metadata-action still exports DOCKER_METADATA_OUTPUT_JSON; download-artifact v8's single-artifact path change does not apply to pattern downloads with merge-multiple. Claude-Session: https://claude.ai/code/session_01BVWnz2gcXRyRoA9vefSFXM
MaximusHaximus
marked this pull request as ready for review
September 10, 2026 22:23
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
gcp_pipeline_release_image.yamlnow builds each platform listed inplatformson a runner of that platform's own CPU architecture (a matrix job), pushes each result by digest, and a final job merges the digests into one tagged multi-platform manifest withdocker buildx imagetools create. QEMU emulation is removed.runner_amd64(defaultubuntu-latest) andrunner_arm64(defaultubuntu-24.04-arm, GitHub's standard arm64 runner, available to private repositories since January 2026). Every existing input and default is unchanged, so callers need no changes.GIT_SHA/BUILT_AT) is resolved once, so every platform's image carries identical values. The GitHub Actions layer cache is scoped per image and per platform so parallel legs, and sibling images released from the same repository, do not overwrite each other's cache index.actions/unpinned-tagcode-scanning alerts on this file. Each input and output the workflow relies on was checked against the new versions.Why
linux/arm64under QEMU on the amd64 runner made a typical service's TypeScript compile about 8x slower than native (471s vs 58s on identical source). The emulated leg accounted for roughly 11 of a 12-minute build step while the finished amd64 image sat waiting. Every release of every consumer of this workflow pays that cost.Verification
Live: a consuming monorepo pinned its release trigger to this branch and cut two real releases of five service images each through it, one before and one after the action-version bump. All ten runs succeeded, the pushed tags are OCI image indexes listing
linux/amd64andlinux/arm64(plus the usual BuildKit attestation entries), and the services were deployed from those images. The second release ran at this PR's head and downloaded exactly the pinned action commits.Per image, across both releases (the first on a cold layer cache, since the cache scopes are new):
Resolve platforms, tags and build provenanceBuild linux/amd64(ubuntu-latest)Build linux/arm64(ubuntu-24.04-arm, 2 vCPU)Push multi-platform manifestThe same five images on the previous single-job QEMU build, over their last ten releases: build step 10m38s to 15m23s, whole workflow 14m24s to 19m09s. The native arm64
pnpm run buildtook 24s against 471s emulated.CodeQL's
Analyze (actions)passes on the head with zeroactions/unpinned-tagalerts remaining on this file, wheremaincarries five.actionlintpasses apart from pre-existing shellcheck quoting notes on the carried-over tag-construction step and the intentional unquoted$(...)expansions on theimagetools createline, which must word-split to produce one argument per tag and digest.Notes for reviewers
prepare,build (<platform>),merge) instead of one. Digests travel between jobs as a one-day-retention artifact nameddigests-<image>-<platform>.ubuntu-24.04-armprivate repositories get 2 vCPU. It was still the faster leg in the runs above; pass a larger-runner label throughrunner_arm64for more.