Files
memind/docs/release-gate-automation.md

198 lines
9.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 自动发布闸门实现说明
## 当前状态
自动发布闸门采用 fail-closed 设计。机器目录从 `production-release-guardian.md` 加载并校验
187 个连续、唯一场景编号,但常规发布只执行 16 项核心场景和 Git diff 选择的影响域。
关键、共享或无法映射的运行时路径自动升级为完整 187 项;执行器不能把被选择但没有实现、
没有执行或没有证据的场景视为成功。
已经实现:
- `release-gate/catalog.mjs`:187 场景机器目录和永远不可豁免清单。
- `release-gate/safety.mjs`:拒绝生产 IP、`*.tkmind.cn`、生产路径和生产关联环境变量。
- `release-gate/artifact.mjs`runtime 排序目录树 SHA256、依赖闭包和持久数据扫描。
- `release-gate/impact.mjs`Core Gate、changed-path 业务域映射、依赖闭包和全量触发规则。
- `release-gate/runner.mjs`:suite 执行、日志归档和失败关闭。
- `release-gate/report.mjs``report.json`、Markdown、JUnit、环境指纹及四小时有效期。
- `release-gate/regression-corpus.mjs`:脱敏生产回归 fixture 和 active manifest 校验。
- `scripts/verify-release-gate-report.mjs`:校验完整 `main` SHA、artifact SHA,并从 Git diff 重算风险分层选择结果。
- `scripts/release-portal-runtime-prod.sh`:任何 103 连接或上传之前强制验证 Gate report。
当前已经有自动判定证据的场景如下。这里的“覆盖”必须同时满足
`release-gate/coverage.mjs` 中逐场景的业务断言;仅仅执行过一个通用测试文件不能计入。
| 场景组 | 已自动判定 | 总数 | 已覆盖编号 |
|---|---:|---:|---|
| REL | 11 | 11 | REL-01 至 REL-11 |
| AUTH | 8 | 8 | AUTH-01 至 AUTH-08 |
| CHAT | 15 | 15 | CHAT-01 至 CHAT-15 |
| MEM | 16 | 16 | MEM-01 至 MEM-16 |
| FILE | 8 | 8 | FILE-01 至 FILE-08 |
| IMGPG | 8 | 8 | IMGPG-01 至 IMGPG-08 |
| XLS | 12 | 12 | XLS-01 至 XLS-12 |
| PAGE | 13 | 13 | PAGE-01 至 PAGE-13 |
| DATA | 13 | 13 | DATA-01 至 DATA-13 |
| SEARCH | 8 | 8 | SEARCH-01 至 SEARCH-08 |
| AGENT | 11 | 11 | AGENT-01 至 AGENT-11 |
| SCHED | 5 | 5 | SCHED-01 至 SCHED-05 |
| WX | 13 | 13 | WX-01 至 WX-13 |
| BILL | 7 | 7 | BILL-01 至 BILL-07 |
| MS | 9 | 9 | MS-01 至 MS-09 |
| PLAZA | 5 | 5 | PLAZA-01 至 PLAZA-05 |
| CFG | 8 | 8 | CFG-01 至 CFG-08 |
| UI | 8 | 8 | UI-01 至 UI-08 |
| COMP | 9 | 9 | COMP-01 至 COMP-09 |
| **合计** | **187** | **187** | 184 个 suite 映射,加 REL-01/REL-02/REL-04 三项直接检查 |
`REL-03` 会比较候选和两次干净重建的排序目录树 SHA256;`REL-06``REL-07`
分别执行生产配置冷启动和脱敏旧库升级,并断言运行前后 artifact 哈希不变;`REL-11`
在无网络 Linux ARM64 容器中实际加载 Portal、WeChat、worker 和每个 MCP 模块。
全部 187 项都已有自动判定路径。完整 Gate 中未执行的 mode 仍保持 `unknown`;风险分层
Gate 只为自动选中的场景生成结果,所有选中项都必须执行并通过。UI-01 至 UI-08
在隔离本地 Portal、390×844 移动视口和公开页 fixture 上运行;COMP-09 由独立执行器
要求 active 脱敏回归 manifest 并逐条回放。没有 manifest 时 COMP-09 明确 `failed`
不会因“没有用例”而通过。`REL-02` 在候选等于 `origin/main` 且 Gitea commit status 为
`success` 时通过;也可显式注入 `MEMIND_RELEASE_CI_STATUS=success`
常规发布使用风险分层 Gate
```bash
node scripts/run-release-gate-impact.mjs --artifact .runtime/portal --deployed-commit <103-stable-sha>
```
它固定执行 16 项核心场景,再根据 `<103-stable-sha>..HEAD` 的 changed paths 选择业务域及
依赖闭包。`server.mjs`、鉴权/会话基础设施、schema/migration、依赖、runtime 构建、
生产启动/发布脚本、Gate 自身或未映射运行时代码会自动选择完整 187 项。发布脚本在有效报告
缺失或过期时自动执行该入口,不再要求人工先跑多个 mode 或逐项填写 129 条豁免。
离线 `--dry-run` 不连接 103;如需模拟风险分层,可设置
`MEMIND_RELEASE_BASE_COMMIT=<known-stable-sha>`,未提供时安全退化为本地 Full Gate。
2026-07-26 本地补齐验证中,历史完整报告为 180/187 通过;`REL-01` 因当前仍在功能
分支且工作区不干净而失败。PAGE-01/02 与 DATA-01/02/03/04 的隔离栈现在使用后台
直连 LLM`custom_deepseek` / `deepseek-v4-pro`),关闭 relay bootstrap,并将代码/技能
根与隔离数据根分离,避免技能目录为空导致普通用户丢失 `static_publish` 工具。页面发布
约束也明确要求 `sandbox-fs__write_file/edit_file` 命名空间,避免模型误调用不存在的裸工具。
修复后的真实 Agent 回归仍需在最新 runtime 上完成全 6 项终态断言;在此之前不能伪装成通过,
也不能标记为合法 `not_applicable`。生产发布继续禁止。
## 本地命令
先运行框架单元测试:
```bash
npm run test:release-gate:unit
```
构建候选 runtime 后,普通发布运行风险分层闸门:
```bash
npm run build:portal-runtime
node scripts/run-release-gate-impact.mjs \
--artifact .runtime/portal \
--deployed-commit <103-stable-sha>
```
高风险变更、选择器自身变化或定期回归运行完整闸门:
```bash
npm run test:release-gate:all -- --artifact .runtime/portal
```
风险分层或完整报告路径:
```text
.release-gate/<full-main-sha>/report.json
```
单层执行结果存放在:
```text
.release-gate/<full-main-sha>/partials/<mode>/
```
只验证已有报告与当前 artifact:
```bash
npm run verify:release-gate-report -- --artifact .runtime/portal
```
### 耗时控制
完整覆盖不等于 187 条都等待在线 Agent 串行执行:
- 业务规则、权限、账务、记忆、文件和交付契约优先做成确定性 fixture/replay,随
`deterministic` 模式并行执行。
- Gate 执行器默认同时运行 4 个独立 suite,可通过
`--suite-concurrency``RELEASE_GATE_SUITE_CONCURRENCY` 在 116 之间调整;
每个 suite 仍写独立日志并单独判定。
- 必须验证真实 Agent 的场景按不同 session 并行;Page Data 场景默认并发 4
单个 Agent 步骤上限 300 秒、子进程总上限 360 秒。超时直接失败,不允许无限等待。
- 可用 `RELEASE_GATE_SCENARIO_CONCURRENCY`
`RELEASE_GATE_SCENARIO_TIMEOUT_MS`
`RELEASE_GATE_SCENARIO_PROCESS_TIMEOUT_MS` 在 CI 资源范围内收紧预算,不得用它们
放宽为无限超时。
- 风险分层或完整闸门只为干净 `main` 的精确 commit + artifact 生成一次四小时有效报告;
发布脚本复用并校验这份报告,不重复跑慢场景。commit、artifact 或环境指纹变化后
证据立即失效并重新执行。
- 本地开发先跑相关确定性 suite;普通发布候选执行 Core + Impact,完整 187 项用于高风险
候选和定期回归。任何被选择但未执行、超时或缺证据项仍保持 `unknown/failed` 并阻断发布。
报告出现以下任意状态都会返回非零:
- `failed`
- `skipped`
- `blocked`
- `unknown`
- `cleanup_failed`
- 缺少被选择场景,或影响选择结果无法从 Git diff 重现
- 非法 `not_applicable`
- commit、branch 或 artifact SHA 不匹配
- 报告超过四小时
## 增加自动化场景
1. 先在 `release-gate/` 或现有模块中实现确定性测试。
2.`release-gate/coverage.mjs` 新增 suite,明确列出唯一场景 ID 和可执行命令。
3. 一个场景只有在守门员列出的所有强制参数 case 都有断言时,才能映射为 `passed`
4. 为 suite 失败、超时和日志路径增加框架测试。
5. 运行 `npm run test:release-gate:unit` 和对应 mode,确认失败时不会被吞掉。
6. 更新本文的覆盖表。
禁止把大型通用测试命令直接映射到大量场景并据此宣称覆盖;每个映射必须能指出真实业务断言。
## 生产失败回归 fixture
active manifest 约定位置:
```text
scenarios/production-regressions/manifests/active.json
```
每个 active fixture 必须位于 approved bucket,具有:
- `PRC-<GROUP>-NNN` ID。
- 一个或多个 guardian scenario ID。
- 合成意图、规范化失败签名和可执行 replay 命令。
- 不可反查用户的证据摘要和审计批次 ID。
- `contains_personal_data=false`
- 隐私审核人和时间。
当前 active manifest 已包含 `PRC-REL-001`,用于回放 runtime worker 的 18036 端口冲突
回归。原始聊天、用户身份、附件和生产资源地址不得进入仓库或 Gate report。
## 发布脚本保护
生产脚本执行顺序固定为:
1. 检查干净、完整且不落后远端的 `main`
2. 运行既有本地 verify。
3. 构建并检查 `.runtime/portal`
4. 验证与当前 commit 和 runtime tree SHA256 完全一致的风险分层或完整 Gate report;缺失时自动执行风险分层 Gate。
5. Gate report 通过后才允许执行 103 只读预检和任何生产写操作。
6. 再次请求本次发布的明确人工确认。
7. 确认后才允许上传和切换。
`--skip-tests`、范围绕过变量和公开页问题绕过变量均被硬拒绝。