Skip to content

Commit f0de8e8

Browse files
committed
CI: matrix build instead of QEMU
1 parent bf49bb2 commit f0de8e8

File tree

1 file changed

+72
-42
lines changed

1 file changed

+72
-42
lines changed

.github/workflows/docker-image.yml

Lines changed: 72 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,33 @@ name: Publish Docker image
33
on:
44
release:
55
types: [published]
6-
push:
7-
branches:
8-
- "*"
6+
push:
7+
branches: ["*"]
98
pull_request: {}
109

10+
permissions:
11+
packages: write
12+
contents: write
13+
attestations: write
14+
id-token: write
15+
1116
jobs:
12-
push_to_registry:
13-
name: Build (and push if publishing release)
14-
runs-on: ubuntu-latest
15-
permissions:
16-
packages: write
17-
contents: write
18-
attestations: write
19-
id-token: write
17+
build:
18+
name: Build ${{ matrix.platform }}
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
include:
23+
- arch: amd64
24+
platform: linux/amd64
25+
runner: ubuntu-latest
26+
tag_suffix: -amd64
27+
- arch: arm64
28+
platform: linux/arm64
29+
runner: ubuntu-24.04-arm
30+
tag_suffix: -arm64
31+
32+
runs-on: ${{ matrix.runner }}
2033

2134
steps:
2235
- name: Check out the repo
@@ -25,70 +38,86 @@ jobs:
2538
lfs: 'true'
2639
submodules: 'recursive'
2740

28-
# Only log in when we actually intend to push (release event).
2941
- name: Log in to Docker Hub
3042
if: github.event_name == 'release'
31-
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
43+
uses: docker/login-action@v3
3244
with:
3345
username: ${{ secrets.DOCKERHUB_USERNAME }}
3446
password: ${{ secrets.DOCKERHUB_PASSWORD }}
3547

36-
# Multi-arch setup only needed for release builds.
37-
- name: Set up QEMU (release only)
38-
if: github.event_name == 'release'
39-
uses: docker/setup-qemu-action@v3
40-
41-
- name: Set up Docker Buildx (release only)
42-
if: github.event_name == 'release'
43-
uses: docker/setup-buildx-action@v3
44-
45-
- name: Extract metadata (tags, labels) for Docker
48+
- name: Extract metadata (tags, labels)
4649
id: meta
47-
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
50+
uses: docker/metadata-action@v5
4851
with:
4952
images: alloverse/alloplace3
5053

51-
# Validation build for pushes/PRs: single-arch, no push.
52-
- name: Build Docker image (validation, no push)
54+
# Validation builds (push/PR): single-arch, no push
55+
- name: Build image (validation only, no push)
5356
if: github.event_name != 'release'
54-
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
57+
uses: docker/build-push-action@v6
5558
with:
5659
context: .
5760
file: ./Dockerfile
61+
platforms: ${{ matrix.platform }}
5862
push: false
59-
platforms: linux/amd64
6063
tags: ${{ steps.meta.outputs.tags }}
6164
labels: ${{ steps.meta.outputs.labels }}
6265

63-
# Release build: multi-platform and pushed.
64-
- name: Build & push Docker image (multi-platform, release)
66+
# Release builds: push single-arch image with suffix
67+
- name: Build & push image (release)
6568
if: github.event_name == 'release'
66-
id: push
67-
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
69+
id: push_single
70+
uses: docker/build-push-action@v6
6871
with:
6972
context: .
7073
file: ./Dockerfile
71-
platforms: linux/amd64,linux/arm64
74+
platforms: ${{ matrix.platform }}
7275
push: true
73-
tags: ${{ steps.meta.outputs.tags }}
76+
provenance: false
77+
sbom: false
78+
tags: alloverse/alloplace3:${{ github.event.release.tag_name }}${{ matrix.tag_suffix }}
7479
labels: ${{ steps.meta.outputs.labels }}
7580

76-
# Attestation only makes sense when an image was pushed.
81+
publish_manifest:
82+
name: Create multi-arch tag(s), attest, & update notes
83+
needs: build
84+
if: github.event_name == 'release'
85+
runs-on: ubuntu-latest
86+
steps:
87+
- name: Log in to Docker Hub
88+
uses: docker/login-action@v3
89+
with:
90+
username: ${{ secrets.DOCKERHUB_USERNAME }}
91+
password: ${{ secrets.DOCKERHUB_PASSWORD }}
92+
93+
- name: Create multi-arch manifest (tag + latest)
94+
run: |
95+
IMAGE=alloverse/alloplace3:${{ github.event.release.tag_name }}
96+
docker buildx imagetools create \
97+
-t "${IMAGE}" \
98+
-t alloverse/alloplace3:latest \
99+
"${IMAGE}-amd64" \
100+
"${IMAGE}-arm64"
101+
102+
- name: Inspect manifest (get digest)
103+
id: insp
104+
run: |
105+
IMAGE=alloverse/alloplace3:${{ github.event.release.tag_name }}
106+
docker buildx imagetools inspect --raw "$IMAGE" | sha256sum | awk '{print "sha256:"$1}' > digest.txt
107+
echo "digest=$(cat digest.txt)" >> $GITHUB_OUTPUT
108+
77109
- name: Generate artifact attestation
78-
if: github.event_name == 'release'
79110
uses: actions/attest-build-provenance@v2
80111
with:
81112
subject-name: index.docker.io/alloverse/alloplace3
82-
subject-digest: ${{ steps.push.outputs.digest }}
113+
subject-digest: ${{ steps.insp.outputs.digest }}
83114
push-to-registry: true
84115

85-
# Append Docker image info to the release notes
86116
- name: Update release notes with Docker instructions
87-
if: github.event_name == 'release'
88117
uses: actions/github-script@v7
89118
env:
90119
IMAGE_BASE: alloverse/alloplace3
91-
IMAGE_DIGEST: ${{ steps.push.outputs.digest }}
120+
IMAGE_DIGEST: ${{ steps.insp.outputs.digest }}
92121
with:
93122
script: |
94123
const rel = context.payload.release;
@@ -102,11 +131,12 @@ jobs:
102131
'',
103132
'```bash',
104133
`docker pull ${image}`,
134+
`docker pull ${process.env.IMAGE_BASE}:latest`,
105135
`docker run --rm -it -p 9080:9080 ${image}`,
106136
'```',
107137
'',
108-
'Multi-arch: `linux/amd64, linux/arm64`.',
109-
process.env.IMAGE_DIGEST ? `Digest: \`${process.env.IMAGE_DIGEST}\`.` : '',
138+
'Architectures: `linux/amd64, linux/arm64`.',
139+
process.env.IMAGE_DIGEST ? `Manifest digest: \`${process.env.IMAGE_DIGEST}\`.` : '',
110140
''
111141
].join('\n');
112142
const body = (rel.body || '') + '\n\n' + snippet;

0 commit comments

Comments
 (0)