diff --git a/.gitea/workflows/backend-quality-gate.yml b/.gitea/workflows/backend-quality-gate.yml index d9f88445..39ba19c4 100644 --- a/.gitea/workflows/backend-quality-gate.yml +++ b/.gitea/workflows/backend-quality-gate.yml @@ -183,7 +183,10 @@ jobs: python -m build npm test --prefix frontend npm run lint --prefix frontend - npm run build --prefix frontend + if ! timeout 600 npm run build --prefix frontend; then + echo "frontend production build exceeded bounded 600-second timeout" >&2 + exit 124 + fi publish: if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/staging' diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 8f3fbe7f..d6c47a23 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -2336,3 +2336,19 @@ - 相关记录:BUG-128、BUG-134、ERR-093、ERR-098 - 复发自:无 - 修复版本:待 staging service runtime 对齐与 exact-SHA 部署验收 + +## BUG-136 | staging quality gate frontend build 无界卡住并耗尽 45 分钟 job + +- 状态:investigating +- 首次发现:2026-08-06 +- 最近更新:2026-08-06 +- 影响面:Gitea `Staging Backend Quality Gate` validate job、staging artifact publication;应用代码、staging host 和 production 未被本次失败修改。 +- 用户现象:push gate `1507` 对 reviewed SHA `6fd22921197715e065d0d137fbd7ea5a82a188e4` 完成 frontend `1472/1472`、ESLint `0 error`,Next.js 输出 `Compiled successfully in 38.2s` 后约 44 分钟无 further output,45 分钟 job 超时,publish 被跳过;公网继续运行旧健康 SHA `e59f15d352787f3d05425ba8c459d092e9801a20`。 +- 触发条件:质量门禁执行 `npm run build --prefix frontend` 没有命令级 bounded timeout;Turbopack 在编译后静态生成/收尾阶段无输出卡住时只能等待 job-level timeout。 +- 根因:quality gate 只有 45 分钟 job 上限,缺少针对生产构建步骤的 fail-closed deadline;此前 PR gate `1503/1505` 同一代码完整 build 通过,说明本次是 runner/build hang,不是已观测的业务编译错误。 +- 修复:在 Gitea validate 中将 frontend production build 包在 `timeout 600` 内,超时输出明确事实并以非零状态失败;不跳过 build、不降低测试、不发布旧 artifact。新增 workflow contract 锁定该 bounded timeout。 +- 验证:待本地 workflow contract、完整 PR gate、同一 reviewed main/staging SHA 的 push gate、immutable manifest 和 deploy 验收;完成前不得标记 resolved。 +- 防复发:所有可能长时间静默的编译、镜像构建和外部网络步骤都必须有命令级 deadline,且 deadline 失败必须 fail closed;保留 job-level timeout 作为第二层上限,不把 timeout 当成功。 +- 相关记录:BUG-129、BUG-131、ERR-096、ERR-099 +- 复发自:无 +- 修复版本:待 frontend build bounded timeout 与 staging exact-SHA 验收 diff --git a/docs/research/pre_work_error_ledger.md b/docs/research/pre_work_error_ledger.md index 8d27e7de..f59b77fa 100644 --- a/docs/research/pre_work_error_ledger.md +++ b/docs/research/pre_work_error_ledger.md @@ -169,6 +169,12 @@ After the admin-origin selector was repaired, the full staging validators expose Prevention: `/docker-entrypoint-initdb.d` is not a compatibility mechanism for an existing PostgreSQL volume. Every newly required runtime role must have a reviewed non-destructive repair path plus pre-deploy role/presence probes. Keep `admin_runtime` outside `service_role`; only `service_runtime` may assume the BYPASSRLS role through the dedicated service URL. Never display role passwords, pass them in argv, or edit an already-ledgered migration checksum to retrofit host bootstrap behavior. +## ERR-099 | Gitea frontend production build hung after successful compilation until job timeout | investigating 2026-08-06 + +Staging push gate `1507` completed all frontend tests (`1472/1472`), lint with zero errors, and Turbopack compilation in 38.2 seconds, then emitted no further build output for roughly 44 minutes. The 45-minute validate job expired, publish was skipped, no artifact or deployment was produced, and public staging remained on the previous healthy SHA. The same code had completed production builds in PR gates `1503` and `1505`, so the observed failure is a runner/build-finalization hang rather than a reported compile error. A manually dispatched diagnostic run does not satisfy the push-only publication contract and must not be treated as an immutable release artifact. + +Prevention: wrap the Gitea frontend production build in a command-level 600-second timeout with an explicit nonzero failure; retain the 45-minute job timeout as a second boundary. Never skip the build, reuse an old artifact, or treat a manual validation-only run as a successful staging push gate. Only a successful exact-SHA push gate may publish images and trigger deployment. + ## Fragment Sweep Command Set ## ERR-086 | Steve Jobs jyotishganit artifacts used non-San-Francisco coordinates | mitigated 2026-07-21 diff --git a/frontend/tests/staging-backend-workflows.test.ts b/frontend/tests/staging-backend-workflows.test.ts index d43117c0..0cce13cb 100644 --- a/frontend/tests/staging-backend-workflows.test.ts +++ b/frontend/tests/staging-backend-workflows.test.ts @@ -210,6 +210,8 @@ test("Gitea quality gate validates before publishing an immutable ACR manifest", assert.equal((workflow.match(/npm test --prefix frontend/g) ?? []).length, 1); assert.equal((workflow.match(/npm run lint --prefix frontend/g) ?? []).length, 1); assert.equal((workflow.match(/npm run build --prefix frontend/g) ?? []).length, 1); + assert.match(workflow, /timeout 600 npm run build --prefix frontend/); + assert.match(workflow, /frontend production build exceeded bounded 600-second timeout/); assert.match(workflow, /needs: validate/); assert.match(workflow, /IMAGE_REPOSITORY: crpi-[^\n]+\/copse\/jyotisha/); assert.match(workflow, /\$IMAGE_REPOSITORY:api-\$GITEA_SHA/);