debug actions #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: build-test-sign-image | |
| on: | |
| push: | |
| branches: [main, master] | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| # Needed for pushing to GHCR + keyless cosign signing (OIDC) | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| env: | |
| REGISTRY: ghcr.io | |
| jobs: | |
| build_test_and_release: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| # Docker repository names must be lowercase | |
| - name: Set image name (lowercase) | |
| id: image | |
| run: echo "name=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT | |
| - name: Set up QEMU (optional) | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| # Produces tags + labels (commit SHA, semver if you use tags, etc.) | |
| - name: Docker metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ steps.image.outputs.name }} | |
| tags: | | |
| type=sha,format=long | |
| type=ref,event=branch | |
| type=ref,event=tag | |
| labels: | | |
| org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} | |
| org.opencontainers.image.revision=${{ github.sha }} | |
| # 1) CI build (LOAD locally) so we can run tests inside the image. | |
| # Attestations (sbom/provenance) require pushing, so we do that only after tests pass. | |
| - name: Build (CI / local load) | |
| id: build_ci | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| platforms: linux/amd64 | |
| push: false | |
| load: true | |
| tags: ${{ env.REGISTRY }}/${{ steps.image.outputs.name }}:ci-${{ github.sha }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Run your build/test script INSIDE the built image. | |
| # Assumes your image contains your package source (COPY . ...) and that this script exists. | |
| - name: Run build/test script inside image | |
| run: | | |
| set -euo pipefail | |
| docker run --rm \ | |
| ${{ env.REGISTRY }}/${{ steps.image.outputs.name }}:ci-${{ github.sha }} \ | |
| Rscript -f tests/build_test.R | |
| # Optional (but common): scan the image before release | |
| - name: Trivy scan (fail on HIGH/CRITICAL) | |
| uses: aquasecurity/trivy-action@0.28.0 | |
| with: | |
| image-ref: ${{ env.REGISTRY }}/${{ steps.image.outputs.name }}:ci-${{ github.sha }} | |
| format: table | |
| ignore-unfixed: true | |
| vuln-type: os,library | |
| severity: HIGH,CRITICAL | |
| exit-code: "1" | |
| # 2) Release build (PUSH) with SBOM + provenance attestations. | |
| - name: Build & push (release + attestations) | |
| id: build_release | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| platforms: linux/amd64 | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| # Supply-chain metadata | |
| provenance: true | |
| sbom: true | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Keyless signing using GitHub OIDC (no long-lived keys). | |
| - name: Install cosign | |
| uses: sigstore/cosign-installer@v3 | |
| with: | |
| cosign-release: v2.4.1 | |
| - name: Sign image digest (keyless) | |
| env: | |
| COSIGN_EXPERIMENTAL: "false" | |
| run: | | |
| set -euo pipefail | |
| IMAGE="${{ env.REGISTRY }}/${{ steps.image.outputs.name }}" | |
| DIGEST="${{ steps.build_release.outputs.digest }}" | |
| cosign sign --yes "${IMAGE}@${DIGEST}" | |
| # Optional: sign the SBOM/provenance attestations too (recommended if you plan to verify them client-side) | |
| - name: Sign attestations (keyless) | |
| run: | | |
| set -euo pipefail | |
| IMAGE="${{ env.REGISTRY }}/${{ steps.image.outputs.name }}" | |
| DIGEST="${{ steps.build_release.outputs.digest }}" | |
| # This signs the attached attestations (provenance/SBOM) for that digest. | |
| cosign sign-attestation --yes "${IMAGE}@${DIGEST}" |