Skip to content

Commit 4958e9c

Browse files
committed
Refactor Docker publish workflow to support multi-platform builds
1 parent 6942367 commit 4958e9c

File tree

1 file changed

+101
-50
lines changed

1 file changed

+101
-50
lines changed
Lines changed: 101 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name: Docker
22

33
env:
4-
REPO_NAME: ${{ github.event.repository.name }}
54
# github.repository as <account>/<repo>
6-
IMAGE_NAME: ${{ github.repository }}
5+
DOCKERHUB_REPO: ${{ github.repository }}
6+
GHCR_REPO: ghcr.io/${{ github.repository }}
77

88
on:
99
pull_request:
@@ -25,84 +25,135 @@ on:
2525

2626
jobs:
2727
build:
28-
runs-on: ubuntu-latest
28+
runs-on: ${{ matrix.os }}
29+
strategy:
30+
fail-fast: false
31+
matrix:
32+
include:
33+
- os: ubuntu-24.04
34+
platform: linux/amd64
35+
- os: ubuntu-24.04-arm
36+
platform: linux/arm64
37+
2938
permissions:
3039
contents: read
3140
packages: write
32-
# This is used to complete the identity challenge
33-
# with sigstore/fulcio when running outside of PRs.
34-
id-token: write
3541

3642
steps:
43+
- name: Prepare
44+
run: |
45+
platform=${{ matrix.platform }}
46+
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
47+
48+
- name: Docker meta
49+
id: meta
50+
uses: docker/metadata-action@v5
51+
with:
52+
images: |
53+
${{ env.DOCKERHUB_REPO }}
54+
${{ env.GHCR_REPO }}
55+
3756
- name: Checkout repository
3857
uses: actions/checkout@v4
3958

40-
# Install the cosign tool except on PR
41-
# https://github.com/sigstore/cosign-installer
42-
- name: Install cosign
59+
- name: Log in to Docker Hub
4360
if: github.event_name != 'pull_request'
44-
uses: sigstore/cosign-installer@v3
61+
uses: docker/login-action@v3
62+
with:
63+
username: ${{ secrets.DOCKER_USERNAME }}
64+
password: ${{ secrets.DOCKER_PASSWORD }}
4565

46-
- name: Set up QEMU
47-
uses: docker/setup-qemu-action@v3
66+
- name: Login to GHCR
67+
if: github.event_name != 'pull_request'
68+
uses: docker/login-action@v3
69+
with:
70+
registry: ghcr.io
71+
username: ${{ github.actor }}
72+
password: ${{ secrets.GITHUB_TOKEN }}
4873

4974
- name: Setup Docker buildx
5075
uses: docker/setup-buildx-action@v3
5176

52-
# Login against a Docker registry except on PR
53-
# https://github.com/docker/login-action
54-
- name: Log in to Docker Hub
77+
- name: Build and push by digest
78+
id: build
79+
uses: docker/build-push-action@v6
80+
with:
81+
context: image/
82+
platforms: ${{ matrix.platform }}
83+
push: ${{ github.event_name != 'pull_request' }}
84+
labels: ${{ steps.meta.outputs.labels }}
85+
outputs: type=image,"name=${{ env.DOCKERHUB_REPO }},${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=true
86+
cache-from: type=gha
87+
cache-to: type=gha,mode=max
88+
89+
- name: Export digest
90+
run: |
91+
mkdir -p ${{ runner.temp }}/digests
92+
digest="${{ steps.build.outputs.digest }}"
93+
touch "${{ runner.temp }}/digests/${digest#sha256:}"
94+
95+
- name: Upload digest
96+
uses: actions/upload-artifact@v4
97+
with:
98+
name: digests-${{ env.PLATFORM_PAIR }}
99+
path: ${{ runner.temp }}/digests/*
100+
if-no-files-found: error
101+
retention-days: 1
102+
103+
merge:
104+
runs-on: ubuntu-24.04
105+
needs:
106+
- build
107+
steps:
108+
- name: Download digests
109+
uses: actions/download-artifact@v4
110+
with:
111+
path: ${{ runner.temp }}/digests
112+
pattern: digests-*
113+
merge-multiple: true
114+
115+
- name: Login to Docker Hub
55116
if: github.event_name != 'pull_request'
56117
uses: docker/login-action@v3
57118
with:
58119
username: ${{ secrets.DOCKER_USERNAME }}
59120
password: ${{ secrets.DOCKER_PASSWORD }}
60121

61-
# Login against a Docker registry except on PR
62-
# https://github.com/docker/login-action
63-
- name: Log in to the Container registry
122+
- name: Login to GHCR
64123
if: github.event_name != 'pull_request'
65124
uses: docker/login-action@v3
66125
with:
67126
registry: ghcr.io
68127
username: ${{ github.actor }}
69128
password: ${{ secrets.GITHUB_TOKEN }}
70129

71-
# Extract metadata (tags, labels) for Docker
72-
# https://github.com/docker/metadata-action
73-
- name: Extract Docker metadata
130+
- name: Set up Docker Buildx
131+
uses: docker/setup-buildx-action@v3
132+
133+
- name: Docker meta
74134
id: meta
75135
uses: docker/metadata-action@v5
76136
with:
77137
images: |
78-
${{ env.IMAGE_NAME }}
79-
ghcr.io/${{ env.IMAGE_NAME }}
138+
${{ env.DOCKERHUB_REPO }}
139+
${{ env.GHCR_REPO }}
140+
tags: |
141+
type=schedule,pattern={{date 'YYYY-MM-DD'}}
142+
type=ref,event=branch
143+
type=ref,event=tag
144+
type=ref,event=pr
80145
81-
# Build and push Docker image with Buildx (don't push on PR)
82-
# https://github.com/docker/build-push-action
83-
- name: Build and push Docker image
84-
id: build-and-push
85-
uses: docker/build-push-action@v6
86-
with:
87-
context: image/
88-
platforms: |-
89-
linux/amd64
90-
linux/arm64
91-
push: ${{ github.event_name != 'pull_request' }}
92-
tags: ${{ steps.meta.outputs.tags }}
93-
labels: ${{ steps.meta.outputs.labels }}
94-
cache-from: type=gha
95-
cache-to: type=gha,mode=max
146+
- name: Create manifest list and push
147+
if: github.event_name != 'pull_request'
148+
working-directory: ${{ runner.temp }}/digests
149+
run: |
150+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
151+
$(printf '${{ env.DOCKERHUB_REPO }}@sha256:%s ' *)
152+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
153+
$(printf '${{ env.GHCR_REPO }}@sha256:%s ' *)
96154
97-
# Sign the resulting Docker image digest except on PRs.
98-
# This will only write to the public Rekor transparency log when the Docker
99-
# repository is public to avoid leaking data. If you would like to publish
100-
# transparency data even for private images, pass --force to cosign below.
101-
# https://github.com/sigstore/cosign
102-
- name: Sign the published Docker image
103-
if: ${{ github.event_name != 'pull_request' }}
104-
env:
105-
COSIGN_EXPERIMENTAL: "true"
106-
# This step uses the identity token to provision an ephemeral certificate
107-
# against the sigstore community Fulcio instance.
108-
run: echo "${{ steps.meta.outputs.tags }}" | xargs -I {} cosign sign --yes {}@${{ steps.build-and-push.outputs.digest }}
155+
- name: Inspect image
156+
if: github.event_name != 'pull_request'
157+
run: |
158+
docker buildx imagetools inspect ${{ env.DOCKERHUB_REPO }}:${{ steps.meta.outputs.version }}
159+
docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ steps.meta.outputs.version }}

0 commit comments

Comments
 (0)