From a51227d9524b6375d8bbb11e0c7d42a3a4b15887 Mon Sep 17 00:00:00 2001 From: Nguyen Minh Phuc Date: Sat, 18 Jul 2026 12:20:16 +0000 Subject: [PATCH] ci: run helm from a checksum-pinned binary, not a container The chart gate failed with 'stat deploy/chart/Chart.yaml: no such file or directory' while the file plainly existed in the checkout. `docker run -v "$PWD:/repo"` is interpreted by the dind sidecar's daemon rather than by the job container, so the bind source has to exist on the daemon's side of that boundary. Downloading the binary removes the boundary entirely. Pinned by sha256 for the same reason every image here is pinned by digest. --- .gitea/workflows/ci.yaml | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index ac8aafd..68699eb 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -199,15 +199,34 @@ jobs: runs-on: ubuntu-latest needs: [lint] env: - # Pinned by digest like gitleaks and trivy, and the same helm the worker and - # reconciler images carry — CI renders with the version that ships. - HELM: alpine/helm:3.21.3@sha256:35da09ba0716fc7c3cd63b6b31ee380a9c7662e95f29ab0e4ae962420afd315b + # The same helm version the worker and reconciler images carry, so CI renders with + # the version that ships. + HELM_VERSION: "3.21.3" + # sha256 of helm-v3.21.3-linux-arm64.tar.gz, from https://get.helm.sh/*.sha256sum. + # Pinned for the same reason every image here is pinned by digest: a tarball fetched + # over HTTPS is still a tarball whoever controls the bucket chose to serve. + HELM_SHA256: "67f58155079ff9ffab98ba5c88daff0ed9b542f3a4732f5dd426dde7dd0f5244" steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: install helm + # A downloaded binary rather than `docker run alpine/helm`. The container form + # cannot see the checkout: `docker run -v "$PWD:/repo"` is interpreted by the dind + # SIDECAR's daemon, and the chart path resolved to nothing inside it — + # "stat deploy/chart/Chart.yaml: no such file or directory" while the file plainly + # exists in the job. A binary on PATH has no such boundary to cross. + run: | + set -euo pipefail + curl -fsSL -o /tmp/helm.tgz \ + "https://get.helm.sh/helm-v${HELM_VERSION}-linux-arm64.tar.gz" + echo "${HELM_SHA256} /tmp/helm.tgz" | sha256sum -c - + tar -xzf /tmp/helm.tgz -C /tmp + install -m 0755 /tmp/linux-arm64/helm /usr/local/bin/helm + helm version --short + - name: helm lint run: | - docker run --rm -v "$PWD:/repo" -w /repo "$HELM" lint deploy/chart + helm lint deploy/chart - name: helm template (rejects unbumped digests) # values.yaml ships all-zeros placeholders, so a bare `helm template` MUST fail. @@ -215,8 +234,7 @@ jobs: # what stops the guard silently regressing into a prefix check again. run: | set -euo pipefail - if docker run --rm -v "$PWD:/repo" -w /repo "$HELM" \ - template svcforge deploy/chart >/dev/null 2>&1; then + if helm template svcforge deploy/chart >/dev/null 2>&1; then echo "FAIL: chart rendered against the placeholder digests in values.yaml." >&2 echo "The digest guard in _helpers.tpl is not guarding." >&2 exit 1 @@ -231,8 +249,7 @@ jobs: A="sha256:$(printf 'a%.0s' $(seq 64))" B="sha256:$(printf 'b%.0s' $(seq 64))" C="sha256:$(printf 'c%.0s' $(seq 64))" - docker run --rm -v "$PWD:/repo" -w /repo "$HELM" \ - template svcforge deploy/chart \ + helm template svcforge deploy/chart \ --set image.api.digest="$A" \ --set image.worker.digest="$B" \ --set image.reconciler.digest="$C" \