From 7c66408cd329bd889beec237e6d2f8eb6b613f93 Mon Sep 17 00:00:00 2001 From: bussyjd Date: Sun, 24 May 2026 11:42:02 +0400 Subject: [PATCH] ci: add helm-template-smoke job to catch chart-render parse errors PR #527 fixed an unescaped {{ $labels }} in a PrometheusRule annotation that broke `helm upgrade base` on every `obol stack up`. The bug shipped to integration testing because go test ./... doesn't exercise Helm rendering. This job pipes the embedded base chart through `helm template` on every PR; parse errors fail the build before merge. - Runs against ./internal/embed/infrastructure/base - Uses helm v3.20.1 (matches obolup.sh pinned version) - Also runs `helm lint` for chart-structure issues - Substitutes {{OLLAMA_HOST_IP}}/{{CLUSTER_ID}} stubs in a temp copy of the chart (mirroring what `obol stack init` does via internal/defaults/defaults.go::InfrastructureReplacements) - Future: pair with a helmfile-lint job for state-value tests If we ever land a chart-template change that this doesn't catch, expand the helm-template invocation with --set values mimicking what `obol stack up` provides. --- .github/workflows/helm-template-smoke.yml | 83 +++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 .github/workflows/helm-template-smoke.yml diff --git a/.github/workflows/helm-template-smoke.yml b/.github/workflows/helm-template-smoke.yml new file mode 100644 index 00000000..27a9ed1f --- /dev/null +++ b/.github/workflows/helm-template-smoke.yml @@ -0,0 +1,83 @@ +name: Helm Template Smoke + +on: + pull_request: + branches: [ main ] + paths: + - 'internal/embed/infrastructure/**' + - '.github/workflows/helm-template-smoke.yml' + push: + branches: [ main ] + paths: + - 'internal/embed/infrastructure/**' + - '.github/workflows/helm-template-smoke.yml' + +jobs: + helm-template-smoke: + name: helm template embedded chart + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Set up Helm + uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1 + with: + version: v3.20.1 # match obolup.sh pinned version + + - name: helm template ./base + run: | + # Render the embedded `base` chart and fail on Go-template parse + # errors. Catches bugs like the unescaped `{{ $labels }}` in + # PrometheusRule annotations that broke `helm upgrade base` on + # every `obol stack up` (see PR #527). `go test ./...` does not + # exercise Helm rendering, so this is the only pre-merge gate + # for chart parse errors. + # + # The base chart contains `{{PLACEHOLDER}}` strings (e.g. + # `{{OLLAMA_HOST_IP}}`, `{{CLUSTER_ID}}`) that are substituted + # by `internal/defaults/defaults.go::InfrastructureReplacements` + # before helmfile runs. Helm's Go-template parser would treat + # them as actions and fail, so we substitute stub values into + # a working copy first — mirroring what `obol stack init` does. + set -euo pipefail + workdir="$(mktemp -d)" + cp -R internal/embed/infrastructure/base "$workdir/base" + # Mirror internal/defaults InfrastructureReplacements with CI stubs. + find "$workdir/base" -type f -name '*.yaml' -print0 \ + | xargs -0 sed -i \ + -e 's/{{OLLAMA_HOST_IP}}/127.0.0.1/g' \ + -e 's/{{OLLAMA_HOST}}/localhost/g' \ + -e 's/{{CLUSTER_ID}}/ci-helm-smoke/g' + # Match values passed by helmfile.yaml `releases[base]`. + helm template base "$workdir/base" \ + --set dataDir=/data \ + --set network=mainnet \ + > /dev/null + + - name: helm template ./cloudflared + run: | + # The cloudflared chart has no placeholder substitution and uses + # default values from values.yaml. + set -euo pipefail + helm template cloudflared internal/embed/infrastructure/cloudflared \ + > /dev/null + + - name: helm lint ./base + run: | + set -euo pipefail + workdir="$(mktemp -d)" + cp -R internal/embed/infrastructure/base "$workdir/base" + find "$workdir/base" -type f -name '*.yaml' -print0 \ + | xargs -0 sed -i \ + -e 's/{{OLLAMA_HOST_IP}}/127.0.0.1/g' \ + -e 's/{{OLLAMA_HOST}}/localhost/g' \ + -e 's/{{CLUSTER_ID}}/ci-helm-smoke/g' + helm lint "$workdir/base" \ + --set dataDir=/data \ + --set network=mainnet + + - name: helm lint ./cloudflared + run: | + set -euo pipefail + helm lint internal/embed/infrastructure/cloudflared