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}"