1212 IMAGE_NAME : ${{ github.repository }}
1313
1414jobs :
15- # Job for AMD64 architecture - runs on all events
16- build-amd64 :
15+ build :
1716 runs-on : ubuntu-latest
17+ strategy :
18+ matrix :
19+ platform : [linux/amd64, linux/arm64]
1820 permissions :
1921 contents : read
2022 packages : write
2123 steps :
2224 - name : Checkout repository
2325 uses : actions/checkout@v4
2426
27+ - name : Set up QEMU
28+ uses : docker/setup-qemu-action@v3
29+
2530 - name : Set up Docker Buildx
2631 uses : docker/setup-buildx-action@v3
2732 id : buildx
2833
2934 - name : Log in to the Container registry
35+ # Only login if we're pushing (not a PR)
3036 if : github.event_name != 'pull_request'
3137 uses : docker/login-action@v3
3238 with :
3339 registry : ${{ env.REGISTRY }}
3440 username : ${{ github.actor }}
3541 password : ${{ secrets.GITHUB_TOKEN }}
3642
37- - name : Extract metadata (tags, labels) for Docker
38- id : meta
39- uses : docker/metadata-action@v5
40- with :
41- images : ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
42- tags : |
43- type=ref,event=branch
44- type=ref,event=pr
45- type=semver,pattern={{version}}
46- type=semver,pattern={{major}}.{{minor}}
47- type=sha,format=long
48-
49- - name : Build and push AMD64 Docker image
50- id : build
51- uses : docker/build-push-action@v5
52- with :
53- context : .
54- push : ${{ github.event_name != 'pull_request' }}
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'
43+ - name : Extract platform short name
44+ id : platform
6545 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 }}
46+ # Extract the architecture from the platform (e.g., amd64 from linux/amd64)
47+ ARCH=$(echo "${{ matrix.platform }}" | cut -d/ -f2)
48+ echo "arch=${ARCH}" >> $GITHUB_OUTPUT
10249
10350 - name : Extract metadata (tags, labels) for Docker
10451 id : meta
@@ -107,64 +54,32 @@ jobs:
10754 images : ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
10855 tags : |
10956 type=ref,event=branch
57+ type=ref,event=pr
11058 type=semver,pattern={{version}}
11159 type=semver,pattern={{major}}.{{minor}}
11260 type=sha,format=long
11361
114- - name : Build and push ARM64 Docker image
115- id : build
62+ - name : Build and push Docker image
11663 uses : docker/build-push-action@v5
11764 with :
11865 context : .
119- push : true
120- tags : ${{ steps.meta.outputs.tags }}-arm64
66+ # Only push if not a PR
67+ push : ${{ github.event_name != 'pull_request' }}
68+ platforms : ${{ matrix.platform }}
69+ tags : ${{ steps.meta.outputs.tags }}-${{ steps.platform.outputs.arch }}
12170 labels : ${{ steps.meta.outputs.labels }}
122- platforms : linux/arm64
12371 cache-from : type=gha
12472 cache-to : type=gha,mode=max
125- 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
14273
143- # Job to create multi-architecture manifest
14474 create-manifest :
75+ # Skip this job for pull requests
76+ if : github.event_name != 'pull_request'
14577 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'
78+ needs : build
15079 permissions :
15180 contents : read
15281 packages : write
15382 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-
16883 - name : Set up Docker Buildx
16984 uses : docker/setup-buildx-action@v3
17085
@@ -182,31 +97,29 @@ jobs:
18297 images : ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
18398 tags : |
18499 type=ref,event=branch
100+ type=ref,event=pr
185101 type=semver,pattern={{version}}
186102 type=semver,pattern={{major}}.{{minor}}
187103 type=sha,format=long
188104
189- - name : Create manifest list and push
105+ - name : Create manifest lists and push
190106 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
107+ # Process each tag and create a manifest for it
108+ echo "${{ steps.meta.outputs.tags }}" | while read -r TAG; do
109+ if [ -n "$TAG" ]; then
110+ echo "Creating manifest for $TAG"
111+ docker buildx imagetools create \
112+ --tag $TAG \
113+ $TAG-amd64 \
114+ $TAG-arm64
115+ fi
116+ done
117+
118+ - name : Inspect images
210119 run : |
211- FIRST_TAG=$(echo "${{ steps.meta.outputs.tags }}" | cut -d, -f1)
212- docker buildx imagetools inspect ${FIRST_TAG}
120+ echo "${{ steps.meta.outputs.tags }}" | while read -r TAG; do
121+ if [ -n "$TAG" ]; then
122+ echo "Inspecting manifest for $TAG"
123+ docker buildx imagetools inspect $TAG
124+ fi
125+ done
0 commit comments