From 0fb6c30466c4d5d5dcf7aba3b7a0cd5e0d924e55 Mon Sep 17 00:00:00 2001 From: jklein Date: Mon, 24 Aug 2026 14:00:06 +0200 Subject: [PATCH] publish: read registry credentials from step outputs and validate them Two defects kept the publish broken after the load-secrets-action v5 bump in #140. v5 no longer exports the loaded values as environment variables for later steps the way v4 did; only the step outputs carry them. Every "${{ env.JK_CR_* }}" reference therefore resolved to an empty string from that bump on, and nothing reported it - the loading step logs "Populating variable" and stays green either way. #149 moved three of the four references to steps..outputs but left "-u ${{ env.JK_CR_USERNAME }}" on the old form, and piped the username instead of the token into --password-stdin. The second defect is why this surfaced as a terminal error: an empty value collapsed into a missing argument instead of failing. With an empty username, "-u" swallowed the following "--password-stdin", helm stopped reading the password from stdin, prompted interactively and died with "inappropriate ioctl for device". All four values now come from steps..outputs, are mapped into each step's own env block and used as quoted shell variables guarded with ":?". An empty or unset value aborts the job naming the op:// path to fix, quoting keeps it from shifting arguments, and the token no longer appears on the command line. --- .github/workflows/publish-helm-chart.yml | 39 ++++++++++++++++++++++-- README.md | 2 +- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish-helm-chart.yml b/.github/workflows/publish-helm-chart.yml index db80166..218fa9c 100644 --- a/.github/workflows/publish-helm-chart.yml +++ b/.github/workflows/publish-helm-chart.yml @@ -62,10 +62,43 @@ jobs: JK_CR_USERNAME: op://GitHub-Actions/jk-registry-access/username JK_CR_CHARTS_LOCATION: op://GitHub-Actions/jk-registry-access/charts-location JK_CR_HELM_REGISTRY: op://GitHub-Actions/jk-registry-access/helm-registry + # The values are mapped into each step's own env block and read as quoted + # shell variables - never interpolated into the command line. + # + # Two separate failures made this necessary. First, load-secrets-action v5 + # (bumped in #140) no longer exports the loaded values as environment + # variables for later steps the way v4 did; only the step outputs carry + # them. Every "${{ env.JK_CR_* }}" reference therefore resolved to an empty + # string from that bump on, with nothing reporting an error - the loading + # step logs "Populating variable" and stays green either way. + # + # Second, an empty value collapsed into a missing argument instead of an + # error: with an empty username, "-u" swallowed the following + # "--password-stdin", helm stopped reading the password from stdin, + # prompted interactively and died on the runner with "inappropriate ioctl + # for device" - a terminal error for what was really an unset variable. + # + # The ":?" guards fail loudly and name the value that is missing, quoting + # keeps an empty one from shifting arguments, and the token no longer + # appears in the process list. - name: "Login to JK-Registry" - run: echo ${{ steps.load-jk-cr-creds.outputs.JK_CR_USERNAME }} | helm registry login ${{ steps.load-jk-cr-creds.outputs.JK_CR_HELM_REGISTRY }} -u ${{ env.JK_CR_USERNAME }} --password-stdin + env: + JK_CR_TOKEN: ${{ steps.load-jk-cr-creds.outputs.JK_CR_TOKEN }} + JK_CR_USERNAME: ${{ steps.load-jk-cr-creds.outputs.JK_CR_USERNAME }} + JK_CR_HELM_REGISTRY: ${{ steps.load-jk-cr-creds.outputs.JK_CR_HELM_REGISTRY }} + run: |- + : "${JK_CR_HELM_REGISTRY:?empty - check op://GitHub-Actions/jk-registry-access/helm-registry}" + : "${JK_CR_USERNAME:?empty - check op://GitHub-Actions/jk-registry-access/username}" + : "${JK_CR_TOKEN:?empty - check op://GitHub-Actions/jk-registry-access/password}" + printf '%s' "$JK_CR_TOKEN" | helm registry login "$JK_CR_HELM_REGISTRY" -u "$JK_CR_USERNAME" --password-stdin - name: "Push Helm Chart to JK-Container Registry" - run: helm push ${{ inputs.chart-name }}-*.tgz ${{ steps.load-jk-cr-creds.outputs.JK_CR_CHARTS_LOCATION }} + env: + JK_CR_CHARTS_LOCATION: ${{ steps.load-jk-cr-creds.outputs.JK_CR_CHARTS_LOCATION }} + run: |- + : "${JK_CR_CHARTS_LOCATION:?empty - check op://GitHub-Actions/jk-registry-access/charts-location}" + helm push "${{ inputs.chart-name }}"-*.tgz "$JK_CR_CHARTS_LOCATION" working-directory: ${{ inputs.chart-location }} - name: "Logout from JK-Registry" - run: helm registry logout ${{ steps.load-jk-cr-creds.outputs.JK_CR_HELM_REGISTRY }} + env: + JK_CR_HELM_REGISTRY: ${{ steps.load-jk-cr-creds.outputs.JK_CR_HELM_REGISTRY }} + run: helm registry logout "$JK_CR_HELM_REGISTRY" diff --git a/README.md b/README.md index 7dfd11c..1a41622 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Collection of some self-made helm-charts. Each top-level directory is a standalo ## CI/CD (GitHub Actions) - `publish-.yml` — one thin workflow per chart; triggers on pushes to `main` touching `/**` (or manually) and calls the reusable workflow below. **A push to a chart directory on `main` publishes that chart**, so the chart version must be bumped in the same change. -- `publish-helm-chart.yml` — reusable workflow: `helm package`, then `helm push` to the private JK-Registry. Registry credentials come from 1Password Connect (`OP_CONNECT_TOKEN` secret, items under `op://GitHub-Actions/`). +- `publish-helm-chart.yml` — reusable workflow: `helm package`, then `helm push` to the private JK-Registry. Registry credentials come from 1Password Connect (`OP_CONNECT_TOKEN` secret, items under `op://GitHub-Actions/`). The loaded values are read via **`steps..outputs.*`**, mapped into each step's own `env:` block and used as quoted shell variables — never interpolated into the command line. `load-secrets-action` **v5 no longer exports them as environment variables** for later steps the way v4 did, so after the v5 bump every `${{ env.JK_CR_* }}` reference resolved to an empty string while the loading step still logged `Populating variable` and stayed green. Each value is additionally guarded with `:?`, because an empty one used to collapse into a missing argument rather than an error: `-u` consumed the following `--password-stdin`, helm fell back to an interactive prompt and the job died with `inappropriate ioctl for device` — a terminal error for what was really an unset variable. - `change-app-version.yml` — manually dispatched app-version bump; the chart must be listed in its `chart-name` choice list. - `validate-charts.yml` — PR pipeline: detects which charts a PR touches and, for exactly those, runs `helm lint --strict`, `helm package`, and a chart-version bump check (`template-chart` is exempt from the version check). PRs without chart changes skip the build matrix. After the build stage, an **install-test** job (same changed-charts matrix) installs each changed chart into an ephemeral [k3d](https://k3d.io) cluster on the runner and requires every workload to become Ready — see below.