上线就绪清单

上线就绪清单用于在代码发布到生产环境之前,做最后的系统性检查。目标不是阻止发布,而是确保发布可控——出问题能及时发现、快速恢复。

要点

  • 上线就绪清单在发布前做最后检查,确保发布可控
  • 重点检查:测试覆盖、数据迁移、配置环境、监控告警、回滚方案
  • 灰度发布:1% → 10% → 50% → 100%,每个阶段观察指标
  • 回滚方案必须可行,能在 15 分钟内完成

1. 适用时机

  • 新功能发布到生产环境
  • 重大重构上线
  • 数据迁移执行
  • 基础设施变更(数据库、中间件、配置)
  • 第三方服务切换

不需要上线就绪清单的场景:

  • 小 bug 修复(有测试覆盖 + 回滚方案即可)
  • 配置微调(有变更记录)
  • 文档更新

2. 核心检查项

2.1 代码与测试

  • 所有 PR 已合并并通过代码评审
  • 自动化测试全通过(单元、集成、E2E)
  • 手动测试覆盖关键路径(产品/QA 验收)
  • 性能测试通过(压测报告在预期范围内)
  • 安全扫描无高危漏洞

2.2 数据迁移

  • 迁移脚本已 review,幂等可重复执行
  • 大表迁移分批执行方案(避免锁表)
  • 迁移数据量估算和耗时预估
  • 回滚方案明确(失败后如何恢复)
  • 数据校验步骤(迁移后对比源和目标)

Cloudflare D1 迁移示例

// wrangler.toml
[[migrations]]
tag = "v1"
new_classes = ["UserCounter"]
 
// 迁移脚本:migrations/001_add_user_table.sql
CREATE TABLE IF NOT EXISTS users (
  id TEXT PRIMARY KEY,
  name TEXT NOT NULL,
  email TEXT NOT NULL UNIQUE,
  created_at INTEGER NOT NULL
);
 
// 执行迁移
// wrangler d1 execute my-database --file=migrations/001_add_user_table.sql
 
// 验证迁移
// wrangler d1 execute my-database --command="SELECT COUNT(*) FROM users"

2.3 配置与环境

  • 生产环境配置准备(环境变量、密钥、Feature Flag)
  • 数据库连接、缓存连接、第三方 API Key 配置正确
  • 日志级别设置正确(生产不用 DEBUG)
  • CDN / 缓存失效策略明确
  • DNS / 负载均衡配置(如涉及)

wrangler.toml 配置示例

# wrangler.toml
name = "my-app"
main = "src/index.ts"
compatibility_date = "2026-06-21"
 
# 环境变量
[env.production]
vars = { ENVIRONMENT = "production", LOG_LEVEL = "info" }
 
# D1 数据库
[[env.production.d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "xxx-xxx-xxx"
 
# KV 命名空间
[[env.production.kv_namespaces]]
binding = "KV"
id = "xxx-xxx-xxx"
 
# R2 存储桶
[[env.production.r2_buckets]]
binding = "BUCKET"
bucket_name = "my-bucket"
 
# 密钥(通过 wrangler secret put 设置)
# wrangler secret put API_KEY
# wrangler secret put DATABASE_URL

2.4 监控与告警

  • 关键业务指标有监控(订单量、注册数、转化率)
  • 系统指标有监控(错误率、延迟、CPU、内存)
  • 告警规则配置(阈值、通知人、升级路径)
  • Dashboard 准备好(发布后实时观察)
  • 日志查询方式已知(出问题能立即查日志)

Hono 示例:健康检查端点

import { Hono } from 'hono'
 
const app = new Hono()
 
// 健康检查端点
app.get('/health', (c) => {
  return c.json({
    status: 'ok',
    timestamp: new Date().toISOString(),
    version: process.env.APP_VERSION || 'unknown'
  })
})
 
// 深度健康检查:检查依赖服务
app.get('/health/ready', async (c) => {
  const checks = {
    database: false,
    cache: false,
    externalApi: false
  }
 
  try {
    // 检查数据库
    await c.env.DB.prepare('SELECT 1').first()
    checks.database = true
  } catch (error) {
    console.error('Database check failed:', error)
  }
 
  try {
    // 检查缓存
    await c.env.KV.get('health:check')
    checks.cache = true
  } catch (error) {
    console.error('Cache check failed:', error)
  }
 
  const allHealthy = Object.values(checks).every(v => v)
 
  return c.json({
    status: allHealthy ? 'ok' : 'degraded',
    checks,
    timestamp: new Date().toISOString()
  }, allHealthy ? 200 : 503)
})

2.5 回滚方案

  • 回滚方式明确(代码回滚、Feature Flag、数据库回滚)
  • 回滚步骤文档化,能在 15 分钟内完成
  • 回滚后数据一致性确认(新旧数据结构兼容?)
  • 回滚演练过(不是「理论上能回滚」)
  • 回滚决策人明确(谁有权决定是否回滚)

回滚步骤示例

# 代码回滚
# 1. 找到上一个稳定版本
git log --oneline -10
 
# 2. 回滚到指定版本
git revert <commit-hash>
 
# 3. 部署
wrangler deploy
 
# Feature Flag 回滚(更快)
# 1. 关闭新功能
wrangler kv:key put --binding=FEATURE_FLAGS 'new-feature-enabled' 'false'
 
# 数据库回滚
# 1. 执行回滚迁移
wrangler d1 execute my-database --file=migrations/rollback_001.sql
 
# 2. 验证数据
wrangler d1 execute my-database --command="SELECT COUNT(*) FROM users"

2.6 灰度策略

  • 灰度比例确定(1% → 10% → 50% → 100%)
  • 灰度观察指标明确(看什么指标判断是否正常)
  • 灰度持续时间确定(每个阶段观察多久)
  • 灰度扩大/回滚的触发条件(错误率 > 1% 就回滚)
  • 灰度用户选择(内部用户、白名单用户、随机抽样)

Hono 示例:灰度发布

import { Hono } from 'hono'
 
const app = new Hono()
 
// 灰度中间件
app.use('*', async (c, next) => {
  const userId = c.req.header('X-User-ID') || 'anonymous'
 
  // 从 KV 读取灰度配置
  const config = await c.env.KV.get('gray-release', 'json') || {
    enabled: false,
    percentage: 0,
    whitelist: []
  }
 
  // 白名单用户
  if (config.whitelist.includes(userId)) {
    c.set('useNewFeature', true)
    return next()
  }
 
  // 按比例灰度
  const hash = userId.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0) % 100
  if (config.enabled && hash < config.percentage) {
    c.set('useNewFeature', true)
    return next()
  }
 
  c.set('useNewFeature', false)
  return next()
})
 
app.get('/api/data', (c) => {
  const useNewFeature = c.get('useNewFeature')
 
  if (useNewFeature) {
    // 新版本逻辑
    return c.json({ version: 'v2', data: 'new' })
  }
 
  // 旧版本逻辑
  return c.json({ version: 'v1', data: 'old' })
})

2.7 沟通与协调

  • 发布时间确定(避开高峰、节假日)
  • 相关团队已通知(客服、运营、产品、依赖方)
  • 用户公告准备(如有影响)
  • 发布负责人明确(谁负责执行、谁负责观察、谁负责决策)
  • 发布期间 on-call 人员安排

2.8 文档与记录

  • 变更日志(changelog)已更新
  • 用户文档已更新(如涉及功能变化)
  • 运维文档已更新(如涉及部署变化)
  • 发布记录模板准备(记录发布时间、版本、负责人、观察结果)

2.9 发布后验证

  • 冒烟测试步骤准备(发布后立即执行的关键路径检查)
  • 验证指标确定(看什么数据判断发布成功)
  • 验证负责人明确
  • 验证时间窗口确定(发布后 1 小时、24 小时、72 小时)

冒烟测试示例

#!/bin/bash
# smoke-test.sh
 
BASE_URL="https://api.example.com"
 
echo "Running smoke tests..."
 
# 1. 健康检查
curl -f "$BASE_URL/health" || exit 1
 
# 2. 核心接口
curl -f "$BASE_URL/api/v1/users" || exit 1
 
# 3. 写入测试
curl -f -X POST "$BASE_URL/api/v1/test" \
  -H "Content-Type: application/json" \
  -d '{"test": true}' || exit 1
 
echo "Smoke tests passed!"

3. 发布流程模板

一个典型的发布流程:

T-1d:最终检查(代码冻结、配置确认、回滚方案确认)
T-2h:通知相关团队(即将发布)
T-0:执行发布(代码部署 + 数据迁移)
T+5min:冒烟测试(关键路径验证)
T+30min:灰度 1%(观察指标)
T+2h:灰度 10%(观察指标)
T+6h:灰度 50%(观察指标)
T+24h:全量 100%(持续观察)
T+72h:发布确认(指标正常,发布成功)

4. 评审会上容易漏的点

  1. 回滚方案:问「发布后发现问题,怎么回滚?需要多久?」
  2. 数据迁移:问「数据迁移需要多久?会影响在线服务吗?」
  3. 监控告警:问「怎么知道发布成功了?看什么指标?」
  4. 沟通:问「客服知道这次发布吗?用户会看到什么变化?」
  5. 决策权:问「出问题了谁决定回滚?」

5. 通过标准

  • 所有阻塞项(blocking)已解决
  • 回滚方案可行,演练过
  • 监控告警到位
  • 灰度策略明确
  • 沟通已到位
  • 发布负责人确认

6. 不发布的情况

以下情况应该推迟发布:

  • 关键测试失败
  • 回滚方案没想清楚
  • 监控告警没配
  • 相关团队没通知
  • 发布负责人不在
  • 临近节假日或业务高峰

7. 维护建议

上线就绪清单需要随团队实践更新:

  • 发布流程变化时(如从手动切到自动),调整相关检查项
  • 出现发布相关的事故后,把根因对应的检查项加进来
  • 团队规模扩大时,强化沟通和协调要求
  • 每半年复审一次,删除过时的检查项