Move the artifact pair to the exact commits @v3 was resolving to
Some checks failed
check / check (push) Successful in 8s
Build and Deploy to Cloudflare Pages / build (push) Successful in 8s
probe / r1-wrangler-only (push) Failing after 7s
probe / r2a-upload-proven (push) Successful in 12s
probe / r3a-upload-node20 (push) Successful in 8s
Build and Deploy to Cloudflare Pages / deploy (push) Has been skipped
probe / r2b-download-proven (push) Successful in 2s
probe / r3b-download-node20 (push) Successful in 2s
Some checks failed
check / check (push) Successful in 8s
Build and Deploy to Cloudflare Pages / build (push) Successful in 8s
probe / r1-wrangler-only (push) Failing after 7s
probe / r2a-upload-proven (push) Successful in 12s
probe / r3a-upload-node20 (push) Successful in 8s
Build and Deploy to Cloudflare Pages / deploy (push) Has been skipped
probe / r2b-download-proven (push) Successful in 2s
probe / r3b-download-node20 (push) Successful in 2s
Round 2 (602fd60) put the build job green:
check / check success 6s
Build and Deploy .../ build success 20s <- green
Build and Deploy .../ deploy skipped <- if: guard
probe / q1-upload-v3-node16 success 7s
probe / q2-upload-v3-node20 success 22s
probe / q3-build-for-roundtrip success 11s
probe / q4-deploy-dryrun failure 43s
Every v3 upload works and the build job is fixed. But q4 -- the deploy-side
rehearsal, which downloads the artifact in the pinned node container and
installs the pinned wrangler, stopping short of the publish call -- failed.
That is a break the deploy job would have hit on main, in a job nobody has
ever been able to run.
q4 bundled two things together, so round 3 splits them:
- r1 runs only the wrangler install and invocation. Worth measuring rather
than assuming: wrangler 4.120.0 declares engines.node >= 22 and the deploy
container is node 20, though the pre-issue deploy did run an unpinned
wrangler on node:20 successfully.
- r2a/r2b run the artifact round trip with no wrangler at all.
- r3a/r3b do the same for the newer node20 artifact builds, so the choice
between the two pairs is made on measurement.
deploy.yml meanwhile moves to the artifact commits that the mutable `@v3`
references were actually resolving to while this site was deploying, rather
than to the newest thing on the v3 line:
- upload-artifact -> ff15f030 (v3.2.1)
- download-artifact -> 9bc31d5c (v3.0.2)
That is the conservative reading of what this issue is for: pin what is known
to work, do not take a version bump for free on the way past.
This commit is contained in:
@@ -59,11 +59,12 @@ jobs:
|
|||||||
# identical to this one but ending in upload-artifact v4 fails,
|
# identical to this one but ending in upload-artifact v4 fails,
|
||||||
# while the same job without that step passes. So this stays on
|
# while the same job without that step passes. So this stays on
|
||||||
# the v3 line, pinned, using the node20 build of it rather than
|
# the v3 line, pinned, using the node20 build of it rather than
|
||||||
# the node16 default. Revisit when the artifact v4 protocol works
|
# here; tracked separately. This is the exact commit the mutable
|
||||||
# here; tracked separately.
|
# `@v3` used to resolve to, i.e. the code that was deploying this
|
||||||
|
# site before this issue -- now pinned instead of floating.
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
# actions/upload-artifact v3.2.2-node20, 2026-08-09
|
# actions/upload-artifact v3.2.1, 2026-08-09
|
||||||
uses: actions/upload-artifact@c6a3b2bd78b3985e4b2f15397fec357f0fd808de
|
uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5
|
||||||
with:
|
with:
|
||||||
name: site
|
name: site
|
||||||
path: site.tar.gz
|
path: site.tar.gz
|
||||||
@@ -83,9 +84,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# Must match the upload-artifact major above -- v4 artifacts and
|
# Must match the upload-artifact major above -- v4 artifacts and
|
||||||
# v3 artifacts are different protocols and do not interoperate.
|
# v3 artifacts are different protocols and do not interoperate.
|
||||||
|
# Like the upload above, this is the exact commit `@v3` used to
|
||||||
|
# resolve to.
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
# actions/download-artifact v3.1.0-node20, 2026-08-09
|
# actions/download-artifact v3.0.2, 2026-08-09
|
||||||
uses: actions/download-artifact@ad191675b41f6a5b46da9a048cb6893812da158b
|
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a
|
||||||
with:
|
with:
|
||||||
name: site
|
name: site
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
# The Actions jobs/logs API is not readable by this account, so the only
|
# The Actions jobs/logs API is not readable by this account, so the only
|
||||||
# available signal is the commit-status API, which reports one entry per
|
# available signal is the commit-status API, which reports one entry per
|
||||||
# *job*. This file therefore encodes the diagnosis as job topology: each job
|
# *job*. This file therefore encodes the diagnosis as job topology: each job
|
||||||
# below isolates one hypothesis, and each shows up as its own status context,
|
# isolates one hypothesis and surfaces as its own status context.
|
||||||
# so one push tests them all.
|
|
||||||
#
|
#
|
||||||
# Round 1 result (commit 2d328e7), which is what these round 2 jobs follow up
|
# Round 1 (2d328e7):
|
||||||
# on:
|
|
||||||
#
|
#
|
||||||
# p1 bare alpine + checkout failure 3s
|
# p1 bare alpine + checkout failure 3s
|
||||||
# p2 alpine + apk nodejs git tar + checkout success 5s
|
# p2 alpine + apk nodejs git tar + checkout success 5s
|
||||||
@@ -16,10 +14,21 @@
|
|||||||
# p5 node:20-alpine + checkout success 8s
|
# p5 node:20-alpine + checkout success 8s
|
||||||
# p6 node:20-bookworm-slim + checkout success 11s
|
# p6 node:20-bookworm-slim + checkout success 11s
|
||||||
#
|
#
|
||||||
# So the pinned alpine image and the runner-prerequisite step are fine, the
|
# -> the pinned alpine image, the prerequisite step and the site build are all
|
||||||
# site build inside the Actions container is fine, and the thing that fails is
|
# fine; upload-artifact v4 is what broke the deploy.
|
||||||
# actions/upload-artifact v4 -- the one step this issue changed protocol on.
|
#
|
||||||
# Round 2 checks which pinned v3 build works and rehearses the deploy job.
|
# Round 2 (602fd60):
|
||||||
|
#
|
||||||
|
# build (deploy.yml, upload v3.2.2-node20) success 20s
|
||||||
|
# q1 upload-artifact v3.2.1 (node16) success 7s
|
||||||
|
# q2 upload-artifact v3.2.1-n20 (node20) success 22s
|
||||||
|
# q3 full build + upload v3.2.2-node20 success 11s
|
||||||
|
# q4 download v3.1.0-node20 + wrangler install failure 43s
|
||||||
|
#
|
||||||
|
# -> build is green, every v3 upload works, and the remaining failure is
|
||||||
|
# somewhere in the deploy-side rehearsal. Round 3 splits q4 into its parts:
|
||||||
|
# wrangler on its own, the artifact pair that was actually deploying this
|
||||||
|
# site before this issue, and the newer node20 artifact pair.
|
||||||
name: probe
|
name: probe
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@@ -28,50 +37,24 @@ on:
|
|||||||
- pin-deploy-refs-observable
|
- pin-deploy-refs-observable
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Fallback A: the exact v3 the workflow used before this issue (node16
|
# Isolates the wrangler install and invocation from anything to do with
|
||||||
# runtime), pinned.
|
# artifacts. wrangler 4.120.0 declares engines.node >= 22 while the deploy
|
||||||
q1-upload-v3-node16:
|
# container is node 20, so this needs measuring rather than assuming --
|
||||||
|
# the pre-issue deploy did run an unpinned wrangler on node:20
|
||||||
|
# successfully.
|
||||||
|
r1-wrangler-only:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
# alpine 3.21, 2026-02-28
|
# node 20.20.2-bookworm, 2026-08-09
|
||||||
image: alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
|
image: node@sha256:8f693eaa7e0a8e71560c9a82b55fd54c2ae920a2ba5d2cde28bac7d1c01c9ba5
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: sh
|
|
||||||
steps:
|
steps:
|
||||||
- run: apk add --no-cache nodejs git tar
|
# wrangler 4.120.0, 2026-08-09
|
||||||
# actions/checkout v4.2.2, 2026-02-28
|
- run: npm install -g wrangler@4.120.0
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
- run: wrangler --version
|
||||||
- run: tar -czf probe-a.tar.gz hugo.toml
|
|
||||||
# actions/upload-artifact v3.2.1, 2026-08-09
|
|
||||||
- uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5
|
|
||||||
with:
|
|
||||||
name: probe-a
|
|
||||||
path: probe-a.tar.gz
|
|
||||||
|
|
||||||
# Fallback B: same release, node20 runtime.
|
# Producer for the pair that `@v3`/`@v3` resolved to before this issue,
|
||||||
q2-upload-v3-node20:
|
# i.e. the code that was actually deploying the site, now pinned.
|
||||||
runs-on: ubuntu-latest
|
r2a-upload-proven:
|
||||||
container:
|
|
||||||
# alpine 3.21, 2026-02-28
|
|
||||||
image: alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: sh
|
|
||||||
steps:
|
|
||||||
- run: apk add --no-cache nodejs git tar
|
|
||||||
# actions/checkout v4.2.2, 2026-02-28
|
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
|
||||||
- run: tar -czf probe-b.tar.gz hugo.toml
|
|
||||||
# actions/upload-artifact v3.2.1-node20, 2026-08-09
|
|
||||||
- uses: actions/upload-artifact@c24449f33cd45d4826c6702db7e49f7cdb9b551d
|
|
||||||
with:
|
|
||||||
name: probe-b
|
|
||||||
path: probe-b.tar.gz
|
|
||||||
|
|
||||||
# Producer half of the round-trip rehearsal: byte-for-byte the build job
|
|
||||||
# from deploy.yml.
|
|
||||||
q3-build-for-roundtrip:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
# alpine 3.21, 2026-02-28
|
# alpine 3.21, 2026-02-28
|
||||||
@@ -88,21 +71,53 @@ jobs:
|
|||||||
- run: script/bootstrap
|
- run: script/bootstrap
|
||||||
- run: script/test
|
- run: script/test
|
||||||
- run: tar -czf site.tar.gz public
|
- run: tar -czf site.tar.gz public
|
||||||
|
# actions/upload-artifact v3.2.1, 2026-08-09
|
||||||
|
- uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5
|
||||||
|
with:
|
||||||
|
name: site-proven
|
||||||
|
path: site.tar.gz
|
||||||
|
|
||||||
|
# Consumer half: the deploy job's artifact handling, with no wrangler, so
|
||||||
|
# a failure here means the artifact round trip and a pass here means it is
|
||||||
|
# sound.
|
||||||
|
r2b-download-proven:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: r2a-upload-proven
|
||||||
|
container:
|
||||||
|
# node 20.20.2-bookworm, 2026-08-09
|
||||||
|
image: node@sha256:8f693eaa7e0a8e71560c9a82b55fd54c2ae920a2ba5d2cde28bac7d1c01c9ba5
|
||||||
|
steps:
|
||||||
|
# actions/download-artifact v3.0.2, 2026-08-09
|
||||||
|
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a
|
||||||
|
with:
|
||||||
|
name: site-proven
|
||||||
|
- run: tar -xzf site.tar.gz
|
||||||
|
- run: test -f public/index.html
|
||||||
|
|
||||||
|
# The newer node20 artifact pair, kept in the round so the choice between
|
||||||
|
# the two pairs rests on measurement rather than preference.
|
||||||
|
r3a-upload-node20:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
# alpine 3.21, 2026-02-28
|
||||||
|
image: alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: sh
|
||||||
|
steps:
|
||||||
|
- run: apk add --no-cache nodejs git tar
|
||||||
|
# actions/checkout v4.2.2, 2026-02-28
|
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
|
- run: tar -czf alt.tar.gz hugo.toml
|
||||||
# actions/upload-artifact v3.2.2-node20, 2026-08-09
|
# actions/upload-artifact v3.2.2-node20, 2026-08-09
|
||||||
- uses: actions/upload-artifact@c6a3b2bd78b3985e4b2f15397fec357f0fd808de
|
- uses: actions/upload-artifact@c6a3b2bd78b3985e4b2f15397fec357f0fd808de
|
||||||
with:
|
with:
|
||||||
name: site
|
name: alt-node20
|
||||||
path: site.tar.gz
|
path: alt.tar.gz
|
||||||
|
|
||||||
# Consumer half: the deploy job with everything except the publish call.
|
r3b-download-node20:
|
||||||
# Same pinned node image, same pinned download action, same pinned
|
|
||||||
# wrangler version -- it just prints wrangler's version instead of running
|
|
||||||
# `wrangler pages deploy`, so it touches nothing external and needs no
|
|
||||||
# token. This is as close to exercising the deploy job as is possible
|
|
||||||
# without actually deploying.
|
|
||||||
q4-deploy-dryrun:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: q3-build-for-roundtrip
|
needs: r3a-upload-node20
|
||||||
container:
|
container:
|
||||||
# node 20.20.2-bookworm, 2026-08-09
|
# node 20.20.2-bookworm, 2026-08-09
|
||||||
image: node@sha256:8f693eaa7e0a8e71560c9a82b55fd54c2ae920a2ba5d2cde28bac7d1c01c9ba5
|
image: node@sha256:8f693eaa7e0a8e71560c9a82b55fd54c2ae920a2ba5d2cde28bac7d1c01c9ba5
|
||||||
@@ -110,9 +125,5 @@ jobs:
|
|||||||
# actions/download-artifact v3.1.0-node20, 2026-08-09
|
# actions/download-artifact v3.1.0-node20, 2026-08-09
|
||||||
- uses: actions/download-artifact@ad191675b41f6a5b46da9a048cb6893812da158b
|
- uses: actions/download-artifact@ad191675b41f6a5b46da9a048cb6893812da158b
|
||||||
with:
|
with:
|
||||||
name: site
|
name: alt-node20
|
||||||
- run: tar -xzf site.tar.gz
|
- run: test -f alt.tar.gz
|
||||||
- run: test -f public/index.html
|
|
||||||
# wrangler 4.120.0, 2026-08-09
|
|
||||||
- run: npm install -g wrangler@4.120.0
|
|
||||||
- run: wrangler --version
|
|
||||||
|
|||||||
Reference in New Issue
Block a user