52
52
run : |
53
53
docker run --rm ${{ env.TEST_TAG }} make ci-test
54
54
55
+ # Inspired to https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
55
56
build-arch :
56
57
runs-on : ${{ matrix.arch.runner }}
57
58
needs : test
64
65
strategy :
65
66
matrix :
66
67
arch :
67
- - platform : " amd64"
68
+ - platform : linux/ amd64
68
69
runner : ubuntu-latest
69
- - platform : " arm64"
70
+ - platform : linux/ arm64
70
71
# There is no latest for ARM yet
71
72
# https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
72
73
runner : ubuntu-24.04-arm
@@ -77,11 +78,14 @@ jobs:
77
78
# - dramatiq
78
79
steps :
79
80
# GitHub gives only repository complete in <owner>/<repo> format.
80
- # Need some manual sheanigans
81
+ # Need some manual shenanigans
81
82
# Set IMAGE_NAME so we can push to <owner>/<repo>/<image>
83
+ # Transform os/arch to os-arch for suffix target
82
84
- name : Set ENV variables
83
85
run : |
84
86
echo "IMAGE_NAME=${GITHUB_REPOSITORY#$GITHUB_REPOSITORY_OWNER/}" >> $GITHUB_ENV
87
+ platform=${{ matrix.platform }}
88
+ echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
85
89
86
90
- name : Checkout repository
87
91
uses : actions/checkout@v4
@@ -115,23 +119,116 @@ jobs:
115
119
${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }}
116
120
# generate Docker tags based on the following events/attributes
117
121
tags : |
118
- type=sha,suffix=${{ matrix.arch.platform }}
122
+ type=sha,suffix=- ${{ env.PLATFORM_PAIR }}
119
123
120
- # Build and push Docker image with Buildx
124
+ # Build and push Docker image with Buildx by digest
121
125
# https://github.com/docker/build-push-action
122
126
- name : Build and push production image
123
127
id : build-and-push
124
128
125
129
with :
126
130
context : .
127
131
target : ${{ matrix.docker_target }}
128
- platforms : linux/ ${{ matrix.arch.platform }}
129
- push : true
132
+ platforms : ${{ matrix.arch.platform }}
133
+ outputs : type=image,push-by-digest=true,name-canonical=true,push= true
130
134
tags : ${{ steps.meta.outputs.tags }}
131
135
labels : ${{ steps.meta.outputs.labels }}
132
136
cache-from : type=gha
133
137
cache-to : type=gha,mode=max
134
138
139
+ - name : Export digest
140
+ run : |
141
+ mkdir -p ${{ runner.temp }}/digests/${{ matrix.docker_target }}
142
+ digest="${{ steps.build.outputs.digest }}"
143
+ touch "${{ runner.temp }}/digests/${{ matrix.docker_target }}/${digest#sha256:}"
144
+
145
+ - name : Upload digest
146
+ uses : actions/upload-artifact@v4
147
+ with :
148
+ name : digests-${{ env.PLATFORM_PAIR }}
149
+ path : ${{ runner.temp }}/digests/*
150
+ if-no-files-found : error
151
+ retention-days : 1
152
+
153
+
154
+ aggregate-manifests :
155
+ runs-on : ubuntu-latest
156
+ needs : build-arch
157
+ permissions :
158
+ contents : read
159
+ packages : write
160
+ # This is used to complete the identity challenge
161
+ # with sigstore/fulcio when running outside of PRs.
162
+ id-token : write
163
+ strategy :
164
+ matrix :
165
+ docker_target :
166
+ # - migrations
167
+ - http
168
+ # - socketio
169
+ # - dramatiq
170
+
171
+ steps :
172
+ # GitHub gives only repository complete in <owner>/<repo> format.
173
+ # Need some manual sheanigans
174
+ # Set IMAGE_NAME so we can push to <owner>/<repo>/<image>
175
+ - name : Set ENV variables
176
+ run : |
177
+ echo "IMAGE_NAME=${GITHUB_REPOSITORY#$GITHUB_REPOSITORY_OWNER/}" >> $GITHUB_ENV
178
+
179
+ - name : Download digests
180
+ uses : actions/download-artifact@v4
181
+ with :
182
+ path : ${{ runner.temp }}/digests/${{ matrix.docker_target }}
183
+ pattern : digests-*
184
+ merge-multiple : true
185
+
186
+ - name : Checkout repository
187
+ uses : actions/checkout@v4
188
+
189
+ # Install the cosign tool
190
+ # https://github.com/sigstore/cosign-installer
191
+ - name : Install cosign
192
+
193
+
194
+ - name : Setup Docker buildx
195
+
196
+
197
+ # Login against a Docker registry
198
+ # https://github.com/docker/login-action
199
+ - name : Log into registry ${{ env.REGISTRY }}
200
+
201
+ with :
202
+ registry : ${{ env.REGISTRY }}
203
+ username : ${{ github.actor }}
204
+ password : ${{ secrets.GITHUB_TOKEN }}
205
+
206
+ # Extract metadata (tags, labels) for Docker
207
+ # https://github.com/docker/metadata-action
208
+ - name : Extract Docker metadata
209
+ id : meta
210
+
211
+ with :
212
+ # list of Docker images to use as base name for tags
213
+ # <registry/<owner>/<repo_name>/<repo_name>-<target>
214
+ images : |
215
+ ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }}
216
+ # generate Docker tags based on the following events/attributes
217
+ tags : |
218
+ type=sha
219
+ type=raw,value={{branch}}-latest
220
+ type=raw,value={{branch}}-{{date 'YYYYMMDDHHmmss'}}
221
+
222
+ - name : Create manifest list and push
223
+ working-directory : ${{ runner.temp }}/digests
224
+ run : |
225
+ docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
226
+ $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
227
+
228
+ - name : Inspect image
229
+ run : |
230
+ docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
231
+
135
232
# TODO: Implement signature using generated key: https://docs.sigstore.dev/signing/quickstart/#signing-with-a-generated-key
136
233
137
234
# Sign the resulting Docker image digest except on PRs.
0 commit comments