Skip to content
返回质量保障

管道设计

将 CI 管道设计为一系列快独立门控、从便宜到贵渐进抓问题。

为什么

CI 管道是一系列质量门控——每门控抓一类问题(lint 抓样式、类型检查抓类型错、单元测试抓逻辑 bug、e2e 抓集成 bug)问题存在时阻构建。管道设计定反馈速度(快门控给快反馈、慢门控阻开发者)和缺陷漏(缺或太弱门控让 bug 到生产)。关键原则是渐进过滤: 先跑便宜快门控(lint 10 秒)后跑贵慢门控(e2e 10 分钟)、大多失败快抓、仅少数过所有便宜门控的 PR 付贵门控代价。并行跑所有门控等所有完的管道比先跑便宜门控失败短路的慢。无门控管道让每 bug 过;太多门控管道慢开发者绕。艺术是找对门控集——足够抓重要 bug、快到不阻开发者。

何时使用

项目开始和反馈环感太慢或太多 bug 到生产时——管道设计是两者杠杆。

如何做

1. 识你需的门控
   - Lint(样式、常见 bug): 10-30 秒
   - 类型检查(类型错): 30-60 秒
   - 单元测试(逻辑): 1-5 分钟
   - 集成测试(API、DB): 5-10 分钟
   - E2E 测试(用户流): 10-30 分钟
   - 安全扫描(CVE、SAST): 2-5 分钟
   - 构建(编译、打包): 1-5 分钟

2. 从便宜到贵排门控
   - 先 lint(10 秒)——失败则停(坏代码无点跑测试)
   - 后类型检查(30 秒)——失败则停
   - 后单元测试(2 分)——失败则停
   - 后构建(3 分)——失败则停
   - 后集成测试(5 分)——失败则停
   - 后 e2e(15 分)——仅以上都过才跑
   - 这首次失败短路、省时

3. 并行跑独立门控
   - Lint 和类型检查可并行(都快、独立)
   - 单元测试和安全扫描可并行
   - 但单元测试过前不跑 e2e(e2e 贵)
   - 用矩阵构建并行作业

4. 激进缓存
   - 依赖: 缓存 node_modules、~/.m2、~/.cargo
   - 构建产物: 缓存 dist/、target/、build/
   - 测试结果: 缓存测试结果跳未改测试
   - 这减门控时间从分钟到秒

5. 使门控强制
   - 分支保护: 合前要求所有门控过
   - 不允许绕(即使管理员)
   - 可绕门控是被绕门控

6. 监控调优
   - 追管道时间(中位和 90 百分位)
   - 管道慢识最慢门控优化
   - bug 漏识缺门控加
   - 管道非设后忘;随项目演进

示例

# .github/workflows/ci.yml — 渐进门控
name: CI
on: [pull_request]

jobs:
  # 门控 1: Lint(10 秒)——最便宜、先跑
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx eslint . --max-warnings 0
      - run: npx prettier --check .

  # 门控 2: 类型检查(30 秒)——与 lint 并行
  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx tsc --noEmit

  # 门控 3: 单元测试(2 分)——lint 和 typecheck 过后
  unit-test:
    needs: [lint, typecheck]  # 等便宜门控
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test -- --coverage --maxWorkers=4

  # 门控 4: 构建(3 分)——单元测试过后
  build:
    needs: [unit-test]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run build

  # 门控 5: E2E 测试(15 分)——贵、仅以上都过才跑
  e2e-test:
    needs: [build]  # 等构建
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run build
      - run: npx playwright test

# 分支保护: 要求所有门控过
# 设置 > 分支 > 分支保护规则:
# - 要求状态检查: lint、typecheck、unit-test、build、e2e-test
# - 合前要求分支最新
# - 不允许绕(即使管理员)

# 缓存: 加速门控
# .github/workflows/ci.yml(每作业加):
#   - uses: actions/cache@v4
#     with:
#       path: node_modules
#       key: ${{ runner.os }}-deps-${{ hashFiles('package-lock.json') }}

常见问题

  • ⚠并行跑所有门控等所有完——lint 失败 10 秒抓但管道等 15 分钟 e2e 完才报失败、开发者阻 15 分钟于 10 秒问题。
  • ⚠无论改什么每 PR 跑 e2e——仅 CSS 改触 15 分钟 e2e、开发者等 15 分钟不可能失败的门控、管道感慢。
  • ⚠允许管理员绕门控——资深开发者推类型检查不过代码、团队学门控可选、门控变戏非真保护。
  • ⚠完全无门控——每 PR 直合 main、bug 发到生产、团队靠热修非预防、比 CI 门控贵 10 倍。

最佳实践

  • ✓从便宜到贵排门控(lint 10 秒 → 类型检查 30 秒 → 单元测试 2 分 → 构建 3 分 → e2e 15 分)首次失败短路——这给大多失败快反馈、仅过便宜门控的 PR 付贵门控。
  • ✓并行跑独立门控(lint 和类型检查)但用 needs: 等便宜门控后跑贵——并行加速管道但渐进过滤失败短路。
  • ✓激进缓存依赖、构建产物和测试结果——这减门控时间从分钟到秒、快管道是开发者不绕的管道。
  • ✓分支保护使所有门控强制不允许绕(即使管理员)——可绕门控是被绕门控、团队学门控可选。