Hash-pin every external reference in deploy.yml, verified on a real runner (closes #7) #22
@@ -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