From 9641a959c98c06bd19c47a26e50f0f402dad54fc Mon Sep 17 00:00:00 2001 From: Lukas Wuttke Date: Wed, 3 Jun 2026 09:30:25 +0200 Subject: [PATCH] ci(helm): guard that the pinned ingestor digest is multi-arch (closes #186) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helm-ci job (ingestor-multiarch) that parses images.ingestor.digest and fails the build unless it's a multi-arch index (linux/amd64 + linux/arm64). Greenfield installs spawn the ingestor Job from this PINNED digest before image-refresh first ticks, so an amd64-only pin breaks data ingestion on arm64 hosts (Apple Silicon, Graviton) with "no match for platform" / ImagePullBackOff. This would have caught #160 (the amd64-only v0.3.1 pin) before it shipped. ghcr.io/tracebloc/ingestor is public -> no secrets. Verified: passes on the current multi-arch baseline (sha256:d361fa77, v0.3.2 / #184), fails on the old amd64-only sha256:a0861ea9. Note: the digest is already multi-arch on develop as of v0.3.2 (#184 — the same d361fa77 index this PR previously bumped to), so #187 no longer touches values.yaml; it adds only the regression guard so an amd64-only pin can't slip back in. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/helm-ci.yaml | 24 ++++++++++++++++++++++++ client/values.yaml | 7 +++++++ 2 files changed, 31 insertions(+) diff --git a/.github/workflows/helm-ci.yaml b/.github/workflows/helm-ci.yaml index 9abefb0..8f6195c 100644 --- a/.github/workflows/helm-ci.yaml +++ b/.github/workflows/helm-ci.yaml @@ -116,6 +116,30 @@ jobs: > /dev/null echo "Schema validation passed for ${{ matrix.platform }}" + ingestor-multiarch: + # Guard: the chart's PINNED ingestor digest must be a multi-arch index + # (linux/amd64 + linux/arm64). Greenfield installs spawn the ingestor from this + # pinned digest (before image-refresh ticks), so an amd64-only pin breaks data + # ingestion on arm64 hosts (Apple Silicon, Graviton) with ImagePullBackOff. This + # would have caught #160 (which pinned the amd64-only v0.3.1). See client#186. + name: Pinned ingestor digest is multi-arch + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Assert images.ingestor.digest supports linux/amd64 + linux/arm64 + run: | + digest=$(yq '.images.ingestor.digest' client/values.yaml) + echo "Pinned ingestor digest: $digest" + if [ -z "$digest" ] || [ "$digest" = "null" ]; then + echo "::error::images.ingestor.digest is empty — it must be a pinned multi-arch digest."; exit 1 + fi + plats=$(docker buildx imagetools inspect "ghcr.io/tracebloc/ingestor@$digest" 2>&1 \ + | awk '/Platform:/{print $2}' | grep -v '^unknown' | sort -u) + echo "Platforms: $(echo "$plats" | paste -sd' ' -)" + echo "$plats" | grep -qx 'linux/arm64' || { echo "::error::Pinned ingestor digest is NOT multi-arch (no linux/arm64). arm64 installs (Apple Silicon, Graviton) would fail ingestion with 'no match for platform' / ImagePullBackOff. Pin a multi-arch :0.x index. See client#186 / #160."; exit 1; } + echo "$plats" | grep -qx 'linux/amd64' || { echo "::error::Pinned ingestor digest is missing linux/amd64."; exit 1; } + echo "OK — pinned ingestor digest is multi-arch (amd64 + arm64)." + # Installer script tests (bats + Pester) + the cross-distro prerequisite matrix # live in their own workflow: .github/workflows/installer-tests.yaml # (triggered on scripts/** changes). diff --git a/client/values.yaml b/client/values.yaml index b550d70..4cf25c8 100644 --- a/client/values.yaml +++ b/client/values.yaml @@ -220,6 +220,13 @@ images: # first multi-arch image (amd64 + arm64, #24) so arm64 nodes can run # the ingestor. Bump only when greenfield installs should start on a # different version; ongoing rollouts are managed by image-refresh. + # + # This digest MUST be a multi-arch index (linux/amd64 + linux/arm64). + # jobs-manager spawns the ingestor Job by this pinned digest, so an + # amd64-only pin breaks ingestion on arm64 hosts (Apple Silicon, + # Graviton) with "no match for platform" / ImagePullBackOff (#186; the + # amd64-only v0.3.1 pin in #160 was the regression). Enforced by the + # `ingestor-multiarch` job in .github/workflows/helm-ci.yaml. digest: "sha256:d361fa778554ab171adcc2671eaf109c32f3d2af339c7920a2d38d102ce53678" # Floating tag polled by image-refresh. The team's ghcr.io # publishing convention uses semver-style float tags — `0` tracks