Skip to content

Commit c3d0b38

Browse files
fix(ci): per-platform builds and dry-run gates publish
Single-platform --load works with any buildx driver (no containerd needed). Build each platform separately, test each, then push multi-platform. Dry-run job runs on all branches and gates publish on release.
1 parent 1bf0dfd commit c3d0b38

2 files changed

Lines changed: 37 additions & 39 deletions

File tree

.github/workflows/cli.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,6 @@ jobs:
431431
docker-dry-run:
432432
name: "Docker images (dry run)"
433433
needs: [ build-cli ]
434-
if: "!endsWith(github.ref, '/release')"
435434
runs-on: ubuntu-22.04
436435

437436
steps:
@@ -468,7 +467,7 @@ jobs:
468467
469468
publish-to-docker-hub:
470469
name: "Publish to Docker Hub"
471-
needs: [ build-cli, run-unit-tests, run-lints, run-smoke-tests, run-linux-distros-test, check-cli-docs ]
470+
needs: [ build-cli, run-unit-tests, run-lints, run-smoke-tests, run-linux-distros-test, check-cli-docs, docker-dry-run ]
472471
if: endsWith(github.ref, '/release')
473472
runs-on: ubuntu-22.04
474473

scripts/publish_docker

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# Usage:
1818
# ./scripts/publish_docker # build and load both platforms locally
1919
# ./scripts/publish_docker --push # build and push multi-arch manifests to Docker Hub
20-
# ./scripts/publish_docker --run # build, load, and run "nextclade --help" on each platform
20+
# ./scripts/publish_docker --run # build, load, and run "nextclade --version" on each platform
2121
# ./scripts/publish_docker --push --run # build, load, test, then push (verify before publish)
2222
#
2323
# Dependencies:
@@ -84,8 +84,6 @@ declare -a PROJECT_NAMES=(
8484

8585
DOCKER_PLATFORMS="linux/amd64,linux/arm64"
8686

87-
BUILDX_ARGS_BASE=(--platform "${DOCKER_PLATFORMS}")
88-
8987
# Create symlinks mapping Docker's TARGETARCH names (amd64/arm64) to Rust target triples (x86_64/aarch64).
9088
# Dockerfiles use TARGETARCH in COPY paths: .out/nextclade-${TARGETARCH}-linux-{gnu,musl}
9189
ln -sf "nextclade-x86_64-unknown-linux-gnu" ".out/nextclade-amd64-linux-gnu"
@@ -162,16 +160,17 @@ declare -a BASE_IMAGES=(
162160
)
163161

164162
# Build both project images (nextclade + nextalign) for a single build spec.
165-
# Called by GNU parallel with --colsep '\t': build_one <base_image> <base_version> <is_latest> <buildx_output>
163+
# Called by GNU parallel with --colsep '\t': build_one <base_image> <base_version> <is_latest> <buildx_output> <platform>
166164
build_one() {
167165
set -euo pipefail
168166

169167
local base_image="${1}"
170168
local base_version="${2}"
171169
local is_latest="${3}"
172170
local buildx_output="${4}"
171+
local platform="${5}"
173172

174-
local -a buildx_args=(--platform "${DOCKER_PLATFORMS}" "${buildx_output}")
173+
local -a buildx_args=(--platform "${platform}" "${buildx_output}")
175174
local -a build_args=()
176175
if [[ -n "${base_version}" ]]; then
177176
build_args=(--build-arg "BASE_VERSION=${base_version}")
@@ -236,10 +235,9 @@ compute_specs() {
236235
done
237236
}
238237

239-
# Generate smoke test specs: "tag\tplatform" for each (variant, platform) pair.
240-
compute_run_specs() {
238+
# Generate smoke test tags: first nextclade tag per variant.
239+
compute_run_tags() {
241240
local project_name="nextclade"
242-
IFS=',' read -ra platforms <<< "${DOCKER_PLATFORMS}"
243241

244242
local base_image
245243
for base_image in "${BASE_IMAGES[@]}"; do
@@ -253,75 +251,76 @@ compute_run_specs() {
253251

254252
local base_version
255253
for base_version in "${base_versions[@]}"; do
256-
local tag
257254
if [[ -n "${base_version}" ]]; then
258-
tag="${DOCKER_ORG}/${project_name}:${release_type}-${base_image}${base_version}"
255+
printf "%s\n" "${DOCKER_ORG}/${project_name}:${release_type}-${base_image}${base_version}"
259256
else
260-
tag="${DOCKER_ORG}/${project_name}:${release_type}-${base_image}"
257+
printf "%s\n" "${DOCKER_ORG}/${project_name}:${release_type}-${base_image}"
261258
fi
262-
263-
local platform
264-
for platform in "${platforms[@]}"; do
265-
printf "%s\t%s\n" "${tag}" "${platform}"
266-
done
267259
done
268260
done
269261
}
270262

271-
# Build all images in parallel with the given buildx output mode (--load or --push).
263+
# Build all images in parallel.
264+
# --push: both platforms in one buildx command.
265+
# --load <platform>: single platform per call (docker-container driver cannot --load multi-platform manifests).
272266
build_all() {
273267
local buildx_output="${1}"
268+
local platform="${2:-${DOCKER_PLATFORMS}}"
274269
local -a specs=()
275270
mapfile -t specs < <(compute_specs)
276271

277-
printf "Building %d image variants (%s)\n" "${#specs[@]}" "${buildx_output}"
272+
printf "Building %d image variants (%s, %s)\n" "${#specs[@]}" "${buildx_output}" "${platform}"
278273

279274
# shellcheck disable=SC2016
280275
parallel \
281276
--halt soon,fail=1 \
282277
--line-buffer \
283278
--colsep '\t' \
284279
--tag --tagstring '{1}{2}' \
285-
build_one {1} {2} {3} "${buildx_output}" \
280+
build_one {1} {2} {3} "${buildx_output}" "${platform}" \
286281
::: "${specs[@]}"
287282
}
288283

289-
# Run "nextclade --version" on a single (tag, platform) pair.
284+
# Run "nextclade --version" on a single image tag.
285+
# No --platform flag: tag has only one platform loaded (the current pass).
290286
run_one() {
291287
set -euo pipefail
292288
local tag="${1}"
293-
local platform="${2}"
294289

295-
printf "Running '%s' on %s\n" "${tag}" "${platform}"
296-
docker run --rm --platform "${platform}" "${tag}" nextclade --version
290+
printf "Running '%s'\n" "${tag}"
291+
docker run --rm "${tag}" nextclade --version
297292
}
298293
export -f run_one
299294

300-
# Run smoke tests for every image variant on each platform, in parallel.
295+
# Run smoke tests for every image variant, in parallel.
296+
# Tags have only one platform loaded (the current pass).
301297
run_smoke_tests() {
302-
local -a run_specs=()
303-
mapfile -t run_specs < <(compute_run_specs)
298+
local platform="${1}"
299+
local -a run_tags=()
300+
mapfile -t run_tags < <(compute_run_tags)
304301

305-
printf "Running smoke tests: %d checks\n" "${#run_specs[@]}"
302+
printf "Running smoke tests: %d images (%s)\n" "${#run_tags[@]}" "${platform}"
306303

307304
# shellcheck disable=SC2016
308305
parallel \
309306
--halt soon,fail=1 \
310307
--line-buffer \
311-
--colsep '\t' \
312-
--tag --tagstring '{= s|.*/||; s|\tlinux/| |; =}' \
313-
run_one {1} {2} \
314-
::: "${run_specs[@]}"
308+
--tag --tagstring '{= s|.*/|| =}' \
309+
run_one {} \
310+
::: "${run_tags[@]}"
315311
}
316312

317313
# Execution phases:
318-
# (none): build + load
319-
# --push: build + push
320-
# --run: build + load, smoke test
321-
# --push --run: build + load, smoke test, push (test before publish)
314+
# (none): load each platform separately
315+
# --push: multi-platform push
316+
# --run: load + test each platform, then next platform
317+
# --push --run: load + test each platform, then multi-platform push
322318
if [ "${DOCKER_IMAGE_RUN}" == "1" ]; then
323-
build_all --load
324-
run_smoke_tests
319+
IFS=',' read -ra platforms <<< "${DOCKER_PLATFORMS}"
320+
for platform in "${platforms[@]}"; do
321+
build_all --load "${platform}"
322+
run_smoke_tests "${platform}"
323+
done
325324
if [ "${DOCKER_IMAGE_PUSH}" == "1" ]; then
326325
build_all --push
327326
fi

0 commit comments

Comments
 (0)