Skip to content

Commit 9b617f8

Browse files
committed
ci: split per-arch builds and aggregate with manifest (no QEMU)
1 parent 81064d6 commit 9b617f8

File tree

1 file changed

+77
-54
lines changed

1 file changed

+77
-54
lines changed

.github/workflows/docker-multi-arch.yml

Lines changed: 77 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -9,112 +9,135 @@ on:
99
default: ""
1010

1111
jobs:
12-
build:
13-
strategy:
14-
fail-fast: false
15-
matrix:
16-
include:
17-
- os: [self-hosted, Linux, X64]
18-
platform: linux/amd64
19-
- os: [self-hosted, macOS, ARM64]
20-
platform: linux/arm64
21-
runs-on: ${{ matrix.os }}
22-
12+
build-amd64:
13+
runs-on: [self-hosted, Linux, X64]
2314
permissions:
2415
contents: read
2516
packages: write
26-
2717
outputs:
2818
sha_tag: ${{ steps.meta.outputs.sha_tag }}
2919
date_tag: ${{ steps.meta.outputs.date_tag }}
3020
user_tag: ${{ steps.meta.outputs.user_tag }}
3121
image_name: ${{ steps.name.outputs.image_name }}
32-
3322
steps:
3423
- name: Checkout
3524
uses: actions/checkout@v4
36-
3725
- name: Set up Docker Buildx
3826
uses: docker/setup-buildx-action@v3
39-
4027
- name: Log in to GHCR
4128
uses: docker/login-action@v3
4229
with:
4330
registry: ghcr.io
4431
username: ${{ github.repository_owner }}
4532
password: ${{ secrets.GITHUB_TOKEN }}
46-
4733
- name: Set lowercase image name
4834
id: name
4935
run: |
5036
IMAGE_NAME_LOWERCASE=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')/rsafd-docker
5137
echo "image_name=$IMAGE_NAME_LOWERCASE" >> $GITHUB_OUTPUT
52-
5338
- name: Compute tags
5439
id: meta
5540
run: |
5641
DATE_TAG=$(date +'%Y%m%d')
57-
SHA_TAG=${GITHUB_SHA::12}
58-
USER_TAG="${{ github.event.inputs.tag }}"
59-
60-
echo "sha_tag=$SHA_TAG" >> $GITHUB_OUTPUT
61-
echo "date_tag=$DATE_TAG" >> $GITHUB_OUTPUT
62-
echo "user_tag=$USER_TAG" >> $GITHUB_OUTPUT
63-
echo "tags=ghcr.io/${{ steps.name.outputs.image_name }}:${SHA_TAG}" >> $GITHUB_OUTPUT
42+
SHA_TAG=${GITHUB_SHA::12}
43+
USER_TAG="${{ github.event.inputs.tag }}"
44+
echo "sha_tag=$SHA_TAG" >> $GITHUB_OUTPUT
45+
echo "date_tag=$DATE_TAG" >> $GITHUB_OUTPUT
46+
echo "user_tag=$USER_TAG" >> $GITHUB_OUTPUT
47+
- name: Build & Push (amd64)
48+
uses: docker/build-push-action@v5
49+
with:
50+
context: .
51+
# Rely on native host arch (amd64)
52+
tags: ghcr.io/${{ steps.name.outputs.image_name }}:${{ steps.meta.outputs.sha_tag }}-amd64
53+
push: true
54+
provenance: false
55+
sbom: false
56+
build-args: |
57+
GH_OWNER=${{ github.repository_owner }}
6458
65-
- name: Build & Push
59+
build-arm64:
60+
runs-on: [self-hosted, macOS, ARM64]
61+
permissions:
62+
contents: read
63+
packages: write
64+
outputs:
65+
sha_tag: ${{ steps.meta.outputs.sha_tag }}
66+
date_tag: ${{ steps.meta.outputs.date_tag }}
67+
user_tag: ${{ steps.meta.outputs.user_tag }}
68+
image_name: ${{ steps.name.outputs.image_name }}
69+
steps:
70+
- name: Checkout
71+
uses: actions/checkout@v4
72+
- name: Set up Docker Buildx
73+
uses: docker/setup-buildx-action@v3
74+
- name: Log in to GHCR
75+
uses: docker/login-action@v3
76+
with:
77+
registry: ghcr.io
78+
username: ${{ github.repository_owner }}
79+
password: ${{ secrets.GITHUB_TOKEN }}
80+
- name: Set lowercase image name
81+
id: name
82+
run: |
83+
IMAGE_NAME_LOWERCASE=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')/rsafd-docker
84+
echo "image_name=$IMAGE_NAME_LOWERCASE" >> $GITHUB_OUTPUT
85+
- name: Compute tags
86+
id: meta
87+
run: |
88+
DATE_TAG=$(date +'%Y%m%d')
89+
SHA_TAG=${GITHUB_SHA::12}
90+
USER_TAG="${{ github.event.inputs.tag }}"
91+
echo "sha_tag=$SHA_TAG" >> $GITHUB_OUTPUT
92+
echo "date_tag=$DATE_TAG" >> $GITHUB_OUTPUT
93+
echo "user_tag=$USER_TAG" >> $GITHUB_OUTPUT
94+
- name: Build & Push (arm64)
6695
uses: docker/build-push-action@v5
6796
with:
6897
context: .
69-
platforms: ${{ matrix.platform }}
70-
tags: ${{ steps.meta.outputs.tags }}
98+
# Native arm64 host build
99+
tags: ghcr.io/${{ steps.name.outputs.image_name }}:${{ steps.meta.outputs.sha_tag }}-arm64
71100
push: true
72101
provenance: false
73102
sbom: false
74103
build-args: |
75104
GH_OWNER=${{ github.repository_owner }}
76105
77-
create-manifest:
106+
manifest:
78107
runs-on: ubuntu-latest
79-
needs: build
108+
needs: [build-amd64, build-arm64]
80109
permissions:
81110
contents: read
82111
packages: write
83-
84112
steps:
85113
- name: Log in to GHCR
86114
uses: docker/login-action@v3
87115
with:
88116
registry: ghcr.io
89117
username: ${{ github.repository_owner }}
90118
password: ${{ secrets.GITHUB_TOKEN }}
91-
92-
- name: Create and push manifest list
119+
- name: Create multi-arch manifest tags
93120
run: |
94121
set -euo pipefail
95-
IMAGE=ghcr.io/${{ needs.build.outputs.image_name }}
96-
SHA_TAG=${{ needs.build.outputs.sha_tag }}
97-
DATE_TAG=${{ needs.build.outputs.date_tag }}
98-
USER_TAG=${{ needs.build.outputs.user_tag }}
99-
100-
# Re-tag the already-built image/manifest (single-arch or multi-arch) using imagetools.
101-
# This avoids attempting to create a manifest from an existing manifest list (which caused the failure).
102-
ARGS=(-t "$IMAGE:$DATE_TAG" -t "$IMAGE:latest")
103-
if [ -n "$USER_TAG" ]; then
104-
ARGS+=( -t "$IMAGE:$USER_TAG" )
105-
fi
106-
# Create new tags pointing to the same digest/manifest
107-
docker buildx imagetools create "${ARGS[@]}" "$IMAGE:$SHA_TAG"
108-
109-
echo "Retagged $IMAGE:$SHA_TAG as: $IMAGE:$DATE_TAG, $IMAGE:latest${USER_TAG:+, $IMAGE:$USER_TAG}"
110-
122+
IMAGE=ghcr.io/${{ needs.build-amd64.outputs.image_name }}
123+
SHA_TAG=${{ needs.build-amd64.outputs.sha_tag }}
124+
DATE_TAG=${{ needs.build-amd64.outputs.date_tag }}
125+
USER_TAG=${{ needs.build-amd64.outputs.user_tag }}
126+
SRC_AMD64=$IMAGE:${SHA_TAG}-amd64
127+
SRC_ARM64=$IMAGE:${SHA_TAG}-arm64
128+
if ! docker buildx imagetools inspect $SRC_AMD64 >/dev/null 2>&1; then echo "Missing $SRC_AMD64"; exit 1; fi
129+
if ! docker buildx imagetools inspect $SRC_ARM64 >/dev/null 2>&1; then echo "Missing $SRC_ARM64"; exit 1; fi
130+
ARGS=(-t $IMAGE:$SHA_TAG -t $IMAGE:$DATE_TAG -t $IMAGE:latest)
131+
if [ -n "$USER_TAG" ]; then ARGS+=( -t $IMAGE:$USER_TAG ); fi
132+
docker buildx imagetools create "${ARGS[@]}" $SRC_AMD64 $SRC_ARM64
133+
docker buildx imagetools inspect $IMAGE:$SHA_TAG
111134
- name: Summary
112135
run: |
113-
IMAGE=ghcr.io/${{ needs.build.outputs.image_name }}
114-
echo "Pushed manifests for:" >> $GITHUB_STEP_SUMMARY
115-
echo "$IMAGE:${{ needs.build.outputs.sha_tag }}" >> $GITHUB_STEP_SUMMARY
136+
IMAGE=ghcr.io/${{ needs.build-amd64.outputs.image_name }}
137+
echo "Published multi-arch tags:" >> $GITHUB_STEP_SUMMARY
138+
echo "$IMAGE:${{ needs.build-amd64.outputs.sha_tag }}" >> $GITHUB_STEP_SUMMARY
139+
echo "$IMAGE:${{ needs.build-amd64.outputs.date_tag }}" >> $GITHUB_STEP_SUMMARY
116140
echo "$IMAGE:latest" >> $GITHUB_STEP_SUMMARY
117-
echo "$IMAGE:${{ needs.build.outputs.date_tag }}" >> $GITHUB_STEP_SUMMARY
118-
if [ -n "${{ needs.build.outputs.user_tag }}" ]; then
119-
echo "$IMAGE:${{ needs.build.outputs.user_tag }}" >> $GITHUB_STEP_SUMMARY
141+
if [ -n "${{ needs.build-amd64.outputs.user_tag }}" ]; then
142+
echo "$IMAGE:${{ needs.build-amd64.outputs.user_tag }}" >> $GITHUB_STEP_SUMMARY
120143
fi

0 commit comments

Comments
 (0)