Skip to content

Commit c82fd45

Browse files
committed
ci: build multi-arch images via matrix and digest merge
1 parent 811f415 commit c82fd45

1 file changed

Lines changed: 96 additions & 15 deletions

File tree

.github/workflows/cicd.yml

Lines changed: 96 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,43 +106,124 @@ jobs:
106106
NODE_ENV: test
107107

108108
build:
109-
runs-on: ubuntu-24.04-arm
110109
permissions:
111110
contents: read
112111
packages: write
113112
id-token: write
113+
strategy:
114+
fail-fast: false
115+
matrix:
116+
include:
117+
- platform: linux/amd64
118+
runner: ubuntu-24.04
119+
platform_pair: amd64
120+
- platform: linux/arm64
121+
runner: ubuntu-24.04-arm
122+
platform_pair: arm64
123+
runs-on: ${{ matrix.runner }}
114124

115125
steps:
126+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
127+
with:
128+
persist-credentials: false
129+
130+
- name: Set lowercase image name
131+
id: image
132+
run: echo "name=ghcr.io/$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
133+
134+
- name: Set up Docker Buildx
135+
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
136+
137+
- name: Login to GHCR
138+
if: github.event_name == 'push'
139+
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
140+
with:
141+
registry: ghcr.io
142+
username: ${{ github.actor }}
143+
password: ${{ secrets.GITHUB_TOKEN }}
144+
116145
- name: Docker meta
117146
id: meta
118147
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
119148
with:
120-
images: |
121-
ghcr.io/${{ github.repository }}
122-
tags: |
123-
type=raw,value={{sha}}
124-
type=raw,value=latest
149+
images: ${{ steps.image.outputs.name }}
150+
151+
- name: Build and push by digest
152+
id: build
153+
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
154+
with:
155+
context: .
156+
platforms: ${{ matrix.platform }}
157+
labels: ${{ steps.meta.outputs.labels }}
158+
outputs: type=image,name=${{ steps.image.outputs.name }},push-by-digest=true,name-canonical=true,push=${{ github.event_name == 'push' }}
159+
cache-from: type=gha,scope=${{ matrix.platform_pair }}
160+
cache-to: type=gha,mode=max,scope=${{ matrix.platform_pair }}
161+
162+
- name: Export digest
163+
if: github.event_name == 'push'
164+
run: |
165+
mkdir -p /tmp/digests
166+
digest="${{ steps.build.outputs.digest }}"
167+
touch "/tmp/digests/${digest#sha256:}"
168+
169+
- name: Upload digest
170+
if: github.event_name == 'push'
171+
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v6.0.1
172+
with:
173+
name: digest-${{ matrix.platform_pair }}
174+
path: /tmp/digests/*
175+
if-no-files-found: error
176+
retention-days: 1
177+
178+
build-merge:
179+
if: github.event_name == 'push'
180+
needs: [build]
181+
runs-on: ubuntu-24.04
182+
permissions:
183+
contents: read
184+
packages: write
185+
186+
steps:
187+
- name: Set lowercase image name
188+
id: image
189+
run: echo "name=ghcr.io/$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
190+
191+
- name: Download digests
192+
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
193+
with:
194+
pattern: digest-*
195+
path: /tmp/digests
196+
merge-multiple: true
197+
198+
- name: Set up Docker Buildx
199+
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
125200

126201
- name: Login to GHCR
127-
if: github.ref == 'refs/heads/main'
128202
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
129203
with:
130204
registry: ghcr.io
131205
username: ${{ github.actor }}
132206
password: ${{ secrets.GITHUB_TOKEN }}
133207

134-
- name: Build and maybe Push Docker image
135-
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
208+
- name: Docker meta
209+
id: meta
210+
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
136211
with:
137-
push: ${{ github.ref == 'refs/heads/main' }}
138-
tags: ${{ steps.meta.outputs.tags }}
139-
labels: ${{ steps.meta.outputs.labels }}
140-
#cache-from: type=gha
141-
#cache-to: type=gha,mode=max
212+
images: ${{ steps.image.outputs.name }}
213+
tags: |
214+
type=raw,value={{sha}}
215+
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
216+
217+
- name: Create and push manifest
218+
working-directory: /tmp/digests
219+
run: |
220+
docker buildx imagetools create \
221+
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< '${{ steps.meta.outputs.json }}') \
222+
$(printf '${{ steps.image.outputs.name }}@sha256:%s ' *)
142223
143224
deploy:
144225
if: github.ref == 'refs/heads/main'
145-
needs: [lint, test, typecheck, build]
226+
needs: [lint, test, typecheck, build-merge]
146227
runs-on: ubuntu-slim
147228
environment:
148229
name: prod

0 commit comments

Comments
 (0)