diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 47ad23d9..a132134d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -65,12 +65,14 @@ jobs: name: release needs: [build] outputs: - container_digest: ${{ steps.container_info.outputs.container_digest }} - container_tags: ${{ steps.container_info.outputs.container_tags }} + container_info: ${{ steps.container_info.outputs.container_info }} container_repos: ${{ steps.container_info.outputs.container_repos }} runs-on: ubuntu-20.04 + env: + DOCKER_CLI_EXPERIMENTAL: enabled + steps: - name: Set up Go uses: actions/setup-go@v2.2.0 @@ -86,6 +88,9 @@ jobs: - name: Install Syft uses: anchore/sbom-action/download-syft@v0.6.0 + - name: Set up QEMU + uses: docker/setup-qemu-action@v1.2.0 + - name: Checkout uses: actions/checkout@v2.4.0 with: @@ -118,7 +123,7 @@ jobs: uses: goreleaser/goreleaser-action@v2 with: version: latest - args: release --rm-dist ${{ (!startsWith(github.ref, 'refs/tags/') && '--snapshot') || '' }} ${{ ((startsWith(github.ref, 'refs/tags/') && endsWith(github.ref, '-draft')) && '-f .goreleaser.draft.yml') || '' }} + args: release --rm-dist ${{ (!startsWith(github.ref, 'refs/tags/') && '--snapshot') || '' }} ${{ ((startsWith(github.ref, 'refs/tags/') && endsWith(github.ref, '-draft')) && '-f .goreleaser.draft.yml') || '' }} --debug env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" LDFLAGS: ${{ steps.release-vars.outputs.LDFLAGS }} @@ -129,10 +134,20 @@ jobs: id: container_info if: startsWith(github.ref, 'refs/tags/') run: | - export CONTAINER_DIGEST=$(make container-digest GITHUB_REF=${{ github.ref_name }}) - echo "::set-output name=container_digest::$CONTAINER_DIGEST" - echo "::set-output name=container_tags::$(make container-tags CONTAINER_DIGEST="${CONTAINER_DIGEST}" | paste -s -d ',' -)" - echo "::set-output name=container_repos::$(make container-repos CONTAINER_DIGEST="${CONTAINER_DIGEST}" | jq --raw-input . | jq --slurp -c)" + function digest_tags { + while IFS= read -r line ; do + jq -n "{digest: \"$line\", tags: \$ARGS.positional}" --args $(make container-tags CONTAINER_DIGEST=$line) + done <<< "$(make manifest-digest GITHUB_REF=${{ github.ref_name }})" + } + + CONTAINER_INFO="$(digest_tags | jq --slurp . -c)" + CONTAINER_DIGEST="$(echo "$CONTAINER_INFO" | jq --raw-output '.[0].digest')" + CONTAINER_REPOS="$(make container-repos CONTAINER_DIGEST="${CONTAINER_DIGEST}" | jq --raw-input . | jq --slurp -c)" + + set | grep 'CONTAINER_' + + echo "::set-output name=container_info::$CONTAINER_INFO" + echo "::set-output name=container_repos::$CONTAINER_REPOS" - name: Logout from Container registries if: ${{ always() }} @@ -241,6 +256,7 @@ jobs: strategy: matrix: repo: ${{ fromJSON(needs.release.outputs.container_repos) }} + container: ${{ fromJSON(needs.release.outputs.container_info) }} steps: - name: Install cosign @@ -253,7 +269,7 @@ jobs: with: command: generate subcommand: container - arguments: --repository ${{ matrix.repo }} --output-path provenance.att --digest ${{ needs.release.outputs.container_digest }} --tags ${{ needs.release.outputs.container_tags }} + arguments: --repository ${{ matrix.repo }} --output-path provenance.att --digest ${{ matrix.container.digest }} --tags ${{ join(matrix.container.tags, ',') }} env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" @@ -270,14 +286,14 @@ jobs: - name: Attach provenance to image run: | echo '${{ secrets.COSIGN_PRIVATE_KEY }}' > cosign.key - cosign attest --predicate provenance-predicate.att --type slsaprovenance --key cosign.key ${{ matrix.repo }}@${{ needs.release.outputs.container_digest }} + cosign attest --predicate provenance-predicate.att --type slsaprovenance --key cosign.key ${{ matrix.repo }}@${{ matrix.container.digest }} env: COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} - name: Verify attestation run: | echo '${{ secrets.COSIGN_PUBLIC_KEY }}' > cosign.pub - cosign verify-attestation --key cosign.pub ${{ matrix.repo }}@${{ needs.release.outputs.container_digest }} + cosign verify-attestation --key cosign.pub ${{ matrix.repo }}@${{ matrix.container.digest }} - name: Logout from Container registries if: ${{ always() }} diff --git a/.goreleaser.draft.yml b/.goreleaser.draft.yml index 10756c1b..1eb152e1 100644 --- a/.goreleaser.draft.yml +++ b/.goreleaser.draft.yml @@ -6,6 +6,10 @@ before: env: - CGO_ENABLED=0 + - DOCKER_CLI_EXPERIMENTAL=enabled + +checksum: + name_template: 'checksums.txt' builds: - id: binary @@ -44,19 +48,40 @@ sboms: - "${artifact}.sbom.json" artifacts: archive -checksum: - name_template: 'checksums.txt' - dockers: - goos: linux goarch: amd64 + use: buildx + image_templates: + - "ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-amd64" + - "philipssoftware/{{ .ProjectName }}:v{{ .Version }}-amd64" + build_flag_templates: + - "--pull" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.description={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version=v{{.Version}}" + - "--label=org.opencontainers.image.licenses=MIT" + - "--label=org.opencontainers.image.vendor=Koninklijke Philips N.V." + extra_files: + - "Makefile" + - "go.mod" + - "go.sum" + - ".git" + - ".gitignore" + - "cmd" + - "lib" + - goos: linux + goarch: arm64 + use: buildx image_templates: - - "philipssoftware/{{ .ProjectName }}:v{{ .Version }}" - - "philipssoftware/{{ .ProjectName }}:{{ .FullCommit }}" - - "ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}" - - "ghcr.io/philips-labs/{{ .ProjectName }}:{{ .FullCommit }}" + - "ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-arm64v8" + - "philipssoftware/{{ .ProjectName }}:v{{ .Version }}-arm64v8" build_flag_templates: - "--pull" + - "--platform=linux/arm64/v8" - "--label=org.opencontainers.image.created={{.Date}}" - "--label=org.opencontainers.image.title={{.ProjectName}}" - "--label=org.opencontainers.image.description={{.ProjectName}}" @@ -73,6 +98,24 @@ dockers: - "cmd" - "lib" +docker_manifests: + - name_template: 'ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}' + image_templates: + - 'ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-amd64' + - 'ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-arm64v8' + - name_template: 'ghcr.io/philips-labs/{{ .ProjectName }}:{{ .FullCommit }}' + image_templates: + - 'ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-amd64' + - 'ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-arm64v8' + - name_template: 'philipssoftware/{{ .ProjectName }}:{{ .FullCommit }}' + image_templates: + - 'philipssoftware/{{ .ProjectName }}:v{{ .Version }}-amd64' + - 'philipssoftware/{{ .ProjectName }}:v{{ .Version }}-arm64v8' + - name_template: 'philipssoftware/{{ .ProjectName }}:v{{ .Version }}' + image_templates: + - 'philipssoftware/{{ .ProjectName }}:v{{ .Version }}-amd64' + - 'philipssoftware/{{ .ProjectName }}:v{{ .Version }}-arm64v8' + signs: - id: checksums cmd: cosign diff --git a/.goreleaser.yml b/.goreleaser.yml index 926ef5d3..cdd94ccd 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -6,6 +6,10 @@ before: env: - CGO_ENABLED=0 + - DOCKER_CLI_EXPERIMENTAL=enabled + +checksum: + name_template: 'checksums.txt' builds: - id: binary @@ -44,19 +48,40 @@ sboms: - "${artifact}.sbom.json" artifacts: archive -checksum: - name_template: 'checksums.txt' - dockers: - goos: linux goarch: amd64 + use: buildx + image_templates: + - "ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-amd64" + - "philipssoftware/{{ .ProjectName }}:v{{ .Version }}-amd64" + build_flag_templates: + - "--pull" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.description={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version=v{{.Version}}" + - "--label=org.opencontainers.image.licenses=MIT" + - "--label=org.opencontainers.image.vendor=Koninklijke Philips N.V." + extra_files: + - "Makefile" + - "go.mod" + - "go.sum" + - ".git" + - ".gitignore" + - "cmd" + - "lib" + - goos: linux + goarch: arm64 + use: buildx image_templates: - - "philipssoftware/{{ .ProjectName }}:v{{ .Version }}" - - "philipssoftware/{{ .ProjectName }}:{{ .FullCommit }}" - - "ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}" - - "ghcr.io/philips-labs/{{ .ProjectName }}:{{ .FullCommit }}" + - "ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-arm64v8" + - "philipssoftware/{{ .ProjectName }}:v{{ .Version }}-arm64v8" build_flag_templates: - "--pull" + - "--platform=linux/arm64/v8" - "--label=org.opencontainers.image.created={{.Date}}" - "--label=org.opencontainers.image.title={{.ProjectName}}" - "--label=org.opencontainers.image.description={{.ProjectName}}" @@ -73,6 +98,24 @@ dockers: - "cmd" - "lib" +docker_manifests: + - name_template: 'ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}' + image_templates: + - 'ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-amd64' + - 'ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-arm64v8' + - name_template: 'ghcr.io/philips-labs/{{ .ProjectName }}:{{ .FullCommit }}' + image_templates: + - 'ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-amd64' + - 'ghcr.io/philips-labs/{{ .ProjectName }}:v{{ .Version }}-arm64v8' + - name_template: 'philipssoftware/{{ .ProjectName }}:{{ .FullCommit }}' + image_templates: + - 'philipssoftware/{{ .ProjectName }}:v{{ .Version }}-amd64' + - 'philipssoftware/{{ .ProjectName }}:v{{ .Version }}-arm64v8' + - name_template: 'philipssoftware/{{ .ProjectName }}:v{{ .Version }}' + image_templates: + - 'philipssoftware/{{ .ProjectName }}:v{{ .Version }}-amd64' + - 'philipssoftware/{{ .ProjectName }}:v{{ .Version }}-arm64v8' + signs: - id: checksums cmd: cosign diff --git a/Makefile b/Makefile index 965eb4f1..b79661ff 100644 --- a/Makefile +++ b/Makefile @@ -96,15 +96,15 @@ image: ## build the binary in a docker image . $(GO_PATH)/bin/goreleaser: - go install github.com/goreleaser/goreleaser@v1.2.5 + go install github.com/goreleaser/goreleaser@v1.3.1 .PHONY: snapshot-release snapshot-release: $(GO_PATH)/bin/goreleaser ## creates a snapshot release using goreleaser - LDFLAGS=$(LDFLAGS) goreleaser release --snapshot --rm-dist + LDFLAGS=$(LDFLAGS) goreleaser release --snapshot --rm-dist --debug .PHONY: release release: $(GO_PATH)/bin/goreleaser ## creates a release using goreleaser - LDFLAGS=$(LDFLAGS) goreleaser release + LDFLAGS=$(LDFLAGS) goreleaser release --debug .PHONY: release-vars release-vars: ## print the release variables for goreleaser @@ -139,6 +139,11 @@ container-digest: ## retrieves the container digest from the given tag @:$(call check_defined, GITHUB_REF) @docker inspect $(GHCR_REPO):$(subst refs/tags/,,$(GITHUB_REF)) --format '{{ index .RepoDigests 0 }}' | cut -d '@' -f 2 +.PHONY: manifest-digest +manifest-digest: ## retrieves the container digest from the given tag + @:$(call check_defined, GITHUB_REF) + @docker manifest inspect $(GHCR_REPO):$(subst refs/tags/,,$(GITHUB_REF)) | grep digest | cut -d '"' -f 4 + .PHONY: container-tags container-tags: ## retrieves the container tags applied to the image with a given digest @:$(call check_defined, CONTAINER_DIGEST)