@@ -17,13 +17,16 @@ concurrency:
1717 cancel-in-progress : false
1818
1919jobs :
20- publish :
20+ metadata :
2121 runs-on : blacksmith-4vcpu-ubuntu-2404
2222 permissions :
2323 contents : read
24- packages : write
25- env :
26- HAS_LEGACY_TOKEN : ${{ secrets.GHCR_LEGACY_TOKEN != '' }}
24+ outputs :
25+ release_tag : ${{ steps.validate.outputs.tag }}
26+ image : ${{ steps.image.outputs.image }}
27+ tags : ${{ steps.image.outputs.tags }}
28+ legacy_tags : ${{ steps.image.outputs.legacy_tags }}
29+ labels : ${{ steps.image.outputs.labels }}
2730
2831 steps :
2932 - name : Checkout
3841 bun-version : 1.3.11
3942
4043 - name : Validate release tag
44+ id : validate
4145 env :
4246 RAW_RELEASE_TAG : ${{ inputs.tag }}
43- run : bun run scripts/validate-release-ref.ts --tag-env RAW_RELEASE_TAG --write-env RELEASE_TAG
47+ run : bun run scripts/validate-release-ref.ts --tag-env RAW_RELEASE_TAG --write-env RELEASE_TAG --output tag
4448
4549 - name : Checkout release tag
4650 env :
9195 echo "LABELS"
9296 } >> "$GITHUB_OUTPUT"
9397
94- - name : Set up QEMU
95- uses : docker/setup-qemu-action@v3
98+ build :
99+ needs : metadata
100+ strategy :
101+ fail-fast : false
102+ matrix :
103+ include :
104+ - arch : amd64
105+ platform : linux/amd64
106+ runner : blacksmith-4vcpu-ubuntu-2404
107+ - arch : arm64
108+ platform : linux/arm64
109+ runner : blacksmith-4vcpu-ubuntu-2404-arm
110+ runs-on : ${{ matrix.runner }}
111+ permissions :
112+ contents : read
113+ packages : write
114+
115+ steps :
116+ - name : Checkout release tag
117+ uses : actions/checkout@v4
118+ with :
119+ ref : ${{ needs.metadata.outputs.release_tag }}
120+ fetch-depth : 0
121+ persist-credentials : false
96122
97123 - name : Setup Blacksmith Builder
98124 uses : useblacksmith/setup-docker-builder@v1
@@ -104,16 +130,94 @@ jobs:
104130 username : ${{ github.actor }}
105131 password : ${{ secrets.GITHUB_TOKEN }}
106132
107- - name : Build and push self-host image
133+ - name : Build and push self-host image by digest
108134 id : build
109135 uses : useblacksmith/build-push-action@v2
110136 with :
111137 context : .
112138 file : apps/host-selfhost/Dockerfile
113- platforms : linux/amd64,linux/arm64
114- push : true
115- tags : ${{ steps.image.outputs.tags }}
116- labels : ${{ steps.image.outputs.labels }}
139+ platforms : ${{ matrix.platform }}
140+ labels : ${{ needs.metadata.outputs.labels }}
141+ outputs : type=image,name=${{ needs.metadata.outputs.image }},push-by-digest=true,name-canonical=true,push=true
142+
143+ - name : Export image digest
144+ shell : bash
145+ env :
146+ DIGEST : ${{ steps.build.outputs.digest }}
147+ run : |
148+ set -euo pipefail
149+
150+ if [ -z "$DIGEST" ]; then
151+ echo "Build did not return a digest."
152+ exit 1
153+ fi
154+
155+ mkdir -p "$RUNNER_TEMP/digests"
156+ touch "$RUNNER_TEMP/digests/${DIGEST#sha256:}"
157+
158+ - name : Upload image digest
159+ uses : actions/upload-artifact@v4
160+ with :
161+ name : digests-${{ matrix.arch }}
162+ path : ${{ runner.temp }}/digests/*
163+ if-no-files-found : error
164+ retention-days : 1
165+
166+ merge :
167+ needs :
168+ - metadata
169+ - build
170+ runs-on : blacksmith-4vcpu-ubuntu-2404
171+ permissions :
172+ packages : write
173+ env :
174+ HAS_LEGACY_TOKEN : ${{ secrets.GHCR_LEGACY_TOKEN != '' }}
175+
176+ steps :
177+ - name : Download image digests
178+ uses : actions/download-artifact@v4
179+ with :
180+ pattern : digests-*
181+ path : ${{ runner.temp }}/digests
182+ merge-multiple : true
183+
184+ - name : Set up Docker Buildx
185+ uses : docker/setup-buildx-action@v3
186+
187+ - name : Log in to GHCR
188+ uses : docker/login-action@v3
189+ with :
190+ registry : ghcr.io
191+ username : ${{ github.actor }}
192+ password : ${{ secrets.GITHUB_TOKEN }}
193+
194+ - name : Publish multi-arch self-host image
195+ shell : bash
196+ env :
197+ IMAGE : ${{ needs.metadata.outputs.image }}
198+ TAGS : ${{ needs.metadata.outputs.tags }}
199+ run : |
200+ set -euo pipefail
201+
202+ sources=()
203+ while IFS= read -r digest_file; do
204+ digest="$(basename "$digest_file")"
205+ [[ -n "$digest" ]] || continue
206+ sources+=("${IMAGE}@sha256:${digest}")
207+ done < <(find "$RUNNER_TEMP/digests" -maxdepth 1 -type f | sort)
208+
209+ if [ "${#sources[@]}" -eq 0 ]; then
210+ echo "No image digests were downloaded."
211+ exit 1
212+ fi
213+
214+ tag_args=()
215+ while IFS= read -r tag; do
216+ [[ -n "$tag" ]] || continue
217+ tag_args+=("-t" "$tag")
218+ done <<< "$TAGS"
219+
220+ docker buildx imagetools create "${tag_args[@]}" "${sources[@]}"
117221
118222 - name : Skip legacy GHCR mirror (GHCR_LEGACY_TOKEN not configured)
119223 if : env.HAS_LEGACY_TOKEN != 'true'
@@ -131,8 +235,8 @@ jobs:
131235 if : env.HAS_LEGACY_TOKEN == 'true'
132236 shell : bash
133237 env :
134- SOURCE_IMAGE : ${{ steps.image .outputs.image }}@ ${{ steps.build .outputs.digest }}
135- LEGACY_TAGS : ${{ steps.image .outputs.legacy_tags }}
238+ SOURCE_IMAGE : ${{ needs.metadata .outputs.image }}: ${{ needs.metadata .outputs.release_tag }}
239+ LEGACY_TAGS : ${{ needs.metadata .outputs.legacy_tags }}
136240 run : |
137241 set -euo pipefail
138242
0 commit comments