@@ -3,21 +3,32 @@ name: Build / Test / Push
33on :
44 push :
55 branches :
6- - ' *'
6+ - ' **'
7+ workflow_call :
78 workflow_dispatch :
89
10+ env :
11+ BUILD_SUFFIX : -build-${{ github.run_id }}_${{ github.run_attempt }}
12+ DOCKER_METADATA_SET_OUTPUT_ENV : ' true'
13+
914jobs :
1015 build :
11- runs-on : ubuntu-latest
16+ runs-on : ${{ matrix.runner }}
1217 outputs :
13- build-image : ${{ steps.build-meta.outputs.tags }}
18+ build-image-arm : ${{ steps.gen-output.outputs.image-arm64 }}
19+ build-image-x64 : ${{ steps.gen-output.outputs.image-x64 }}
20+ strategy :
21+ fail-fast : false
22+ matrix :
23+ include :
24+ - platform : linux/amd64
25+ runner : ubuntu-24.04
26+ - platform : linux/arm64
27+ runner : ubuntu-24.04-arm
1428 steps :
1529 - name : Checkout code
1630 uses : actions/checkout@v4
1731
18- - name : Set up QEMU
19- uses : docker/setup-qemu-action@v3
20-
2132 - name : Set up Docker Buildx
2233 uses : docker/setup-buildx-action@v3
2334
@@ -28,37 +39,105 @@ jobs:
2839 username : ${{ github.actor }}
2940 password : ${{ secrets.GITHUB_TOKEN }}
3041
31- - name : Produce the build image tag
32- id : build-meta
42+ - id : build-meta
43+ name : Docker meta
44+ uses : docker/metadata-action@v5
45+ with :
46+ images : ghcr.io/${{ github.repository }}
47+ tags : type=sha,suffix=${{ env.BUILD_SUFFIX }}
48+
49+ # Build cache is shared among all builds of the same architecture
50+ - id : cache-meta
51+ name : Docker meta
3352 uses : docker/metadata-action@v5
3453 with :
3554 images : ghcr.io/${{ github.repository }}
36- tags : type=sha,suffix=-build-${{ github.run_id }}_${{ github.run_attempt }}
55+ tags : type=raw,value=buildcache-${{ runner.arch }}
56+
57+ - id : get-registry
58+ name : Get the sanitized registry name
59+ run : |
60+ echo "registry=$(echo '${{ steps.build-meta.outputs.tags }}' | cut -f1 -d:)" | tee -a "$GITHUB_OUTPUT"
61+
62+ - id : set_build_url
63+ name : Set BUILD_URL
64+ run : |
65+ echo "build_url=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" | tee -a "$GITHUB_OUTPUT"
3766
38- - name : Build and push the untested image
67+ - id : build
68+ name : Build/push the arch-specific image
3969 uses : docker/build-push-action@v6
4070 with :
41- push : true
71+ platforms : ${{ matrix.platform }}
72+ build-args : |
73+ BUILD_TIMESTAMP=${{ github.event.repository.updated_at }}
74+ BUILD_URL=${{ steps.set_build_url.outputs.build_url }}
75+ GIT_REF_NAME=${{ github.ref_name }}
76+ GIT_SHA=${{ github.sha }}
77+ GIT_REPOSITORY_URL=${{ github.repositoryUrl }}
78+ cache-from : type=registry,ref=${{ steps.cache-meta.outputs.tags }}
79+ cache-to : type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
4280 labels : ${{ steps.build-meta.outputs.labels }}
43- tags : ${{ steps.build-meta.outputs.tags }}
44- provenance : true
45- cache-from : type=gha
46- cache-to : type=gha
81+ provenance : mode=max
82+ sbom : true
83+ tags : ${{ steps.get-registry.outputs.registry }}
84+ outputs : type=image,push-by-digest=true,push=true
85+
86+ - id : gen-output
87+ name : Write arch-specific image digest to outputs
88+ run : |
89+ echo "image-${RUNNER_ARCH,,}=${{ steps.get-registry.outputs.registry }}@${{ steps.build.outputs.digest }}" | tee -a "$GITHUB_OUTPUT"
90+
91+ merge :
92+ runs-on : ubuntu-24.04
93+ needs :
94+ - build
95+ env :
96+ DOCKER_APP_IMAGE_ARM64 : ${{ needs.build.outputs.build-image-arm }}
97+ DOCKER_APP_IMAGE_X64 : ${{ needs.build.outputs.build-image-x64 }}
98+ outputs :
99+ build-image : ${{ steps.meta.outputs.tags }}
100+ build-image-arm : ${{ needs.build.outputs.build-image-arm }}
101+ build-image-x64 : ${{ needs.build.outputs.build-image-x64 }}
102+ steps :
103+ - name : Checkout code
104+ uses : actions/checkout@v4
105+
106+ - name : Set up Docker Buildx
107+ uses : docker/setup-buildx-action@v3
108+
109+ - name : Login to GitHub Container Registry
110+ uses : docker/login-action@v3
111+ with :
112+ registry : ghcr.io
113+ username : ${{ github.actor }}
114+ password : ${{ secrets.GITHUB_TOKEN }}
115+
116+ - name : Docker meta
117+ id : meta
118+ uses : docker/metadata-action@v5
119+ with :
120+ images : ghcr.io/${{ github.repository }}
121+ tags : |
122+ type=sha,suffix=-build-${{ github.run_id }}_${{ github.run_attempt }}
123+
124+ - name : Push the multi-platform image
125+ run : |
126+ docker buildx imagetools create \
127+ --tag "$DOCKER_METADATA_OUTPUT_TAGS" \
128+ "$DOCKER_APP_IMAGE_ARM64" "$DOCKER_APP_IMAGE_X64"
47129
48130 test :
49- runs-on : ubuntu-latest
131+ runs-on : ubuntu-24.04
50132 needs :
51- - build
133+ - merge
52134 env :
53135 COMPOSE_FILE : docker-compose.yml:docker-compose.ci.yml
54- DOCKER_APP_IMAGE : ${{ needs.build .outputs.build-image }}
136+ DOCKER_APP_IMAGE : ${{ needs.merge .outputs.build-image }}
55137 steps :
56138 - name : Checkout code
57139 uses : actions/checkout@v4
58140
59- - name : Set up QEMU
60- uses : docker/setup-qemu-action@v3
61-
62141 - name : Set up Docker Compose
63142 uses : docker/setup-compose-action@v1
64143
@@ -102,14 +181,21 @@ jobs:
102181 if-no-files-found : error
103182
104183 push :
105- runs-on : ubuntu-latest
184+ runs-on : ubuntu-24.04
106185 needs :
107- - build
186+ - merge
108187 - test
188+ env :
189+ DOCKER_APP_IMAGE : ${{ needs.merge.outputs.build-image }}
190+ DOCKER_APP_IMAGE_ARM64 : ${{ needs.merge.outputs.build-image-arm }}
191+ DOCKER_APP_IMAGE_X64 : ${{ needs.merge.outputs.build-image-x64 }}
109192 steps :
110193 - name : Checkout code
111194 uses : actions/checkout@v4
112195
196+ - name : Set up Docker Buildx
197+ uses : docker/setup-buildx-action@v3
198+
113199 - name : Login to GitHub Container Registry
114200 uses : docker/login-action@v3
115201 with :
@@ -128,9 +214,6 @@ jobs:
128214 type=raw,value=latest,enable={{is_default_branch}}
129215
130216 - name : Retag and push the image
131- uses : docker/build-push-action@v6
132- with :
133- push : true
134- labels : ${{ steps.branch-meta.outputs.labels }}
135- tags : ${{ steps.branch-meta.outputs.tags }}
136- cache-from : type=registry,ref=${{ needs.build.outputs.build-image }}
217+ run : |
218+ docker buildx imagetools create \
219+ $(jq -cr '.tags | map("--tag " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") $DOCKER_APP_IMAGE_ARM64 $DOCKER_APP_IMAGE_X64
0 commit comments