Skip to content

Commit 1b28637

Browse files
committed
ci: migrate Docker builds to native GitHub ARM64 runners
Replace QEMU-emulated multi-platform builds with parallel native builds using ubuntu-24.04-arm runner. Drop unsupported linux/arm/v7 platform. Use docker/login-action and push-by-digest pattern with manifest merge for both ghcr.io and DockerHub registries.
1 parent 7a8ba8c commit 1b28637

2 files changed

Lines changed: 166 additions & 40 deletions

File tree

.github/workflows/ci.yml

Lines changed: 165 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -54,49 +54,175 @@ jobs:
5454
env:
5555
COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5656

57-
- name: set up QEMU
58-
uses: docker/setup-qemu-action@v4
57+
docker:
58+
needs: build
59+
if: github.event_name == 'push'
60+
strategy:
61+
fail-fast: false
62+
matrix:
63+
include:
64+
- platform: linux/amd64
65+
runner: ubuntu-latest
66+
artifact: linux-amd64
67+
- platform: linux/arm64
68+
runner: ubuntu-24.04-arm
69+
artifact: linux-arm64
70+
runs-on: ${{ matrix.runner }}
71+
permissions:
72+
contents: read
73+
packages: write
74+
75+
steps:
76+
- name: checkout
77+
uses: actions/checkout@v6
78+
with:
79+
persist-credentials: false
5980

6081
- name: set up Docker Buildx
61-
id: buildx
6282
uses: docker/setup-buildx-action@v4
6383

64-
- name: available platforms
65-
run: echo ${{ steps.buildx.outputs.platforms }}
84+
- name: login to ghcr.io
85+
uses: docker/login-action@v3
86+
with:
87+
registry: ghcr.io
88+
username: ${{ github.actor }}
89+
password: ${{ secrets.PKG_TOKEN }}
6690

67-
- name: build and deploy master image to ghcr.io and dockerhub
68-
if: ${{ github.ref == 'refs/heads/master' }}
69-
env:
70-
GITHUB_PACKAGE_TOKEN: ${{ secrets.PKG_TOKEN }}
71-
DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }}
72-
USERNAME: ${{ github.actor }}
73-
GITHUB_SHA: ${{ github.sha}}
74-
GITHUB_REF: ${{ github.ref}}
91+
- name: login to DockerHub
92+
uses: docker/login-action@v3
93+
with:
94+
username: ${{ github.actor }}
95+
password: ${{ secrets.DOCKER_HUB_TOKEN }}
96+
97+
- name: build and push to ghcr.io by digest
98+
id: build-ghcr
99+
uses: docker/build-push-action@v6
100+
with:
101+
context: .
102+
platforms: ${{ matrix.platform }}
103+
build-args: |
104+
CI=github
105+
GITHUB_SHA=${{ github.sha }}
106+
GIT_BRANCH=${{ github.ref_name }}
107+
outputs: type=image,name=ghcr.io/ukeeper/ukeeper-readability,push-by-digest=true,name-canonical=true,push=true
108+
109+
- name: build and push to DockerHub by digest
110+
id: build-dockerhub
111+
uses: docker/build-push-action@v6
112+
with:
113+
context: .
114+
platforms: ${{ matrix.platform }}
115+
build-args: |
116+
CI=github
117+
GITHUB_SHA=${{ github.sha }}
118+
GIT_BRANCH=${{ github.ref_name }}
119+
outputs: type=image,name=umputun/ukeeper-readability,push-by-digest=true,name-canonical=true,push=true
120+
121+
- name: export digests
75122
run: |
76-
ref="$(echo ${GITHUB_REF} | cut -d'/' -f3)"
77-
echo GITHUB_REF - $ref
78-
echo ${GITHUB_PACKAGE_TOKEN} | docker login ghcr.io -u ${USERNAME} --password-stdin
79-
echo ${DOCKER_HUB_TOKEN} | docker login -u ${USERNAME} --password-stdin
80-
docker buildx build --push \
81-
--build-arg CI=github --build-arg GITHUB_SHA=${GITHUB_SHA} --build-arg GIT_BRANCH=${ref} \
82-
--platform linux/amd64,linux/arm/v7,linux/arm64 \
83-
-t ghcr.io/ukeeper/ukeeper-readability:${ref} -t umputun/ukeeper-readability:${ref} .
84-
85-
- name: deploy tagged (latest) to ghcr.io and dockerhub
86-
if: ${{ startsWith(github.ref, 'refs/tags/') }}
87-
env:
88-
GITHUB_PACKAGE_TOKEN: ${{ secrets.PKG_TOKEN }}
89-
DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }}
90-
USERNAME: ${{ github.actor }}
91-
GITHUB_SHA: ${{ github.sha}}
92-
GITHUB_REF: ${{ github.ref}}
123+
mkdir -p /tmp/digests/ghcr /tmp/digests/dockerhub
124+
digest_ghcr="${{ steps.build-ghcr.outputs.digest }}"
125+
digest_dockerhub="${{ steps.build-dockerhub.outputs.digest }}"
126+
touch "/tmp/digests/ghcr/${digest_ghcr#sha256:}"
127+
touch "/tmp/digests/dockerhub/${digest_dockerhub#sha256:}"
128+
129+
- name: upload ghcr digest
130+
uses: actions/upload-artifact@v4
131+
with:
132+
name: digests-ghcr-${{ matrix.artifact }}
133+
path: /tmp/digests/ghcr/*
134+
retention-days: 1
135+
136+
- name: upload dockerhub digest
137+
uses: actions/upload-artifact@v4
138+
with:
139+
name: digests-dockerhub-${{ matrix.artifact }}
140+
path: /tmp/digests/dockerhub/*
141+
retention-days: 1
142+
143+
docker-merge:
144+
needs: docker
145+
runs-on: ubuntu-latest
146+
permissions:
147+
contents: read
148+
packages: write
149+
150+
steps:
151+
- name: download ghcr digests
152+
uses: actions/download-artifact@v4
153+
with:
154+
path: /tmp/digests/ghcr
155+
pattern: digests-ghcr-*
156+
merge-multiple: true
157+
158+
- name: download dockerhub digests
159+
uses: actions/download-artifact@v4
160+
with:
161+
path: /tmp/digests/dockerhub
162+
pattern: digests-dockerhub-*
163+
merge-multiple: true
164+
165+
- name: verify all digests present
166+
run: |
167+
for registry in ghcr dockerhub; do
168+
expected=2
169+
actual=$(find /tmp/digests/$registry -maxdepth 1 -type f | wc -l)
170+
if [ "$actual" -ne "$expected" ]; then
171+
echo "Expected $expected digests for $registry, found $actual"
172+
ls -la /tmp/digests/$registry
173+
exit 1
174+
fi
175+
done
176+
echo "All digests present"
177+
178+
- name: set up Docker Buildx
179+
uses: docker/setup-buildx-action@v4
180+
181+
- name: login to ghcr.io
182+
uses: docker/login-action@v3
183+
with:
184+
registry: ghcr.io
185+
username: ${{ github.actor }}
186+
password: ${{ secrets.PKG_TOKEN }}
187+
188+
- name: login to DockerHub
189+
uses: docker/login-action@v3
190+
with:
191+
username: ${{ github.actor }}
192+
password: ${{ secrets.DOCKER_HUB_TOKEN }}
193+
194+
- name: determine tags
195+
id: tags
196+
run: |
197+
ref="${GITHUB_REF#refs/*/}"
198+
ref="${ref//\//_}"
199+
echo "ref=${ref}" >> $GITHUB_OUTPUT
200+
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
201+
echo "is_tag=true" >> $GITHUB_OUTPUT
202+
else
203+
echo "is_tag=false" >> $GITHUB_OUTPUT
204+
fi
205+
206+
- name: create ghcr.io manifest and push
207+
working-directory: /tmp/digests/ghcr
208+
run: |
209+
ref="${{ steps.tags.outputs.ref }}"
210+
is_tag="${{ steps.tags.outputs.is_tag }}"
211+
tags="-t ghcr.io/ukeeper/ukeeper-readability:${ref}"
212+
if [[ "$is_tag" == "true" ]]; then
213+
tags="${tags} -t ghcr.io/ukeeper/ukeeper-readability:latest"
214+
fi
215+
docker buildx imagetools create ${tags} \
216+
$(printf 'ghcr.io/ukeeper/ukeeper-readability@sha256:%s ' *)
217+
218+
- name: create DockerHub manifest and push
219+
working-directory: /tmp/digests/dockerhub
93220
run: |
94-
ref="$(echo ${GITHUB_REF} | cut -d'/' -f3)"
95-
echo GITHUB_REF - $ref
96-
echo ${GITHUB_PACKAGE_TOKEN} | docker login ghcr.io -u ${USERNAME} --password-stdin
97-
echo ${DOCKER_HUB_TOKEN} | docker login -u umputun --password-stdin
98-
docker buildx build --push \
99-
--build-arg CI=github --build-arg GITHUB_SHA=${GITHUB_SHA} --build-arg GIT_BRANCH=${ref} \
100-
--platform linux/amd64,linux/arm/v7,linux/arm64 \
101-
-t ghcr.io/ukeeper/ukeeper-readability:${ref} -t ghcr.io/ukeeper/ukeeper-readability:latest \
102-
-t umputun/ukeeper-readability:${ref} -t umputun/ukeeper-readability:latest .
221+
ref="${{ steps.tags.outputs.ref }}"
222+
is_tag="${{ steps.tags.outputs.is_tag }}"
223+
tags="-t umputun/ukeeper-readability:${ref}"
224+
if [[ "$is_tag" == "true" ]]; then
225+
tags="${tags} -t umputun/ukeeper-readability:latest"
226+
fi
227+
docker buildx imagetools create ${tags} \
228+
$(printf 'umputun/ukeeper-readability@sha256:%s ' *)

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build
2-
FROM umputun/baseimage:buildgo-latest as build-backend
2+
FROM umputun/baseimage:buildgo-latest AS build-backend
33

44
ARG CI
55
ARG GITHUB_REF

0 commit comments

Comments
 (0)