Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 8 additions & 1 deletion deploy/docker/Dockerfile.web
Original file line number Diff line number Diff line change
@@ -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).
Expand Down
Loading