Files
memind/docs/release-gate-automation.md
john 7a381db132
Memind CI / Test, build, and release guards (push) Has been cancelled
refactor: make production gate impact only
2026-07-28 01:13:28 +08:00

9.4 KiB
Raw Permalink Blame History

自动发布闸门实现说明

当前状态

自动发布闸门采用 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.mjsruntime 排序目录树 SHA256、依赖闭包和持久数据扫描。
  • release-gate/impact.mjsCore Gate、changed-path 业务域映射、依赖闭包和未映射阻断规则。
  • release-gate/runner.mjs:suite 执行、日志归档和失败关闭。
  • release-gate/report.mjsreport.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 会连续两次干净重建 runtime,并比较两次排序目录树 SHA256 是否一致;REL-06REL-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 时通过;若仓库未接入 commit status 或状态仍为 pending,候选 SHA 已等于 origin/main 时也视为通过。 仍可用 MEMIND_RELEASE_CI_STATUS=success 显式注入。REL-01 会忽略 .release-gate/.runtime/ 下的本地构建产物,避免 Gate 前构建 runtime 误报工作区脏。

常规发布使用风险分层 Gate

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 自身会展开到预定义影响域;未映射运行时代码直接失败。发布脚本在有效报告 缺失或过期时自动执行该入口,不再要求人工先跑多个 mode 或逐项填写 129 条豁免。 离线 --dry-run 不连接 103;如需模拟风险分层,可设置 MEMIND_RELEASE_BASE_COMMIT=<known-stable-sha>;未提供有效基线时直接阻断。

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。生产发布继续禁止。

本地命令

先运行框架单元测试:

npm run test:release-gate:unit

构建候选 runtime 后,普通发布运行风险分层闸门:

npm run build:portal-runtime
node scripts/run-release-gate-impact.mjs \
  --artifact .runtime/portal \
  --deployed-commit <103-stable-sha>

人工或定期目录审计仍可运行完整闸门,但生产发布脚本不会调用它:

npm run test:release-gate:all -- --artifact .runtime/portal

风险分层或完整报告路径:

.release-gate/<full-main-sha>/report.json

单层执行结果存放在:

.release-gate/<full-main-sha>/partials/<mode>/

只验证已有报告与当前 artifact:

npm run verify:release-gate-report -- --artifact .runtime/portal

耗时控制

完整覆盖不等于 187 条都等待在线 Agent 串行执行:

  • 业务规则、权限、账务、记忆、文件和交付契约优先做成确定性 fixture/replay,随 deterministic 模式并行执行。
  • Gate 执行器默认同时运行 4 个独立 suite,可通过 --suite-concurrencyRELEASE_GATE_SUITE_CONCURRENCY 在 1~16 之间调整; 每个 suite 仍写独立日志并单独判定。
  • 必须验证真实 Agent 的场景按不同 session 并行;Page Data 场景默认并发 4 单个 Agent 步骤上限 300 秒、子进程总上限 360 秒。超时直接失败,不允许无限等待。
  • 可用 RELEASE_GATE_SCENARIO_CONCURRENCYRELEASE_GATE_SCENARIO_TIMEOUT_MSRELEASE_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 约定位置:

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、范围绕过变量和公开页问题绕过变量均被硬拒绝。