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.
106 lines
4.7 KiB
YAML
106 lines
4.7 KiB
YAML
name: Build and Deploy to Cloudflare Pages
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
# TEMPORARY: development-only trigger so the build job actually
|
|
# executes under act_runner before this reaches main. Removed in
|
|
# the final commit.
|
|
- pin-deploy-refs-observable
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
container:
|
|
# Same digest the Dockerfile pins: one pinned base image and the
|
|
# same dependency list (script/bootstrap) for both the check build
|
|
# and the deploy build. The one extra thing this job needs on top
|
|
# of the Dockerfile is the Actions runner's own prerequisites --
|
|
# see the first step.
|
|
# alpine 3.21, 2026-02-28
|
|
image: alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
|
|
defaults:
|
|
run:
|
|
# The default step shell is bash; this image has only busybox
|
|
# sh, so say so explicitly rather than rely on a fallback.
|
|
shell: sh
|
|
steps:
|
|
# This image is bare busybox+musl. act_runner executes JavaScript
|
|
# actions (checkout, upload-artifact) with `node` *inside* the job
|
|
# container and does not inject one, so node has to exist before
|
|
# the first `uses:` step -- script/bootstrap runs too late. git is
|
|
# needed for checkout's `submodules: recursive` (without it
|
|
# checkout degrades to a tarball download that cannot do
|
|
# submodules). An inline `run:` needs only a shell, so this step
|
|
# works on the bare image. These apk packages resolve at run time
|
|
# and are not hash-pinned; that gap is repo-wide (script/bootstrap
|
|
# has it too) and is tracked in #19.
|
|
- name: Install runner prerequisites
|
|
run: apk add --no-cache nodejs git tar
|
|
|
|
- name: Checkout
|
|
# actions/checkout v4.2.2, 2026-02-28
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
|
with:
|
|
submodules: recursive
|
|
|
|
- name: Install build dependencies
|
|
run: script/bootstrap
|
|
|
|
- name: Build site
|
|
run: script/test
|
|
|
|
- name: Archive site
|
|
run: tar -czf site.tar.gz public
|
|
|
|
# v4 does not work on this Gitea Actions instance -- it is what
|
|
# broke the deploy in run 25. Measured on this branch: a job
|
|
# identical to this one but ending in upload-artifact v4 fails,
|
|
# while the same job without that step passes. So this stays on
|
|
# the v3 line, pinned, using the node20 build of it rather than
|
|
# here; tracked separately. This is the exact commit the mutable
|
|
# `@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
|
|
# actions/upload-artifact v3.2.1, 2026-08-09
|
|
uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5
|
|
with:
|
|
name: site
|
|
path: site.tar.gz
|
|
|
|
deploy:
|
|
runs-on: ubuntu-latest
|
|
needs: build
|
|
# Publishing guard. This job spends CLOUDFLARE_API_TOKEN and creates a
|
|
# real Cloudflare Pages deployment, so it must never run off main --
|
|
# not even if a branch is added to the push trigger above, deliberately
|
|
# or by accident. Costs one line; the build job stays exercisable from
|
|
# a branch without this job touching anything external.
|
|
if: github.ref_name == 'main'
|
|
container:
|
|
# node 20.20.2-bookworm, 2026-08-09
|
|
image: node@sha256:8f693eaa7e0a8e71560c9a82b55fd54c2ae920a2ba5d2cde28bac7d1c01c9ba5
|
|
steps:
|
|
# Must match the upload-artifact major above -- v4 artifacts and
|
|
# 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
|
|
# actions/download-artifact v3.0.2, 2026-08-09
|
|
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a
|
|
with:
|
|
name: site
|
|
|
|
- name: Extract site
|
|
run: tar -xzf site.tar.gz
|
|
|
|
- name: Install Wrangler
|
|
# wrangler 4.120.0, 2026-08-09
|
|
run: npm install -g wrangler@4.120.0
|
|
|
|
- name: Deploy to Cloudflare Pages
|
|
run: wrangler pages deploy public --project-name=lora-vegas --branch=${{ github.ref_name }}
|
|
env:
|
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|