Skip to content

Commit 27822e1

Browse files
committed
feat: adding multi arch build workflow
1 parent 154285c commit 27822e1

2 files changed

Lines changed: 266 additions & 1 deletion

File tree

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
name: Build Multi-Arch Container
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
version:
7+
description: 'Image version tag (e.g. from prepare outputs)'
8+
required: true
9+
type: string
10+
image:
11+
description: 'Full image path without tag (e.g. ghcr.io/myorg/myimage)'
12+
required: true
13+
type: string
14+
registry:
15+
description: 'Container registry hostname for docker login'
16+
required: false
17+
default: 'ghcr.io'
18+
type: string
19+
dockerfile:
20+
description: 'Path to Dockerfile'
21+
required: false
22+
default: './Dockerfile'
23+
type: string
24+
context:
25+
description: 'Docker build context path'
26+
required: false
27+
default: '.'
28+
type: string
29+
architectures:
30+
description: 'Comma-separated architectures to build: amd64, arm64, armv7'
31+
required: false
32+
default: 'amd64,arm64,armv7'
33+
type: string
34+
build_args:
35+
description: 'Additional Docker build arguments (multiline key=value). COMMIT_HASH, GIT_BRANCH, BUILD_TIMESTAMP, VERSION are always injected.'
36+
required: false
37+
default: ''
38+
type: string
39+
build_args_amd64:
40+
description: 'Extra build arguments injected only into the amd64 build job.'
41+
required: false
42+
default: ''
43+
type: string
44+
build_args_arm64:
45+
description: 'Extra build arguments injected only into the arm64 build job.'
46+
required: false
47+
default: ''
48+
type: string
49+
build_args_armv7:
50+
description: 'Extra build arguments injected only into the armv7 build job.'
51+
required: false
52+
default: ''
53+
type: string
54+
push_latest:
55+
description: 'Push a :latest tag when building from the main branch'
56+
required: false
57+
default: true
58+
type: boolean
59+
runner_amd64:
60+
description: 'Runner label for amd64 native builds'
61+
required: false
62+
default: 'arc-runner-set-amd64'
63+
type: string
64+
runner_arm64:
65+
description: 'Runner label for arm64 native builds'
66+
required: false
67+
default: 'arc-runner-set-arm64'
68+
type: string
69+
outputs:
70+
digest_amd64:
71+
description: 'Image digest for amd64'
72+
value: ${{ jobs.build-amd64.outputs.digest }}
73+
digest_arm64:
74+
description: 'Image digest for arm64'
75+
value: ${{ jobs.build-arm64.outputs.digest }}
76+
digest_armv7:
77+
description: 'Image digest for armv7'
78+
value: ${{ jobs.build-armv7.outputs.digest }}
79+
80+
jobs:
81+
# ============================================================================
82+
# Per-architecture builds (run natively on matching runners; armv7 cross-compiles from amd64)
83+
# ============================================================================
84+
build-amd64:
85+
if: contains(inputs.architectures, 'amd64')
86+
runs-on: ${{ inputs.runner_amd64 }}
87+
permissions:
88+
contents: read
89+
packages: write
90+
outputs:
91+
digest: ${{ steps.build.outputs.digest }}
92+
steps:
93+
- name: Checkout
94+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
95+
96+
- name: Get build metadata
97+
id: meta
98+
run: |
99+
echo "commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
100+
echo "git_branch=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
101+
echo "build_timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
102+
103+
- name: Set up Docker Buildx
104+
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
105+
106+
- name: Login to registry
107+
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
108+
with:
109+
registry: ${{ inputs.registry }}
110+
username: ${{ github.actor }}
111+
password: ${{ secrets.GITHUB_TOKEN }}
112+
113+
- name: Build and push
114+
id: build
115+
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
116+
with:
117+
context: ${{ inputs.context }}
118+
file: ${{ inputs.dockerfile }}
119+
platforms: linux/amd64
120+
push: true
121+
tags: ${{ inputs.image }}:${{ inputs.version }}-amd64
122+
build-args: |
123+
COMMIT_HASH=${{ steps.meta.outputs.commit_hash }}
124+
GIT_BRANCH=${{ steps.meta.outputs.git_branch }}
125+
BUILD_TIMESTAMP=${{ steps.meta.outputs.build_timestamp }}
126+
VERSION=${{ inputs.version }}
127+
${{ inputs.build_args }}
128+
${{ inputs.build_args_amd64 }}
129+
130+
build-arm64:
131+
if: contains(inputs.architectures, 'arm64')
132+
runs-on: ${{ inputs.runner_arm64 }}
133+
permissions:
134+
contents: read
135+
packages: write
136+
outputs:
137+
digest: ${{ steps.build.outputs.digest }}
138+
steps:
139+
- name: Checkout
140+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
141+
142+
- name: Get build metadata
143+
id: meta
144+
run: |
145+
echo "commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
146+
echo "git_branch=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
147+
echo "build_timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
148+
149+
- name: Set up Docker Buildx
150+
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
151+
152+
- name: Login to registry
153+
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
154+
with:
155+
registry: ${{ inputs.registry }}
156+
username: ${{ github.actor }}
157+
password: ${{ secrets.GITHUB_TOKEN }}
158+
159+
- name: Build and push
160+
id: build
161+
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
162+
with:
163+
context: ${{ inputs.context }}
164+
file: ${{ inputs.dockerfile }}
165+
platforms: linux/arm64
166+
push: true
167+
tags: ${{ inputs.image }}:${{ inputs.version }}-arm64
168+
build-args: |
169+
COMMIT_HASH=${{ steps.meta.outputs.commit_hash }}
170+
GIT_BRANCH=${{ steps.meta.outputs.git_branch }}
171+
BUILD_TIMESTAMP=${{ steps.meta.outputs.build_timestamp }}
172+
VERSION=${{ inputs.version }}
173+
${{ inputs.build_args }}
174+
${{ inputs.build_args_arm64 }}
175+
176+
build-armv7:
177+
# Cross-compile on amd64 — much faster than QEMU emulation on a native armv7 runner
178+
if: contains(inputs.architectures, 'armv7')
179+
runs-on: ${{ inputs.runner_amd64 }}
180+
permissions:
181+
contents: read
182+
packages: write
183+
outputs:
184+
digest: ${{ steps.build.outputs.digest }}
185+
steps:
186+
- name: Checkout
187+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
188+
189+
- name: Get build metadata
190+
id: meta
191+
run: |
192+
echo "commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
193+
echo "git_branch=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
194+
echo "build_timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
195+
196+
- name: Set up QEMU
197+
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4
198+
199+
- name: Set up Docker Buildx
200+
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
201+
202+
- name: Login to registry
203+
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
204+
with:
205+
registry: ${{ inputs.registry }}
206+
username: ${{ github.actor }}
207+
password: ${{ secrets.GITHUB_TOKEN }}
208+
209+
- name: Build and push
210+
id: build
211+
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
212+
with:
213+
context: ${{ inputs.context }}
214+
file: ${{ inputs.dockerfile }}
215+
platforms: linux/arm/v7
216+
push: true
217+
tags: ${{ inputs.image }}:${{ inputs.version }}-armv7
218+
build-args: |
219+
COMMIT_HASH=${{ steps.meta.outputs.commit_hash }}
220+
GIT_BRANCH=${{ steps.meta.outputs.git_branch }}
221+
BUILD_TIMESTAMP=${{ steps.meta.outputs.build_timestamp }}
222+
VERSION=${{ inputs.version }}
223+
${{ inputs.build_args }}
224+
${{ inputs.build_args_armv7 }}
225+
226+
# ============================================================================
227+
# Create multi-arch manifest combining all successfully built arch images
228+
# ============================================================================
229+
manifest:
230+
needs: [build-amd64, build-arm64, build-armv7]
231+
if: always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled')
232+
runs-on: ${{ inputs.runner_amd64 }}
233+
permissions:
234+
contents: read
235+
packages: write
236+
steps:
237+
- name: Set up Docker Buildx
238+
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
239+
240+
- name: Login to registry
241+
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
242+
with:
243+
registry: ${{ inputs.registry }}
244+
username: ${{ github.actor }}
245+
password: ${{ secrets.GITHUB_TOKEN }}
246+
247+
- name: Create and push manifest
248+
env:
249+
IMAGE: ${{ inputs.image }}
250+
VERSION: ${{ inputs.version }}
251+
RESULT_AMD64: ${{ needs.build-amd64.result }}
252+
RESULT_ARM64: ${{ needs.build-arm64.result }}
253+
RESULT_ARMV7: ${{ needs.build-armv7.result }}
254+
run: |
255+
IMAGES=""
256+
[ "${RESULT_AMD64}" == "success" ] && IMAGES="${IMAGES} ${IMAGE}:${VERSION}-amd64"
257+
[ "${RESULT_ARM64}" == "success" ] && IMAGES="${IMAGES} ${IMAGE}:${VERSION}-arm64"
258+
[ "${RESULT_ARMV7}" == "success" ] && IMAGES="${IMAGES} ${IMAGE}:${VERSION}-armv7"
259+
IMAGES="${IMAGES# }"
260+
261+
docker buildx imagetools create -t "${IMAGE}:${VERSION}" ${IMAGES}
262+
263+
if [ "${{ inputs.push_latest }}" == "true" ]; then
264+
docker buildx imagetools create -t "${IMAGE}:latest" ${IMAGES}
265+
fi
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ jobs:
9393
owner: ${{ github.repository_owner }}
9494

9595
- name: Checkout repository
96-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
96+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2.0.2
9797
with:
9898
ref: ${{ inputs.ref || github.ref }}
9999
# token: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)