diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0405a098..c83e526c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -232,13 +232,20 @@ jobs: $(printf "${IMAGE}@sha256:%s " *) # --------------------------------------------------------------------------- - # Docker Web: static files are arch-independent, single buildx with QEMU + # Docker Web: static files are arch-independent. Dockerfile.web builds them + # once on this runner's own platform and copies them into each arch's nginx + # image, so no build step runs under emulation. # --------------------------------------------------------------------------- docker-web: name: Web Build & Push runs-on: ubuntu-latest needs: [rust, frontend] if: github.event_name == 'push' && github.ref == 'refs/heads/main' + # A healthy run takes minutes. With no limit, a hung build holds the + # runner for GitHub's six-hour maximum — which is what happened when + # Node crashed under QEMU in the old per-arch build and the step never + # exited. + timeout-minutes: 20 permissions: contents: read packages: write diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d545317..fa213332 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,18 @@ target. ## [Unreleased] +### Fixed + +- **CI** — the `main` push that merged #23 never produced its web image. + `Dockerfile.web` built the frontend once per architecture, Node crashed + with SIGILL in the QEMU-emulated arm64 build, and the build step hung + until GitHub cancelled the job at the six-hour limit. The static files + are identical on every architecture, so they are now built once, + natively, and copied into each architecture's nginx image — emulated, + `pnpm build` alone took 260s against 23s. The job also times out after + 20 minutes. Image contents are unchanged; release builds already ran on + native runners. + ## [1.0.2] — 2026-09-13 The shared gateway layer moves out into its own repository, and OIDC diff --git a/deploy/docker/Dockerfile.web b/deploy/docker/Dockerfile.web index 831e2cc0..77ffe242 100644 --- a/deploy/docker/Dockerfile.web +++ b/deploy/docker/Dockerfile.web @@ -1,5 +1,12 @@ # Stage 1: Build -FROM node:24-alpine AS builder +# +# Runs on the building machine's own platform rather than once per target. +# dist/ is static files, identical for every architecture, so it is built +# once, natively, and stage 2 only copies it. Built per target, arm64 ran +# `pnpm install` and `pnpm build` under QEMU: the build alone took 260s +# against 23s natively, and when Node crashed there with SIGILL the step +# never exited — the CI job sat idle until GitHub's six-hour limit. +FROM --platform=$BUILDPLATFORM node:24-alpine AS builder # Pin pnpm to a known-good 11.x. The workspace YAML's `allowBuilds` # field requires pnpm 11+ (see web/pnpm-workspace.yaml top comment).