name: Bake images on: schedule: - cron: 0 8 * * 1 workflow_dispatch: inputs: environment: type: choice options: - testing - production default: testing description: "Choose the environment to bake the images for" target: type: string default: "" description: "A comma separated list of targets to build. If empty, all targets will be built." jobs: # Start by building images for testing. We want to run security checks before pushing those to production. testbuild: name: Build for testing runs-on: ubuntu-latest permissions: contents: read packages: write security-events: write # Required by the cosign step id-token: write outputs: metadata: ${{ steps.build.outputs.metadata }} images: ${{ steps.images.outputs.images }} steps: - name: Checkout Code uses: actions/checkout@v4 - name: Log in to the GitHub Container registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} # TODO: review this when GitHub has linux/arm64 runners available (Q1 2025?) # https://github.com/github/roadmap/issues/970 - name: Set up QEMU uses: docker/setup-qemu-action@v3 with: platforms: 'arm64' - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build and push uses: docker/bake-action@v6 id: build env: environment: testing registry: ghcr.io/${{ github.repository_owner }} revision: ${{ github.sha }} with: push: true targets: ${{ github.event.inputs.target }} # Get a list of the images that were built and pushed. We only care about a single tag for each image. - name: Generated images id: images run: | echo "images=$(echo '${{ steps.build.outputs.metadata }}' | jq -c '[ .[]."image.name" | sub(",.*";"") ]')" >> "$GITHUB_OUTPUT" # Even if we're testing we sign the images, so we can push them to production later if that's required - name: Install cosign uses: sigstore/cosign-installer@v3 # See https://github.blog/security/supply-chain-security/safeguard-container-signing-capability-actions/ # and https://github.com/actions/starter-workflows/blob/main/ci/docker-publish.yml for more details on # how to use cosign. - name: Sign images run: | echo '${{ steps.build.outputs.metadata }}' | \ jq '.[] | (."image.name" | sub(",.*";"" )) + "@" + ."containerimage.digest"' | \ xargs cosign sign --yes security: name: Security checks runs-on: ubuntu-latest needs: - testbuild strategy: matrix: image: ${{fromJson(needs.testbuild.outputs.images)}} steps: - name: Checkout Code uses: actions/checkout@v4 - name: Log in to the GitHub Container registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Dockle uses: erzz/dockle-action@v1 with: image: ${{ matrix.image }} exit-code: '1' - name: Snyk uses: snyk/actions/docker@master continue-on-error: true env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: image: "${{ matrix.image }}" args: --severity-threshold=high --file=Dockerfile - name: Upload result to GitHub Code Scanning uses: github/codeql-action/upload-sarif@v3 continue-on-error: true with: sarif_file: snyk.sarif # Build the image for production. # # TODO: no need to rebuild everything, just copy the testing images we have generated to the production registry # if we get here and we are building for production. prodbuild: if: github.event.inputs.environment == 'production' || github.event_name == 'schedule' name: Build for production runs-on: ubuntu-latest needs: - security permissions: contents: read packages: write security-events: write steps: - name: Checkout Code uses: actions/checkout@v4 - name: Log in to the GitHub Container registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up QEMU uses: docker/setup-qemu-action@v3 with: platforms: 'arm64' - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build and push uses: docker/bake-action@v6 id: build env: environment: production registry: ghcr.io/${{ github.repository_owner }} revision: ${{ github.sha }} with: push: true - name: Install cosign uses: sigstore/cosign-installer@v3 # See https://github.blog/security/supply-chain-security/safeguard-container-signing-capability-actions/ # and https://github.com/actions/starter-workflows/blob/main/ci/docker-publish.yml for more details on # how to use cosign. - name: Sign images run: | images=$(echo '${{ steps.build.outputs.metadata }}' | jq '.[] | (."image.name" | sub(",.*";"" )) + "@" + ."containerimage.digest"' ) cosign sign --yes ${images}