1212 IMAGE_NAME : ${{ github.repository }}
1313
1414jobs :
15- build-and-push :
15+ # Job for AMD64 architecture - runs on all events
16+ build-amd64 :
1617 runs-on : ubuntu-latest
1718 permissions :
1819 contents : read
1920 packages : write
20-
2121 steps :
2222 - name : Checkout repository
2323 uses : actions/checkout@v4
2424
2525 - name : Set up Docker Buildx
2626 uses : docker/setup-buildx-action@v3
27+ id : buildx
2728
2829 - name : Log in to the Container registry
30+ if : github.event_name != 'pull_request'
2931 uses : docker/login-action@v3
3032 with :
3133 registry : ${{ env.REGISTRY }}
@@ -44,14 +46,167 @@ jobs:
4446 type=semver,pattern={{major}}.{{minor}}
4547 type=sha,format=long
4648
47- - name : Build and push Docker image
49+ - name : Build and push AMD64 Docker image
50+ id : build
4851 uses : docker/build-push-action@v5
4952 with :
5053 context : .
5154 push : ${{ github.event_name != 'pull_request' }}
52- tags : ${{ steps.meta.outputs.tags }}
55+ tags : ${{ steps.meta.outputs.tags }}-amd64
56+ labels : ${{ steps.meta.outputs.labels }}
57+ platforms : linux/amd64
58+ cache-from : type=gha
59+ cache-to : type=gha,mode=max
60+ builder : ${{ steps.buildx.outputs.name }}
61+ outputs : type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
62+
63+ - name : Export AMD64 digest
64+ if : github.event_name != 'pull_request'
65+ run : |
66+ mkdir -p /tmp/digests
67+ digest="${{ steps.build.outputs.digest }}"
68+ touch "/tmp/digests/${digest#sha256:}"
69+ echo "AMD64_DIGEST=${digest}" >> $GITHUB_ENV
70+
71+ - name : Upload AMD64 digest
72+ if : github.event_name != 'pull_request'
73+ uses : actions/upload-artifact@v4
74+ with :
75+ name : amd64-digest
76+ path : /tmp/digests/*
77+ if-no-files-found : error
78+ retention-days : 1
79+
80+ # Job for ARM64 architecture - only runs on main branch
81+ build-arm64 :
82+ runs-on : ubuntu-latest
83+ permissions :
84+ contents : read
85+ packages : write
86+ # Only run this job for pushes to main, not for PRs
87+ if : github.event_name == 'push' && github.ref == 'refs/heads/main'
88+ steps :
89+ - name : Checkout repository
90+ uses : actions/checkout@v4
91+
92+ - name : Set up Docker Buildx
93+ uses : docker/setup-buildx-action@v3
94+ id : buildx
95+
96+ - name : Log in to the Container registry
97+ uses : docker/login-action@v3
98+ with :
99+ registry : ${{ env.REGISTRY }}
100+ username : ${{ github.actor }}
101+ password : ${{ secrets.GITHUB_TOKEN }}
102+
103+ - name : Extract metadata (tags, labels) for Docker
104+ id : meta
105+ uses : docker/metadata-action@v5
106+ with :
107+ images : ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
108+ tags : |
109+ type=ref,event=branch
110+ type=semver,pattern={{version}}
111+ type=semver,pattern={{major}}.{{minor}}
112+ type=sha,format=long
113+
114+ - name : Build and push ARM64 Docker image
115+ id : build
116+ uses : docker/build-push-action@v5
117+ with :
118+ context : .
119+ push : true
120+ tags : ${{ steps.meta.outputs.tags }}-arm64
53121 labels : ${{ steps.meta.outputs.labels }}
54- platforms : linux/amd64,linux/ arm64
122+ platforms : linux/arm64
55123 cache-from : type=gha
56124 cache-to : type=gha,mode=max
57125 builder : ${{ steps.buildx.outputs.name }}
126+ outputs : type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
127+
128+ - name : Export ARM64 digest
129+ run : |
130+ mkdir -p /tmp/digests
131+ digest="${{ steps.build.outputs.digest }}"
132+ touch "/tmp/digests/${digest#sha256:}"
133+ echo "ARM64_DIGEST=${digest}" >> $GITHUB_ENV
134+
135+ - name : Upload ARM64 digest
136+ uses : actions/upload-artifact@v4
137+ with :
138+ name : arm64-digest
139+ path : /tmp/digests/*
140+ if-no-files-found : error
141+ retention-days : 1
142+
143+ # Job to create multi-architecture manifest
144+ create-manifest :
145+ runs-on : ubuntu-latest
146+ needs : [build-amd64, build-arm64]
147+ # This job only runs if at least build-amd64 completed successfully
148+ # build-arm64 might be skipped for PRs, so we don't require it
149+ if : github.event_name != 'pull_request' && always() && needs.build-amd64.result == 'success'
150+ permissions :
151+ contents : read
152+ packages : write
153+ steps :
154+ - name : Download AMD64 digest
155+ uses : actions/download-artifact@v4
156+ with :
157+ name : amd64-digest
158+ path : /tmp/digests/amd64
159+
160+ - name : Download ARM64 digest
161+ # Only try to download ARM64 digest if the job ran
162+ if : needs.build-arm64.result == 'success'
163+ uses : actions/download-artifact@v4
164+ with :
165+ name : arm64-digest
166+ path : /tmp/digests/arm64
167+
168+ - name : Set up Docker Buildx
169+ uses : docker/setup-buildx-action@v3
170+
171+ - name : Log in to the Container registry
172+ uses : docker/login-action@v3
173+ with :
174+ registry : ${{ env.REGISTRY }}
175+ username : ${{ github.actor }}
176+ password : ${{ secrets.GITHUB_TOKEN }}
177+
178+ - name : Extract metadata (tags, labels) for Docker
179+ id : meta
180+ uses : docker/metadata-action@v5
181+ with :
182+ images : ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
183+ tags : |
184+ type=ref,event=branch
185+ type=semver,pattern={{version}}
186+ type=semver,pattern={{major}}.{{minor}}
187+ type=sha,format=long
188+
189+ - name : Create manifest list and push
190+ run : |
191+ # Get the first tag from meta outputs
192+ FIRST_TAG=$(echo "${{ steps.meta.outputs.tags }}" | cut -d, -f1)
193+
194+ # If ARM64 build was skipped, only use AMD64 digest
195+ if [ "${{ needs.build-arm64.result }}" != "success" ]; then
196+ AMD64_DIGEST=$(cat /tmp/digests/amd64/*)
197+ docker buildx imagetools create \
198+ --tag ${FIRST_TAG} \
199+ ${AMD64_DIGEST}
200+ else
201+ # Otherwise use both digests
202+ AMD64_DIGEST=$(cat /tmp/digests/amd64/*)
203+ ARM64_DIGEST=$(cat /tmp/digests/arm64/*)
204+ docker buildx imagetools create \
205+ --tag ${FIRST_TAG} \
206+ ${AMD64_DIGEST} ${ARM64_DIGEST}
207+ fi
208+
209+ - name : Inspect image
210+ run : |
211+ FIRST_TAG=$(echo "${{ steps.meta.outputs.tags }}" | cut -d, -f1)
212+ docker buildx imagetools inspect ${FIRST_TAG}
0 commit comments