diff --git a/.gitea/workflows/release-quality-gate.yml b/.gitea/workflows/release-quality-gate.yml index b235097f..57a97f4e 100644 --- a/.gitea/workflows/release-quality-gate.yml +++ b/.gitea/workflows/release-quality-gate.yml @@ -5,7 +5,7 @@ on: jobs: release-quality-gate: - runs-on: xiaoxin + runs-on: manman-linux timeout-minutes: 45 env: GITEA_SHA: ${{ gitea.sha }} @@ -25,6 +25,7 @@ jobs: node --version npm --version docker version + docker compose version --short | grep -Eq '^v?2\.' - name: Install dependencies and run release gate env: NEXT_PUBLIC_SUPABASE_URL: https://ci-placeholder.supabase.co diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 04254e53..16f5d764 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -2568,3 +2568,19 @@ - 相关记录:BUG-142、BUG-149 - 复发自:无 - 修复版本:待本次提交 / gate / deploy + +## BUG-151 | 手工 Release Gate 被分配到缺少 Docker Compose v2 的 runner + +- 状态:mitigated +- 首次发现:2026-08-09 +- 最近更新:2026-08-09 +- 影响面:Gitea 手工 `release-quality-gate.yml` Run `1638`;旧生产、Supabase、DNS 和新生产应用均未被切换。 +- 用户现象:候选 SHA `9235ee66f6d889e6c27e4b85411448889dd7d37d` 已通过 staging gate 并在公网 staging 运行,但手工 Release Gate 在 1113 个前端子测试中出现 17 个失败。失败均从 `docker compose --project-name` 或 `docker compose --env-file` 返回 `unknown flag` 开始。 +- 触发条件:完整 release profile 在 `xiaoxin` runner 执行 PostgreSQL/Compose 集成测试,而该 runner 只有 Docker CLI、没有可用的 Docker Compose v2 插件。 +- 根因:workflow 的工具链预检只执行 `docker version`,未验证 `docker compose`;同时 Release Gate 与已验证具备 Compose v2 的 staging/backend runner 分离,导致环境能力漂移直到完整测试阶段才暴露。 +- 修复:将手工 Release Gate 收敛到 `manman-linux`,并在依赖安装前强制 `docker compose version --short` 必须为 v2;增加 workflow 回归断言,防止重新绑定到无 Compose runner 或删除能力检查。 +- 验证:Run `1638` 的脱敏日志确认 17 个失败均由 Compose 命令不可用触发;同日 `manman-linux` 的 backend gate Run `1636` 已报告 Docker Compose `2.40.3` 并成功完成质量门;本地聚焦 workflow 测试 4/4 通过。仍需新 SHA 的手工 Release Gate 成功后再视为完整关闭。 +- 防复发:任何执行 Compose 集成测试的 runner 必须在昂贵依赖安装和测试前显式验证 Compose v2;Docker Engine 可用不能替代 Compose 能力证明。 +- 相关记录:BUG-128、BUG-129、BUG-136、ERR-095、ERR-099、ERR-103 +- 复发自:无 +- 修复版本:待新 SHA 的 Release Gate 验证 diff --git a/docs/research/pre_work_error_ledger.md b/docs/research/pre_work_error_ledger.md index 6a0fa122..28f947d6 100644 --- a/docs/research/pre_work_error_ledger.md +++ b/docs/research/pre_work_error_ledger.md @@ -257,3 +257,9 @@ Prevention: classify insufficient candidate-range discrimination explicitly; whe Two final `git fetch origin --prune` attempts against the configured primary Gitea remote failed before ref exchange with HTTP `502`. The last locally verified refs remain available, but this run cannot prove that they are still current and must not claim a completed remote synchronization or push. Prevention: retry fetch and `git ls-remote` before any push or release action, compare the full `main`, `staging`, and migration-branch SHAs, and stop if Gitea remains unavailable. Do not substitute cached refs, the GitHub mirror, or a successful local commit for current Gitea synchronization evidence. + +## ERR-103 | Release Gate runner 缺少 Docker Compose v2 导致 17 个集成测试级联失败 | mitigated 2026-08-09 + +手工 Release Gate Run `1638` 在 `xiaoxin` 上通过 Docker Engine 检查后进入完整测试,但该 runner 不支持 `docker compose`,`--project-name` 与 `--env-file` 被 Docker 顶层 CLI 判为 unknown flag,导致 17 个 PostgreSQL、备份、身份和权限集成测试级联失败。候选 staging SHA、旧生产、Supabase 与 DNS 未被改变。 + +Prevention: 将该门禁运行在已验证 Docker Compose v2 的 `manman-linux`,并在安装依赖前以 `docker compose version --short` 强制 v2;不得把 `docker version` 当作 Compose 能力证明。新 SHA 必须重新完成 staging gate、公网 staging 身份和手工 Release Gate,失败 run 不得授权生产 migration、deploy 或维护停写。 diff --git a/frontend/tests/staging-backend-workflows.test.ts b/frontend/tests/staging-backend-workflows.test.ts index db665f16..a070ac36 100644 --- a/frontend/tests/staging-backend-workflows.test.ts +++ b/frontend/tests/staging-backend-workflows.test.ts @@ -46,6 +46,10 @@ const giteaProductionMigrationWorkflow = new URL( "../../.gitea/workflows/migrate-production-database.yml", import.meta.url, ); +const giteaReleaseQualityWorkflow = new URL( + "../../.gitea/workflows/release-quality-gate.yml", + import.meta.url, +); const resetStagingAccountWorkflow = new URL( "../../.github/workflows/reset-staging-account.yml", import.meta.url, @@ -875,6 +879,14 @@ test("run-local registry state and incoming trees are always cleaned up", () => } }); +test("manual release gate runs where Docker Compose v2 is available", () => { + const workflow = read(giteaReleaseQualityWorkflow); + + assert.match(workflow, /^on:\n\s+workflow_dispatch:/m); + assert.match(workflow, /runs-on: manman-linux/); + assert.match(workflow, /docker compose version --short \| grep -Eq '\^v\?2\\\.'/); +}); + test("production deploy is manual-only and consumes the accepted staging artifact", () => { const mirror = readFileSync(new URL("../../.github/workflows/deploy-production.yml", import.meta.url), "utf8"); const production = read(giteaProductionWorkflow);