33#
44# build.sh --key print the inputs key of this checkout
55# build.sh build for linux/amd64 into the local Docker, print the image ID
6- # build.sh --push main publish job only: push to GHCR, print the image.json record
6+ # build.sh --push the manual publish job only: build, push to GHCR, print the image.json record
77#
88# The inputs key is the sha256 of three lines: the sha256 of the Dockerfile, the sha256 of this
99# script, and the playwright-core version of @e2e-dev/web in bun.lock. The image carries it as
1010# the label org.xum.bugbash.inputs, and the runner computes the same key for its checkout.
1111# The script reads these files from the working tree and refuses when they differ from HEAD, so
1212# the key always names committed source.
1313#
14- # The build gets an empty context, no cache and no build args from the env. --push skips the
15- # build when the registry already has the tag inputs-<key>: one key, one published digest.
14+ # The build gets an empty context, no cache and no build args from the env. --push always builds
15+ # fresh: it never checks the registry and never reuses an image. It pushes a new tag, so it
16+ # overwrites no tag, and it reports the name and digest from its own build output. Two publishes
17+ # of one inputs key give two digests; the reviewed digest in image.json is what runners trust.
1618# Nothing here deletes an image.
1719set -euo pipefail
1820
@@ -64,7 +66,7 @@ case "$mode" in
6466esac
6567
6668context=$( mktemp -d)
67- trap ' rm -rf "$context" "$context.json" "$context.raw" ' EXIT
69+ trap ' rm -rf "$context" "$context.json"' EXIT
6870build () {
6971 docker buildx build --platform linux/amd64 --no-cache --pull --provenance=false --sbom=false \
7072 --build-arg " PLAYWRIGHT_CORE_VERSION=$PLAYWRIGHT " --build-arg " INPUTS_SHA256=$KEY " \
@@ -77,18 +79,13 @@ if [ "$mode" = local ]; then
7779 exit 0
7880fi
7981
80- # --push
81- TAG=" $IMAGE :inputs-$KEY "
82- # The digest of a manifest is the sha256 of its raw bytes. Hash the file, not a --format value:
83- # some buildx versions ignore --format here and print a table (docker/buildx#4006).
84- if docker buildx imagetools inspect --raw " $TAG " > " $context .raw" 2> /dev/null; then
85- digest=" sha256:$( sha " $context .raw" ) "
86- echo " build.sh: $TAG exists, no build" >&2
87- else
88- build --push --tag " $TAG "
89- digest=$( jq -r ' ."containerimage.digest"' " $context .json" )
90- fi
91- [[ $digest =~ ^sha256:[0-9a-f]{64}$ ]] || die " bad digest: $digest "
92- jq -n --arg image " $IMAGE " --arg digest " $digest " --arg key " $KEY " --arg pw " $PLAYWRIGHT " \
82+ # --push. One new tag per publish (inputs key, commit, UTC time), so a publish overwrites no tag.
83+ build --push --tag " $IMAGE :inputs-${KEY: 0: 16} -$( git rev-parse --short=12 HEAD) -$( date -u +%Y%m%d%H%M%S) "
84+ # The name and digest come from this build's own metadata, not from a registry lookup.
85+ digest=$( jq -r ' ."containerimage.digest"' " $context .json" )
86+ pushed=$( jq -r ' ."image.name"' " $context .json" )
87+ [[ $digest =~ ^sha256:[0-9a-f]{64}$ ]] || die " bad digest in the build metadata: $digest "
88+ [[ $pushed == " $IMAGE :" * && $pushed != * ,* ]] || die " unexpected image name in the build metadata: $pushed "
89+ jq -n --arg image " ${pushed%:* } " --arg digest " $digest " --arg key " $KEY " --arg pw " $PLAYWRIGHT " \
9390 --arg from " $( git rev-parse HEAD) " \
9491 ' {image: $image, digest: $digest, inputsKey: $key, playwrightCore: $pw, publishedFrom: $from}'
0 commit comments