Hash-pin every external reference in deploy.yml, verified on a real runner (closes #7) #22
@@ -3,28 +3,60 @@ name: Build and Deploy to Cloudflare Pages
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- feat/initial-site
|
|
||||||
- main
|
- 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:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: klakegg/hugo:ext-alpine
|
# 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:
|
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
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
# actions/checkout v4.2.2, 2026-02-28
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Install build dependencies
|
||||||
|
run: script/bootstrap
|
||||||
|
|
||||||
- name: Build site
|
- name: Build site
|
||||||
run: hugo --minify
|
run: script/test
|
||||||
|
|
||||||
- name: Archive site
|
- name: Archive site
|
||||||
run: tar -czf site.tar.gz public
|
run: tar -czf site.tar.gz public
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v3
|
# actions/upload-artifact v4.6.2, 2026-08-09
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
||||||
with:
|
with:
|
||||||
name: site
|
name: site
|
||||||
path: site.tar.gz
|
path: site.tar.gz
|
||||||
@@ -32,11 +64,19 @@ jobs:
|
|||||||
deploy:
|
deploy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
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:
|
container:
|
||||||
image: node:20
|
# node 20.20.2-bookworm, 2026-08-09
|
||||||
|
image: node@sha256:8f693eaa7e0a8e71560c9a82b55fd54c2ae920a2ba5d2cde28bac7d1c01c9ba5
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: actions/download-artifact@v3
|
# actions/download-artifact v4.3.0, 2026-08-09
|
||||||
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
|
||||||
with:
|
with:
|
||||||
name: site
|
name: site
|
||||||
|
|
||||||
@@ -44,7 +84,8 @@ jobs:
|
|||||||
run: tar -xzf site.tar.gz
|
run: tar -xzf site.tar.gz
|
||||||
|
|
||||||
- name: Install Wrangler
|
- name: Install Wrangler
|
||||||
run: npm install -g wrangler
|
# wrangler 4.120.0, 2026-08-09
|
||||||
|
run: npm install -g wrangler@4.120.0
|
||||||
|
|
||||||
- name: Deploy to Cloudflare Pages
|
- name: Deploy to Cloudflare Pages
|
||||||
run: wrangler pages deploy public --project-name=lora-vegas --branch=${{ github.ref_name }}
|
run: wrangler pages deploy public --project-name=lora-vegas --branch=${{ github.ref_name }}
|
||||||
|
|||||||
110
.gitea/workflows/probe.yml
Normal file
110
.gitea/workflows/probe.yml
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# TEMPORARY diagnostic workflow. Deleted before this branch is merged.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# *job*. This file therefore encodes the diagnosis as job topology: each job
|
||||||
|
# below isolates exactly one hypothesis about why the pinned-alpine build job
|
||||||
|
# failed after 22s on main (run 25), and each shows up as its own status
|
||||||
|
# context, so one push tests them all in parallel.
|
||||||
|
name: probe
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- pin-deploy-refs-observable
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Control. If this passes, act_runner supplies its own node for JS actions
|
||||||
|
# and the whole "install node first" theory is wrong.
|
||||||
|
p1-bare-alpine-checkout:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
# alpine 3.21, 2026-02-28
|
||||||
|
image: alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
|
||||||
|
steps:
|
||||||
|
# actions/checkout v4.2.2, 2026-02-28
|
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
|
|
||||||
|
# Exactly the reverted prefix: apk prerequisites, then checkout. Isolates
|
||||||
|
# checkout from everything downstream of it.
|
||||||
|
p2-alpine-apk-checkout:
|
||||||
|
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
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
# p2 plus the site build. Isolates script/bootstrap and script/test inside
|
||||||
|
# the Actions container from the JS-action machinery.
|
||||||
|
p3-alpine-apk-build:
|
||||||
|
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
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- run: script/bootstrap
|
||||||
|
- run: script/test
|
||||||
|
- run: tar -czf site.tar.gz public
|
||||||
|
|
||||||
|
# p2 plus the artifact upload. This is the one step whose protocol changed
|
||||||
|
# in this issue (v3 -> v4) and the ~22s timing is consistent with reaching
|
||||||
|
# it.
|
||||||
|
p4-alpine-apk-upload:
|
||||||
|
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 probe4.tar.gz hugo.toml
|
||||||
|
# actions/upload-artifact v4.6.2, 2026-08-09
|
||||||
|
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
||||||
|
with:
|
||||||
|
name: probe4
|
||||||
|
path: probe4.tar.gz
|
||||||
|
|
||||||
|
# Fallback image direction, measured rather than assumed: an image that
|
||||||
|
# already carries node.
|
||||||
|
p5-node20alpine-checkout:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
# node 20-alpine, 2026-08-09
|
||||||
|
image: node@sha256:fb4cd12c85ee03686f6af5362a0b0d56d50c58a04632e6c0fb8363f609372293
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: sh
|
||||||
|
steps:
|
||||||
|
# actions/checkout v4.2.2, 2026-02-28
|
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
|
|
||||||
|
# The glibc control. If musl node is the problem, this passes where the
|
||||||
|
# alpine jobs do not.
|
||||||
|
p6-node20slim-checkout:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
# node 20-bookworm-slim, 2026-08-09
|
||||||
|
image: node@sha256:2cf067cfed83d5ea958367df9f966191a942351a2df77d6f0193e162b5febfc0
|
||||||
|
steps:
|
||||||
|
# actions/checkout v4.2.2, 2026-02-28
|
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
Reference in New Issue
Block a user