# Dry-run 渐进开关：CI 自动化 / 阻断性工具上线的通用模式

**日期**: 2026-04-29
**上下文**: 启用 ai-review.yml（AI 自动审 PR、有可能 BLOCK 合并），第一次开就直接进 required check 的话风险高——AI 误报会卡住一堆 PR、prompt 没调好一堆噪音、token / 配额炸了等等。

不只是 AI review，任何**可能阻断关键路径**的自动化都适用这个模式：lint / 安全扫描 / 合规检查 / 自动 release-gate 等。

## 模式三步

### Step 1：影子模式（Dry-run）

工具跑、但**不写任何外部状态**。具体几个开关位置：

```yaml
env:
  TOOL_DRY_RUN: '1'        # 工具自身 env，最干净
  # 或者：
  TOOL_OUTPUT_TARGET: log   # 只打日志，不写评论 / status / issue
```

工具内部的 dry-run 实现规范：
- 不调 Gitea/GitHub API 的写接口（POST/PUT/PATCH）
- **可以**调读接口（拉 PR diff 等输入）
- 把"本来要写的内容"完整打到 stdout，加 `[DRY RUN]` 前缀
- exit code 跟正式跑一样（成功 0、失败 1）——这样转正只需删 dry-run 开关

### Step 2：观察期

跑 1-2 周或 N 个 PR（取够样本数 + 多种场景）。观察重点：
- 输出**质量**（不是有没有跑出来，是跑出来的内容对不对）
- **误报集中点**：哪类问题报的不对？调 prompt / 规则
- **漏报**：故意提交一个有真问题的 PR，看抓不抓得住
- **耗时 / 资源**：会不会拖慢 CI？吃多少 runner 容量？

样本量参考：
- 高频工具（每个 PR 都跑）：≥ 30 个 PR
- 低频工具（只 PR → staging/production 跑）：≥ 5 个 PR

### Step 3：转正

满足验收标准（建议 70% 准确率以上）才转正：
1. 删 dry-run 开关
2. 加进 branch protection 的 required checks
3. 同步更新 docs

## 可复用模板（实际从 ai-review.yml 抽）

```yaml
on:
  pull_request:
    types: [opened, synchronize, reopened]
    branches: [develop, staging, production]

jobs:
  the-tool:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          ./run-tool.sh   # 工具自己读 TOOL_DRY_RUN
        env:
          TOOL_DRY_RUN: '1'  # ← 观察期；转正时删这一行
```

工具脚本内：
```bash
if [ -n "${TOOL_DRY_RUN:-}" ]; then
  echo "[DRY RUN] 本来会发的评论："
  echo "$BODY"
else
  curl -X POST .../comments -d ...
fi
```

## 跟"feature flag"的区别

Feature flag 是给**业务功能**逐步放量。Dry-run 是给**自动化工具**逐步加权——区别：
- feature flag 影响用户体验、需要 A/B 数据
- dry-run 影响开发者体验、只观察工具自己输出
- feature flag 可能永久保留（按用户分群），dry-run 是**有终点的**（要么转正要么放弃）

## 适用场景

✅ 适用：
- AI review / 智能 lint
- 安全扫描（GitLeaks、Semgrep、SAST）
- 合规检查（commit message 规范、文件命名）
- 自动 release-gate（看变更范围决定是否能上线）
- 任何"我觉得这个 check 有用，但不确定误报多不多"的场景

❌ 不适用：
- 编译器 / 类型检查（确定的、不该 dry-run，直接开）
- 测试（pass/fail 是工具自身定义清楚的，不存在"准确率"问题）
- 已经在别处验证过的工具（直接开）

## 启动检查清单

开 dry-run 前确认：
- [ ] 工具脚本支持 dry-run 开关
- [ ] dry-run 时**真的**不写任何外部状态（review 一遍代码）
- [ ] 输出格式对人友好（不是堆 JSON 让人猜）
- [ ] 失败模式：工具自身 crash 是 fail 还是 skip？默认 skip 更稳（不阻断 CI）
- [ ] 关闭路径：能一行删掉 trigger 退回 workflow_dispatch only

## 关联

- 本仓库 ai-review.yml + scripts/ops/ai-review-runner.sh 是这个模式的实例
- Issue #171 跟踪 ai-review 转正评估
- `.learnings/2026-04-29-ai-review-enablement.md` 启用过程具体踩坑

## 是否提炼成 skill

值得。**适用面广**（不限于 AI review，任何 CI 自动化上线都能用）+ **重复出现**（公司层面会反复启用各种新工具）。建议未来可考虑做成 `.agents/skills/dryrun-rollout/` 或者并入现有 `code-review` skill 的 references。先观察 ai-review 转正过程是否真按这套走顺，再决定是否提炼。
