From b0a1174eae022dac7955bebe0e6d3f6d757848dc Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Sat, 15 Aug 2026 14:32:40 +0800 Subject: [PATCH] test(deploy): guard unreadable staging revision fallback --- docs/BUG_HISTORY.md | 15 +++++++++++++++ frontend/tests/staging-backend-workflows.test.ts | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index e4ccd64e..ac468509 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -3258,3 +3258,18 @@ - 防复发:版本化第三方研究快照必须检查外层 ignore 规则导致的漏文件;registry hash 必须从完整、可由 clean checkout 重建的 Git tree 生成,不能通过放宽 hash traversal 掩盖缺失源码。 - 相关记录:BUG-190、BUG-191 - 修复版本:本次功能分支提交(精确 SHA 以提交、远程分支和 staging 发布核对结果为准) + +## BUG-193 | staging revision 状态文件存在但不可读时部署提前失败 + +- 状态:resolved(待 staging 精确 SHA 发布验收) +- 首次发现:2026-08-14 +- 最近更新:2026-08-15 +- 影响面:staging 部署和数据库迁移的 forward-only revision 检查。 +- 用户现象:`.state/deployed-revision` 已存在但部署用户无法读取时,发布流程在比较旧、新 revision 之前以 `Permission denied` 退出,无法使用运行中容器的 `GITHUB_SHA` 完成回退发现。 +- 触发条件:状态文件由不同权限上下文写入,文件存在但当前执行用户没有读取权限。 +- 根因:GitHub staging workflow、`run-staging-deploy.sh` 和 `run-staging-migration.sh` 只用 `-f` 判断文件存在;存在性不代表可读性,因此错误地进入直接读取分支。 +- 修复:将三处判断收紧为 `-r`;状态文件不可读时按既有协议从当前 Web 容器发现 `GITHUB_SHA`。Gitea staging deploy workflow 已有相同的可读性判断,保持不变。 +- 验证:新增部署合同测试锁定 workflow 与两个 runner 必须使用 `-r`;聚焦部署测试、Shell 语法检查、正式 staging gate、精确 SHA 部署与非 Playwright HTTP 健康检查分别记录。 +- 防复发:任何 revision state 快路径都必须验证可读性,并保留容器镜像 revision 的只读回退,不得仅以路径存在作为可消费条件。 +- 相关记录:BUG-083、BUG-192 +- 修复版本:本次 staging 集成提交(精确 SHA 以远端 staging 与部署结果为准) diff --git a/frontend/tests/staging-backend-workflows.test.ts b/frontend/tests/staging-backend-workflows.test.ts index 2ec43a5b..4c6cd5a5 100644 --- a/frontend/tests/staging-backend-workflows.test.ts +++ b/frontend/tests/staging-backend-workflows.test.ts @@ -398,6 +398,13 @@ test("staging deployment scripts validate deploy-owned env files", () => { } }); +test("staging revision discovery falls back when the state file is unreadable", () => { + assert.ok(read(deployWorkflow).includes('if [ -r \\"\\$state\\" ]')); + for (const runner of [read(deployScript), read(migrationScript)]) { + assert.ok(runner.includes('if [ -r "$state_directory/deployed-revision" ]')); + } +}); + test("quality gate builds the Python package with its declared backend dependencies", () => { const workflow = read(qualityWorkflow);