5252 run : |
5353 docker run --rm ${{ env.TEST_TAG }} make ci-test
5454
55+ # Inspired to https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
5556 build-arch :
5657 runs-on : ${{ matrix.arch.runner }}
5758 needs : test
6465 strategy :
6566 matrix :
6667 arch :
67- - platform : " amd64"
68+ - platform : linux/ amd64
6869 runner : ubuntu-latest
69- - platform : " arm64"
70+ - platform : linux/ arm64
7071 # There is no latest for ARM yet
7172 # https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
7273 runner : ubuntu-24.04-arm
@@ -77,11 +78,14 @@ jobs:
7778# - dramatiq
7879 steps :
7980 # GitHub gives only repository complete in <owner>/<repo> format.
80- # Need some manual sheanigans
81+ # Need some manual shenanigans
8182 # Set IMAGE_NAME so we can push to <owner>/<repo>/<image>
83+ # Transform os/arch to os-arch for suffix target
8284 - name : Set ENV variables
8385 run : |
8486 echo "IMAGE_NAME=${GITHUB_REPOSITORY#$GITHUB_REPOSITORY_OWNER/}" >> $GITHUB_ENV
87+ platform=${{ matrix.platform }}
88+ echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
8589
8690 - name : Checkout repository
8791 uses : actions/checkout@v4
@@ -115,23 +119,116 @@ jobs:
115119 ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }}
116120 # generate Docker tags based on the following events/attributes
117121 tags : |
118- type=sha,suffix=${{ matrix.arch.platform }}
122+ type=sha,suffix=- ${{ env.PLATFORM_PAIR }}
119123
120- # Build and push Docker image with Buildx
124+ # Build and push Docker image with Buildx by digest
121125 # https://github.com/docker/build-push-action
122126 - name : Build and push production image
123127 id : build-and-push
124128125129 with :
126130 context : .
127131 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
130134 tags : ${{ steps.meta.outputs.tags }}
131135 labels : ${{ steps.meta.outputs.labels }}
132136 cache-from : type=gha
133137 cache-to : type=gha,mode=max
134138
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+
135232 # TODO: Implement signature using generated key: https://docs.sigstore.dev/signing/quickstart/#signing-with-a-generated-key
136233
137234 # Sign the resulting Docker image digest except on PRs.
0 commit comments