From 6ee08b45a57279cff5c90cfc209ed8ab7e6e7b16 Mon Sep 17 00:00:00 2001 From: Gang Tao Date: Fri, 25 Sep 2026 09:22:42 +0800 Subject: [PATCH] ci(docker): build the web bundle natively; fail a hung build fast The v0.0.7 release run ended 'cancelled': its all-in-one job hung for 6h -- GitHub's default job timeout -- after 'npm ci' in the arm64 half of the multi-arch build died under QEMU ('uncaught target signal 4 (Illegal instruction)') and buildx never returned. timeplus/tpk:0.0.7 was never pushed. The web bundle is plain JS/CSS, identical for every target, so the webbuild stage now runs on the build host (--platform=$BUILDPLATFORM) and is copied into both images; Node no longer runs under emulation at all. Both jobs get timeout-minutes: 30 so a hang surfaces as a failure within the hour. Verified: an amd64 cross-build from an arm64 host completes with webbuild executing natively. Co-Authored-By: Claude Fable 5.1 --- .github/workflows/docker-publish.yml | 6 ++++++ deploy/docker/Dockerfile | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 97aeb11..8740bfe 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -41,6 +41,9 @@ jobs: app: name: app image (timeplus/tpk-app) runs-on: ubuntu-latest + # A hung buildx (seen once: an arm64 QEMU crash that never returned) must + # fail fast, not sit until GitHub's 6h default and end up 'cancelled'. + timeout-minutes: 30 steps: - uses: actions/checkout@v4 @@ -102,6 +105,9 @@ jobs: # registry secrets are available. PRs skip it. if: github.event_name != 'pull_request' runs-on: ubuntu-latest + # A hung buildx (seen once: an arm64 QEMU crash that never returned) must + # fail fast, not sit until GitHub's 6h default and end up 'cancelled'. + timeout-minutes: 30 env: TP_REGISTRY_USER: ${{ secrets.TIMEPLUSD_REGISTRY_USERNAME }} steps: diff --git a/deploy/docker/Dockerfile b/deploy/docker/Dockerfile index aa82435..ad9945b 100644 --- a/deploy/docker/Dockerfile +++ b/deploy/docker/Dockerfile @@ -13,7 +13,12 @@ # builds the app target; docker-compose.allinone.yml builds the allinone target. # --- shared: React chat UI (so runtime images don't need node) --------------- -FROM node:22-alpine AS webbuild +# Built ONCE on the runner's own architecture: the bundle is plain JS/CSS, the +# same for every target platform. Without --platform=$BUILDPLATFORM buildx runs +# `npm ci` a second time under arm64 QEMU emulation, which crashed with +# "qemu: uncaught target signal 4 (Illegal instruction)" on the v0.0.7 release +# build and hung the job until GitHub's 6h timeout. +FROM --platform=$BUILDPLATFORM node:22-alpine AS webbuild WORKDIR /web COPY web/package.json web/package-lock.json ./ RUN npm ci