# CI CD And Automation

> 自动化 CI/CD 流水线配置。适用于搭建或修改构建与部署流水线时，也适用于需要自动化质量门禁、在 CI 中配置测试执行器，或建立部署策略的时候。

- Skill: `233i/ci-cd-and-automation` (Agent Skill)
- Install (CLI): `npx skillmds@latest add 233i/ci-cd-and-automation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/233i/ci-cd-and-automation/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: 233i (https://skillmd.com/u/233i)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/233i/ci-cd-and-automation

---


# CI/CD 与自动化

## 概览

把质量门禁自动化，确保任何改动在通过测试、lint、类型检查和构建之前，都不能进入生产环境。CI/CD 是其他所有 skill 的执行保障机制，它能稳定地捕捉人类和 agent 都会漏掉的问题，而且对每一次改动一视同仁。

**Shift Left：** 尽量在流水线更前面发现问题。一个在 lint 阶段发现的 bug，代价可能只是几分钟；同样的问题到了生产环境，代价可能是几小时。要把检查前移，静态分析早于测试，测试早于 staging，staging 早于 production。

**越快越安全：** 更小的改动批次和更频繁的发布，并不会增加风险，反而会降低风险。只有 3 个改动的部署，比带着 30 个改动的部署更容易调试。频繁发布也会增强团队对发布流程本身的信心。

## 何时使用

- 为新项目搭建 CI 流水线
- 增加或修改自动化检查
- 配置部署流水线
- 某项改动应该触发自动验证时
- 调试 CI 失败

## 质量门禁流水线

每一个改动在合并前都必须通过这些门禁：

```
Pull Request Opened
    │
    ▼
┌─────────────────┐
│   LINT CHECK     │  eslint, prettier
│   ↓ pass         │
│   TYPE CHECK     │  tsc --noEmit
│   ↓ pass         │
│   UNIT TESTS     │  jest/vitest
│   ↓ pass         │
│   BUILD          │  npm run build
│   ↓ pass         │
│   INTEGRATION    │  API/DB tests
│   ↓ pass         │
│   E2E (optional) │  Playwright/Cypress
│   ↓ pass         │
│   SECURITY AUDIT │  npm audit
│   ↓ pass         │
│   BUNDLE SIZE    │  bundlesize check
└─────────────────┘
    │
    ▼
  Ready for review
```

**任何门禁都不能跳过。** Lint 失败就修 lint，不要关规则。测试失败就修代码，不要跳过测试。

## GitHub Actions 配置

### 基础 CI 流水线

```yaml
# .github/workflows/ci.yml
name: CI

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Type check
        run: npx tsc --noEmit

      - name: Test
        run: npm test -- --coverage

      - name: Build
        run: npm run build

      - name: Security audit
        run: npm audit --audit-level=high
```

### 带数据库集成测试

```yaml
  integration:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_DB: testdb
          POSTGRES_USER: ci_user
          POSTGRES_PASSWORD: ${{ secrets.CI_DB_PASSWORD }}
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'
      - run: npm ci
      - name: Run migrations
        run: npx prisma migrate deploy
        env:
          DATABASE_URL: postgresql://ci_user:${{ secrets.CI_DB_PASSWORD }}@localhost:5432/testdb
      - name: Integration tests
        run: npm run test:integration
        env:
          DATABASE_URL: postgresql://ci_user:${{ secrets.CI_DB_PASSWORD }}@localhost:5432/testdb
```

> **注意：** 即使是 CI 专用的测试数据库，也要把凭据放在 GitHub Secrets，而不是硬编码进配置。这能帮助团队养成正确习惯，也能避免测试凭据被错误地复制到其他环境。

### E2E 测试

```yaml
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'
      - run: npm ci
      - name: Install Playwright
        run: npx playwright install --with-deps chromium
      - name: Build
        run: npm run build
      - name: Run E2E tests
        run: npx playwright test
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report
          path: playwright-report/
```

## 把 CI 失败反馈给 Agent

CI 和 AI agent 结合的关键，是反馈闭环。CI 一旦失败：

```
CI fails
    │
    ▼
Copy the failure output
    │
    ▼
Feed it to the agent:
"The CI pipeline failed with this error:
[paste specific error]
Fix the issue and verify locally before pushing again."
    │
    ▼
Agent fixes → pushes → CI runs again
```

**关键模式：**

```
Lint failure → Agent runs `npm run lint --fix` and commits
Type error  → Agent reads the error location and fixes the type
Test failure → Agent follows debugging-and-error-recovery skill
Build error → Agent checks config and dependencies
```

## 部署策略

### 预览部署

每个 PR 都应该有一个预览部署，供人工验证：

```yaml
# Deploy preview on PR (Vercel/Netlify/etc.)
deploy-preview:
  runs-on: ubuntu-latest
  if: github.event_name == 'pull_request'
  steps:
    - uses: actions/checkout@v4
    - name: Deploy preview
      run: npx vercel --token=${{ secrets.VERCEL_TOKEN }}
```

### Feature Flags

Feature flag 让“部署”和“发布”解耦。把未完成或高风险功能放在 flag 后面，这样你就可以：

- **代码先上线，不立即启用**
- **无需重新部署即可回滚**，直接关掉 flag
- **做 canary**，先 1%，再 10%，最后 100%
- **做 A/B 测试**，比较开关两种行为差异

```typescript
// Simple feature flag pattern
if (featureFlags.isEnabled('new-checkout-flow', { userId })) {
  return renderNewCheckout();
}
return renderLegacyCheckout();
```

**Flag 生命周期：** Create → Enable for testing → Canary → Full rollout → Remove the flag and dead code。  
永远不清理的 flag 会演变成技术债，所以在创建它的时候就应设定清理日期。

### 分阶段发布

```
PR merged to main
    │
    ▼
  Staging deployment (auto)
    │ Manual verification
    ▼
  Production deployment (manual trigger or auto after staging)
    │
    ▼
  Monitor for errors (15-minute window)
    │
    ├── Errors detected → Rollback
    └── Clean → Done
```

### 回滚计划

每一次部署都必须可逆：

```yaml
# Manual rollback workflow
name: Rollback
on:
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to rollback to'
        required: true

jobs:
  rollback:
    runs-on: ubuntu-latest
    steps:
      - name: Rollback deployment
        run: |
          # Deploy the specified previous version
          npx vercel rollback ${{ inputs.version }}
```

## 环境管理

```
.env.example       → Committed (template for developers)
.env               → NOT committed (local development)
.env.test          → Committed (test environment, no real secrets)
CI secrets         → Stored in GitHub Secrets / vault
Production secrets → Stored in deployment platform / vault
```

CI 不应该拥有生产 secrets。测试环境和生产环境的凭据必须分开。

## CI 之外的自动化

### Dependabot / Renovate

```yaml
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule:
      interval: weekly
    open-pull-requests-limit: 5
```

### Build Cop 角色

指定一个 Build Cop，专门对“CI 必须保持绿色”负责。构建一旦坏掉，Build Cop 的职责是修复或回滚，而不是默认归咎于最后一个提交的人。这能避免坏构建一直堆积，而大家都以为别人会修。

### PR 检查

- **Required reviews：** 合并前至少 1 个批准
- **Required status checks：** CI 必须通过
- **Branch protection：** 禁止对 `main` 强推
- **Auto-merge：** 所有检查通过且已批准后自动合并

## CI 优化

当流水线耗时超过 10 分钟时，按以下顺序优化：

```
Slow CI pipeline?
├── Cache dependencies
│   └── Use actions/cache or setup-node cache option for node_modules
├── Run jobs in parallel
│   └── Split lint, typecheck, test, build into separate parallel jobs
├── Only run what changed
│   └── Use path filters to skip unrelated jobs (e.g., skip e2e for docs-only PRs)
├── Use matrix builds
│   └── Shard test suites across multiple runners
├── Optimize the test suite
│   └── Remove slow tests from the critical path, run them on a schedule instead
└── Use larger runners
    └── GitHub-hosted larger runners or self-hosted for CPU-heavy builds
```

**示例：缓存与并行**
```yaml
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '22', cache: 'npm' }
      - run: npm ci
      - run: npm run lint

  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '22', cache: 'npm' }
      - run: npm ci
      - run: npx tsc --noEmit

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '22', cache: 'npm' }
      - run: npm ci
      - run: npm test -- --coverage
```

## 常见自我安慰

| 自我安慰 | 现实 |
|---|---|
| “CI 太慢了” | 应该优化流水线，而不是跳过。5 分钟 CI 往往能省掉几小时调试。 |
| “这次改动很小，跳过 CI 吧” | 小改动一样会炸构建。再说，小改动跑 CI 也很快。 |
| “这个测试 flaky，重跑一下就行” | Flaky test 会掩盖真 bug，还会浪费所有人的时间。修掉它。 |
| “CI 以后再补” | 没有 CI 的项目很容易积累一堆损坏状态。第一天就要配。 |
| “人工测试就够了” | 人工测试不可扩展，也不可重复。能自动化的就自动化。 |

## 危险信号

- 项目里没有 CI 流水线
- CI 失败被忽略或被静音
- 为了让流水线变绿而在 CI 里禁用测试
- 生产部署前没有 staging 验证
- 没有回滚机制
- secrets 存在代码或 CI 配置里，而不是 secrets manager
- CI 很慢，但没人尝试优化

## 验证

配置或修改 CI 后，确认：

- [ ] 所有质量门禁都存在，例如 lint、types、tests、build、audit
- [ ] 每个 PR 和每次 push 到 `main` 都会触发流水线
- [ ] 失败会阻止合并，branch protection 已配置
- [ ] CI 结果会真正反馈回开发闭环
- [ ] Secrets 保存在 secrets manager，而不是代码里
- [ ] 部署流程具备回滚机制
- [ ] 测试套件相关流水线在 10 分钟内完成

