From 20399f59e169c5e0bbc99aa56173a60a607c0d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Gr=C3=BCner?= <47506558+MegaRedHand@users.noreply.github.com> Date: Wed, 8 Jul 2026 11:25:45 -0300 Subject: [PATCH 1/2] ci(docker): also publish -shadow image variants Add a `variant` matrix dimension (default + shadow) to the docker publish workflow so every tag gets a Shadow-simulator-compatible twin (e.g. `latest`+`latest-shadow`, `unstable`+`unstable-shadow`). The shadow build args mirror the `shadow-docker-build` Makefile target (SHADOW=1, FEATURES=shadow-integration, --no-default-features, unlocked), so consumers no longer have to build the Shadow image by hand. Both arches are built for each variant and combined into per-tag and sha- multi-arch manifests, keeping the shadow set fully symmetric with the regular set. --- .github/workflows/docker_publish.yaml | 64 ++++++++++++++++++--------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/.github/workflows/docker_publish.yaml b/.github/workflows/docker_publish.yaml index a7c76aa6..ce092e7a 100644 --- a/.github/workflows/docker_publish.yaml +++ b/.github/workflows/docker_publish.yaml @@ -27,15 +27,29 @@ env: jobs: build-image: - name: Build Docker image (${{ matrix.arch }}) + name: Build Docker image (${{ matrix.arch.name }}, ${{ matrix.variant.name }}) strategy: matrix: - include: + arch: - runner: ubuntu-latest - arch: amd64 + name: amd64 - runner: ubuntu-22.04-arm - arch: arm64 - runs-on: ${{ matrix.runner }} + name: arm64 + # Each tag is published twice: once as the regular image and once as a + # Shadow-simulator-compatible image (tag suffixed "-shadow"). The shadow + # build args mirror the `shadow-docker-build` Makefile target. + variant: + - name: default + suffix: "" + build_args: "" + - name: shadow + suffix: "-shadow" + build_args: | + SHADOW=1 + FEATURES=shadow-integration + NO_DEFAULT_FEATURES=--no-default-features + LOCKED= + runs-on: ${{ matrix.arch.runner }} steps: - name: Checkout repository @@ -53,11 +67,14 @@ jobs: - name: Prepare tags id: prep + env: + SUFFIX: ${{ matrix.variant.suffix }} + ARCH: ${{ matrix.arch.name }} run: | TAGS="" IFS=',' read -ra TAG_ARRAY <<< "${TAGS_INPUT}" for t in "${TAG_ARRAY[@]}"; do - TAGS="${TAGS}${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${t}-${{ matrix.arch }}," + TAGS="${TAGS}${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${t}${SUFFIX}-${ARCH}," done TAGS="${TAGS%,}" # Remove trailing comma echo "tags=${TAGS}" >> $GITHUB_OUTPUT @@ -70,11 +87,12 @@ jobs: build-args: | GIT_COMMIT=${{ github.sha }} GIT_BRANCH=${{ github.ref_name }} + ${{ matrix.variant.build_args }} push: true tags: ${{ steps.prep.outputs.tags }} - platforms: linux/${{ matrix.arch }} - cache-from: type=gha,scope=${{ matrix.arch }} - cache-to: type=gha,scope=${{ matrix.arch }},mode=max + platforms: linux/${{ matrix.arch.name }} + cache-from: type=gha,scope=${{ matrix.arch.name }}-${{ matrix.variant.name }} + cache-to: type=gha,scope=${{ matrix.arch.name }}-${{ matrix.variant.name }},mode=max publish-manifest: name: Create and push multi-arch manifest @@ -95,18 +113,22 @@ jobs: run: | IFS=',' read -ra TAG_ARRAY <<< "${TAGS_INPUT}" FIRST_TAG="${TAG_ARRAY[0]}" + SHORT="${SHORT_SHA::7}" - # Create manifest for first tag with SHA tag - docker buildx imagetools create \ - -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${FIRST_TAG} \ - -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${SHORT_SHA::7} \ - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${FIRST_TAG}-amd64 \ - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${FIRST_TAG}-arm64 - - # Create manifests for remaining tags - for t in "${TAG_ARRAY[@]:1}"; do + # Publish each tag twice: the regular image and its "-shadow" twin. + for suffix in "" "-shadow"; do + # First tag also gets an immutable sha- tag. docker buildx imagetools create \ - -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${t} \ - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${t}-amd64 \ - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${t}-arm64 + -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${FIRST_TAG}${suffix} \ + -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${SHORT}${suffix} \ + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${FIRST_TAG}${suffix}-amd64 \ + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${FIRST_TAG}${suffix}-arm64 + + # Remaining tags. + for t in "${TAG_ARRAY[@]:1}"; do + docker buildx imagetools create \ + -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${t}${suffix} \ + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${t}${suffix}-amd64 \ + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${t}${suffix}-arm64 + done done From 4b28f1fdf67902fbf207e7a4ad87005e3688c9ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Gr=C3=BCner?= <47506558+MegaRedHand@users.noreply.github.com> Date: Wed, 8 Jul 2026 12:01:23 -0300 Subject: [PATCH 2/2] ci(docker): document shadow build non-reproducibility and manifest sync Address PR review feedback: note that the -shadow variant builds unlocked (so those images are non-reproducible, per Claude/Kimi), and flag that the manifest suffix loop must stay in sync with the variant matrix (per Greptile). --- .github/workflows/docker_publish.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker_publish.yaml b/.github/workflows/docker_publish.yaml index ce092e7a..bb94e6cc 100644 --- a/.github/workflows/docker_publish.yaml +++ b/.github/workflows/docker_publish.yaml @@ -37,7 +37,11 @@ jobs: name: arm64 # Each tag is published twice: once as the regular image and once as a # Shadow-simulator-compatible image (tag suffixed "-shadow"). The shadow - # build args mirror the `shadow-docker-build` Makefile target. + # build args mirror the `shadow-docker-build` Makefile target. LOCKED= + # builds the shadow variant unlocked (the quinn-udp [patch] is absent + # from Cargo.lock; see Dockerfile), so -shadow images are not + # reproducible and should not be treated as equivalent-security + # artifacts to the regular tags. variant: - name: default suffix: "" @@ -116,6 +120,8 @@ jobs: SHORT="${SHORT_SHA::7}" # Publish each tag twice: the regular image and its "-shadow" twin. + # These suffixes must stay in sync with the `variant` matrix suffixes + # in the build-image job above: a new variant must be added in both. for suffix in "" "-shadow"; do # First tag also gets an immutable sha- tag. docker buildx imagetools create \