diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index c82d418..57d4a0c 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -55,14 +55,6 @@ jobs: with: platforms: ${{ matrix.platform.qemu }} - # Install the cosign tool except on PR - # https://github.com/sigstore/cosign-installer - - name: Install cosign - if: github.event_name != 'pull_request' - uses: sigstore/cosign-installer@v3.1.2 - with: - cosign-release: 'v2.2.0' - # Set up BuildKit Docker container builder to be able to build # multi-platform images and export cache # https://github.com/docker/setup-buildx-action @@ -72,18 +64,18 @@ jobs: - name: Go package cache uses: actions/cache@v3 with: - path: go-package-cache - key: ${{ matrix.platform.go }}-docker-go-package-${{ hashFiles('go.sum') }} - restore-keys: | - ${{ matrix.platform.go }}-docker-go-package- + path: go-package-cache + key: ${{ matrix.platform.go }}-docker-go-package-${{ hashFiles('go.sum') }} + restore-keys: | + ${{ matrix.platform.go }}-docker-go-package- - name: Go build cache uses: actions/cache@v3 with: - path: go-build-cache - key: ${{ matrix.platform.go }}-docker-go-build-${{ hashFiles('go.sum') }} - restore-keys: | - ${{ matrix.platform.go }}-docker-go-build- + path: go-build-cache + key: ${{ matrix.platform.go }}-docker-go-build-${{ hashFiles('go.sum') }} + restore-keys: | + ${{ matrix.platform.go }}-docker-go-build- - name: Inject go package cache into docker uses: reproducible-containers/buildkit-cache-dance@v2.1.2 @@ -114,30 +106,107 @@ jobs: uses: docker/metadata-action@v5.0.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=edge,branch=main - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha,enable=false # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - - name: Build and push Docker image + - name: Build and push Docker image in PR + id: build-and-push-pr + uses: docker/build-push-action@v5.0.0 + if: github.event_name == 'pull_request' + with: + context: . + file: ${{ matrix.platform.dockerfile && matrix.platform.dockerfile || 'Dockerfile' }} + build-args: GOARCH=${{ matrix.platform.go }} + platforms: ${{ matrix.platform.docker }} + push: false + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + # Build and push Docker image with Buildx (push if not on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image outside Branch id: build-and-push uses: docker/build-push-action@v5.0.0 + if: github.event_name != 'pull_request' with: context: . file: ${{ matrix.platform.dockerfile && matrix.platform.dockerfile || 'Dockerfile' }} build-args: GOARCH=${{ matrix.platform.go }} platforms: ${{ matrix.platform.docker }} - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} + push: true labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max + outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + + - name: Export digest + if: github.event_name != 'pull_request' + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + if: github.event_name != 'pull_request' + uses: actions/upload-artifact@v3 + with: + name: digests + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + create-manifests: + runs-on: ubuntu-latest + needs: [ build ] + if: github.event_name != 'pull_request' + + steps: + - name: Download digests + uses: actions/download-artifact@v3 + with: + name: digests + path: /tmp/digests + + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + uses: docker/login-action@v3.0.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Install the cosign tool except on PR + # https://github.com/sigstore/cosign-installer + - name: Install cosign + uses: sigstore/cosign-installer@v3.1.2 + with: + cosign-release: 'v2.2.0' + + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5.0.0 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=edge,branch=main + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha,enable=false + + - name: Create manifest list and push + env: + DOCKER_METADATA_OUTPUT_JSON: ${{ toJSON(steps.meta.outputs) }} + working-directory: /tmp/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) # Sign the resulting Docker image digest except on PRs. # This will only write to the public Rekor transparency log when the Docker @@ -145,11 +214,20 @@ jobs: # transparency data even for private images, pass --force to cosign below. # https://github.com/sigstore/cosign - name: Sign the published Docker image - if: ${{ github.event_name != 'pull_request' }} + working-directory: /tmp/digests env: - # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable - TAGS: ${{ steps.meta.outputs.tags }} - DIGEST: ${{ steps.build-and-push.outputs.digest }} + RAW_TAGS: ${{ join(steps.meta.outputs.tags, ' ') }} # This step uses the identity token to provision an ephemeral certificate # against the sigstore community Fulcio instance. - run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} + run: | + TAGS="" + for RAW_TAG in RAW_TAGS; do + TAGS="${TAGS}$(printf '${RAW_TAG}@sha256:%s ' *)" + done + echo "${TAGS}" | xargs -I {} cosign sign --yes {} + + - name: Inspect image + run: | + for RAW_TAG in RAW_TAGS; do + docker buildx imagetools inspect ${RAW_TAG} + done