From 0253fe23be5aac70c80ebffdaac894bf40ee4587 Mon Sep 17 00:00:00 2001 From: AYDEV-FR Date: Sat, 20 Jun 2026 19:47:24 +0200 Subject: [PATCH] ci(chart): publish the dploy Helm chart as a signed OCI artifact Add a dedicated Chart workflow mirroring docker.yml's split behavior: - Every branch / PR: helm lint + template render + package smoke test, so chart regressions surface before a tag is cut (ci.yml didn't cover the chart at all). - On v* tags: package with the version/appVersion synced to the tag, push to oci://ghcr.io//charts, and cosign-sign the pushed artifact by digest (keyless, id-token). Charts publish under a "charts/" path so the OCI artifact doesn't collide with the container images already at ghcr.io//dploy(-operator). Install: helm install dploy oci://ghcr.io/aydev-fr/charts/dploy --version X.Y.Z Claude-Session: https://claude.ai/code/session_01M4Dd5oASBGHwr6ts6wTnYn --- .github/workflows/chart.yml | 94 +++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 .github/workflows/chart.yml diff --git a/.github/workflows/chart.yml b/.github/workflows/chart.yml new file mode 100644 index 0000000..482d78f --- /dev/null +++ b/.github/workflows/chart.yml @@ -0,0 +1,94 @@ +name: Chart + +on: + push: + branches: ['**'] # every branch: lint + template + package as a smoke test + tags: ['v*'] # tags: publish the signed OCI chart + pull_request: + branches: [main, master] + +env: + REGISTRY: ghcr.io + # Charts go under a dedicated repo path so they don't collide with the + # container images already published at ghcr.io//dploy(-operator). + CHART_NAMESPACE: charts + # Run JS-based actions on Node 24 now (silences the Node 20 deprecation warning) + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + validate: + name: Lint and Template + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Set up Helm + uses: azure/setup-helm@v4 + + - name: Lint chart + run: helm lint charts/dploy + + - name: Render templates + run: helm template dploy charts/dploy > /dev/null + + - name: Package chart (smoke) + run: helm package charts/dploy --destination "${RUNNER_TEMP}/chart" + + publish: + name: Publish OCI Chart + runs-on: ubuntu-latest + needs: validate + if: startsWith(github.ref, 'refs/tags/v') + permissions: + contents: read + packages: write + id-token: write # keyless cosign signing + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Set up Helm + uses: azure/setup-helm@v4 + + - name: Install cosign + uses: sigstore/cosign-installer@v3 + + - name: Resolve version and owner + id: meta + run: | + # ghcr requires a lowercase repository path. + echo "owner=${GITHUB_REPOSITORY_OWNER,,}" >> "$GITHUB_OUTPUT" + echo "version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT" + + - name: Log in to Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" \ + | helm registry login "${REGISTRY}" --username "${{ github.actor }}" --password-stdin + + - name: Package chart + id: package + env: + VERSION: ${{ steps.meta.outputs.version }} + run: | + helm package charts/dploy \ + --version "${VERSION}" \ + --app-version "${VERSION}" \ + --destination "${RUNNER_TEMP}/chart" + echo "file=${RUNNER_TEMP}/chart/dploy-${VERSION}.tgz" >> "$GITHUB_OUTPUT" + + - name: Push and sign chart + env: + OCI_REPO: oci://${{ env.REGISTRY }}/${{ steps.meta.outputs.owner }}/${{ env.CHART_NAMESPACE }} + run: | + # helm push prints "Digest: sha256:..." on success — capture it so we + # sign the exact artifact by digest rather than a mutable tag. + helm push "${{ steps.package.outputs.file }}" "${OCI_REPO}" 2>&1 | tee push.log + DIGEST="$(grep -oE 'sha256:[0-9a-f]{64}' push.log | head -n1)" + if [ -z "${DIGEST}" ]; then + echo "::error::could not parse pushed chart digest from helm output" + exit 1 + fi + CHART_REF="${{ env.REGISTRY }}/${{ steps.meta.outputs.owner }}/${{ env.CHART_NAMESPACE }}/dploy@${DIGEST}" + echo "Signing ${CHART_REF}" + cosign sign --yes "${CHART_REF}"