# Release Rollout

> 产出《发布与回滚预案》：变更面盘点 → 灰度批次与开关 → 监控指标与阈值 → 回滚触发条件与步骤 → 演练记录，落 `dev/release/`。回答的是「怎么发上去」和**「出事了怎么退回来」**这两个问题。 能力：(1) 把代码/配置/数据/契约/依赖五类变更分开定回滚方式 (2) 数据迁移按 expand-contract 拆成可逆步骤， 不可逆操作单列并要人工确认 (3) 每个监控指标带数据来源、观察窗口与回滚阈值 (4) 回滚步骤**必须演练过一次**才算完成。 触发词：「发布方案」「发布预案」「上线方案」「怎么发版」「灰度发布」「灰度放量」「放量节奏」「回滚方案」「回滚预案」 「出事了怎么退回去」「数据迁移能不能回滚」「发布检查单」「上线 checklist」「蓝绿」「金丝雀」「feature flag 怎么配」， 或 `dev-master` 阶段 12 要出上线材料时。 不适用：A/B 实验的分流与显著性判定（`pm-experiment-designer`——它的「灰度」指实验分组，本技能的灰度指**发布放量**）、 面向用户的版本更新文案（`pm-release-notes`）、分支合并与收尾（`finishing-branch`）、 任务分解、开发顺序与进度（`task-breakdown`）、上线前的代码与文档审计（`pm-ai-ship-audit`）。

- Skill: `idwong/release-rollout` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add idwong/release-rollout`
- Raw SKILL.md: https://api.skillmd.com/api/skills/idwong/release-rollout/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: iDWong (https://skillmd.com/u/idwong)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/idwong/release-rollout

---


# release-rollout：发布与回滚预案

> 硬前提：**没有演练过的回滚步骤不算回滚方案**。真到要回滚的那一刻，没人有时间现想。

## 产出

`dev/release/发布与回滚预案-{项目}-V{版本}.md`（存量项目文档在 `docs/` 时按实际目录，不搬家）。
一次发布一份，版本号与本次发布的版本一致。

## Step 1：盘点变更面（五类分开，回滚方式不同）

| 类别 | 举例 | 回滚方式 | 可逆性 |
|---|---|---|---|
| **代码** | 服务镜像、前端产物 | 切回上一个镜像 tag／产物版本 | 可逆（分钟级） |
| **配置** | 环境变量、网关路由、限流阈值 | 改回旧值并重载 | 可逆，但**要记下旧值**，没记就回不去 |
| **数据** | 迁移脚本、数据清洗、字段语义变更 | 见 Step 4 的 expand-contract | **默认不可逆**，要专门设计 |
| **契约** | 接口入参出参、消息体、错误码 | 双端同时回滚，或前向兼容一个版本 | 单端回滚会把另一端打挂 |
| **依赖** | 第三方 SDK、外部服务版本、基础镜像 | 钉版本回退 | 看对方是否保留旧版本 |

**输出一张变更清单**：每行写「类别 / 具体项 / 回滚方式 / 回滚耗时 / 有没有演练」。

## Step 2：灰度批次与开关

- **默认全部新功能挂开关（feature flag），开关默认关**——「发布」与「放开」分成两件事，
  出问题先关开关（秒级），而不是回滚镜像（分钟级）
- 批次按「影响面从小到大」排：内部账号 → 1% → 10% → 50% → 100%，每批之间留**观察窗口**（最短一个完整业务周期）
- 每批写明：放量比例、观察时长、**放行判据**（指标全绿才进下一批）、谁点这个按钮
- 无灰度能力的小项目（单实例部署）照实写「不具备灰度，按低峰期整体发布」，不要编一个假的灰度方案

## Step 3：监控指标与阈值

每条指标必须四要素齐全，缺一条就等于没有监控：

| 指标 | 数据来源 | 观察窗口 | 回滚阈值 |
|---|---|---|---|
| 接口 5xx 率 | 网关日志 / `/metrics` | 发布后 10 分钟 | > 1% 持续 2 分钟 |
| 关键接口 P95 | APM / 日志 | 10 分钟 | 比基线高 50% |
| 业务成功率（下单/发布/登录） | 业务日志埋点 | 30 分钟 | 低于基线 5 个百分点 |
| 错误日志突增 | 日志平台 | 10 分钟 | 同比 3 倍 |

**基线必须是发布前实测的值**，不是拍脑袋的数字；没有监控系统的项目写明「人工看日志 + 手动跑冒烟用例」并给出用例编号。

## Step 4：回滚触发条件与步骤

**触发条件分两类**，写清楚谁有权拍板：

- **自动/无需商量**：命中 Step 3 任一回滚阈值、数据出现错误写入、核心链路不可用 → 立即回滚，事后复盘
- **人工判断**：非核心功能异常、影响面可控 → 值班人 + 负责人两人确认，可选择"关开关"而不是整体回滚

**回滚步骤**写成可照做的命令清单（含数据层），细则与模板见 `references/rollback-playbook.md`：

1. 关功能开关（如果问题在新功能）
2. 切回上一版本镜像／产物，确认健康检查通过
3. 配置回退（对照 Step 1 记录的旧值）
4. 数据层处置：能回滚的回滚，不可逆的执行补偿脚本（**必须提前写好并演练**）
5. 验证：跑冒烟用例，确认核心链路恢复
6. 通告：告知相关方当前状态与影响范围

同时给出 **RTO**（从决定回滚到恢复的目标时长）与实际演练耗时。

## Step 5：演练（不演练不算完成）

在测试环境**真跑一次**：发布 → 制造一个触发条件 → 按步骤回滚 → 验证恢复。
记录：演练日期、执行人、每步实际耗时、发现的问题与修正。演练记录进预案文档，**没有演练记录的预案标「未演练 ⚠」**。

## 硬规则

1. **数据迁移一律 expand-contract 三步**：先加（新增列/表，双写）→ 再迁（回填 + 切读）→ 最后收（删旧）。
   三步分三次发布，**收尾那一步单独一次且不与代码变更同时发**。
2. **不可逆操作单列**：删列、删表、清洗、批量改写历史数据 —— 单独成节，写明影响行数、备份位置、
   恢复办法与**人工确认签字**；预案里没有备份位置的不可逆操作不许执行。
3. **契约变更前向兼容一个版本**：新老两端至少能共存一个发布周期，否则单端回滚就是把另一端打挂。
4. **发布窗口**：避开业务高峰与无人值守时段；写明值班人与联系方式占位。
5. **一次只发一件大事**：大改动与数据迁移不要塞进同一次发布，出问题时无法定位是哪一个。

## 门禁

- [ ] 阶段 11 上线审计无致命项（有则先整改）
- [ ] 变更清单五类齐备，每类都有回滚方式与耗时
- [ ] 每个监控指标四要素齐全，基线是实测值
- [ ] 回滚步骤已演练并记录耗时；不可逆操作有备份位置与确认人
- [ ] 预案已落 `dev/release/`，并在交付说明里链上

## 在 dev-master 流程里的位置

挂 **阶段 12（文档与发版）** 的 `also`：`pm-operation-manual`（手册）+ `pm-release-notes`（对用户的说明）+
**本技能（对自己人的发布与回滚操作手册）** + `finishing-branch`（分支收尾）。四者产出不同，别互相替代。

