ci-cd-and-automation

ci-cd-and-automation

熱門

自動化 CI/CD 管線設定。在設定或修改建置與部署管線時使用。當你需要自動化品質關卡、在 CI 中設定測試執行器,或建立部署策略時使用。

7.8萬星標
8330分支
更新於 2026/7/12
SKILL.md
readonlyread-only
name
ci-cd-and-automation
description

自動化 CI/CD 管線設定。在設定或修改建置與部署管線時使用。當你需要自動化品質關卡、在 CI 中設定測試執行器,或建立部署策略時使用。

CI/CD 與自動化

概述

自動化品質關卡,確保任何變更在未通過測試、lint、型別檢查和建置之前,都不會進入正式環境。CI/CD 是所有其他技能的執行機制——它能捕捉人類和代理遺漏的問題,並且在每次變更時一致地執行。

Shift Left(左移測試): 盡早在管線中發現問題。在 lint 階段發現的錯誤只需幾分鐘;同樣的錯誤在正式環境中發現則需要數小時。將檢查向上游移動——靜態分析在測試之前,測試在暫存環境之前,暫存環境在正式環境之前。

越快越安全: 較小的批次和更頻繁的發布能降低風險,而非增加風險。包含 3 個變更的部署比包含 30 個變更的部署更容易除錯。頻繁發布能建立對發布流程本身的信心。

使用時機

  • 設定新專案的 CI 管線
  • 新增或修改自動化檢查
  • 設定部署管線
  • 當變更應觸發自動化驗證時
  • 除錯 CI 失敗

品質關卡管線

每次變更在合併前都必須通過以下關卡:

Pull Request 開啟
    │
    ▼
┌─────────────────┐
│   LINT 檢查      │  eslint, prettier
│   ↓ 通過         │
│   型別檢查        │  tsc --noEmit
│   ↓ 通過         │
│   單元測試        │  jest/vitest
│   ↓ 通過         │
│   建置            │  npm run build
│   ↓ 通過         │
│   整合測試        │  API/DB 測試
│   ↓ 通過         │
│   E2E(選擇性)   │  Playwright/Cypress
│   ↓ 通過         │
│   安全稽核        │  npm audit
│   ↓ 通過         │
│   套件大小檢查    │  bundlesize check
└─────────────────┘
    │
    ▼
  準備好進行審查

沒有任何關卡可以跳過。 如果 lint 失敗,請修正 lint——不要停用規則。如果測試失敗,請修正程式碼——不要跳過測試。

GitHub Actions 設定

基本 CI 管線

# .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: 安裝依賴
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: 型別檢查
        run: npx tsc --noEmit

      - name: 測試
        run: npm test -- --coverage

      - name: 建置
        run: npm run build

      - name: 安全稽核
        run: npm audit --audit-level=high

含資料庫整合測試

  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: npx prisma migrate deploy
        env:
          DATABASE_URL: postgresql://ci_user:${{ secrets.CI_DB_PASSWORD }}@localhost:5432/testdb
      - name: 整合測試
        run: npm run test:integration
        env:
          DATABASE_URL: postgresql://ci_user:${{ secrets.CI_DB_PASSWORD }}@localhost:5432/testdb

注意: 即使是僅供 CI 使用的測試資料庫,也應使用 GitHub Secrets 來儲存憑證,而非直接寫死在程式碼中。這能養成良好習慣,並防止測試憑證在其他情境中被意外使用。

E2E 測試

  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: 安裝 Playwright
        run: npx playwright install --with-deps chromium
      - name: 建置
        run: npm run build
      - name: 執行 E2E 測試
        run: npx playwright test
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report
          path: playwright-report/

將 CI 失敗回饋給代理

CI 與 AI 代理結合的威力在於回饋迴圈。當 CI 失敗時:

CI 失敗
    │
    ▼
複製失敗輸出
    │
    ▼
提供給代理:
「CI 管線因以下錯誤而失敗:
[貼上具體錯誤]
修正問題並在本地驗證後再推送。」
    │
    ▼
代理修正 → 推送 → CI 再次執行

關鍵模式:

Lint 失敗 → 代理執行 `npm run lint --fix` 並提交
型別錯誤 → 代理讀取錯誤位置並修正型別
測試失敗 → 代理遵循除錯與錯誤復原技能
建置錯誤 → 代理檢查設定與依賴

部署策略

預覽部署

每個 PR 都會獲得一個預覽部署以供手動測試:

# 在 PR 上部署預覽(Vercel/Netlify 等)
deploy-preview:
  runs-on: ubuntu-latest
  if: github.event_name == 'pull_request'
  steps:
    - uses: actions/checkout@v4
    - name: 部署預覽
      run: npx vercel --token=${{ secrets.VERCEL_TOKEN }}

功能開關

功能開關將部署與發布脫鉤。將未完成或有風險的功能部署在開關之後,以便:

  • 在不啟用功能的情況下發布程式碼。 及早合併到 main,準備好時再啟用。
  • 無需重新部署即可回滾。 停用開關,而非還原程式碼。
  • 金絲雀發布新功能。 先對 1% 的使用者啟用,然後 10%,最後 100%。
  • 執行 A/B 測試。 比較啟用與未啟用功能時的行為。
// 簡單的功能開關模式
if (featureFlags.isEnabled('new-checkout-flow', { userId })) {
  return renderNewCheckout();
}
return renderLegacyCheckout();

開關生命週期: 建立 → 啟用測試 → 金絲雀發布 → 全面上線 → 移除開關與死程式碼。永遠存在的開關會變成技術債——建立時就設定清理日期。

分階段發布

PR 合併到 main
    │
    ▼
  暫存環境部署(自動)
    │ 手動驗證
    ▼
  正式環境部署(手動觸發或暫存環境驗證後自動)
    │
    ▼
  監控錯誤(15 分鐘視窗)
    │
    ├── 偵測到錯誤 → 回滾
    └── 無錯誤 → 完成

回滾計畫

每次部署都應可逆:

# 手動回滾工作流程
name: Rollback
on:
  workflow_dispatch:
    inputs:
      version:
        description: '要回滾到的版本'
        required: true

jobs:
  rollback:
    runs-on: ubuntu-latest
    steps:
      - name: 回滾部署
        run: |
          # 部署指定的先前版本
          npx vercel rollback ${{ inputs.version }}

環境管理

.env.example       → 提交(開發者範本)
.env                → 不提交(本地開發)
.env.test           → 提交(測試環境,不含真實機密)
CI 機密            → 儲存在 GitHub Secrets / vault
正式環境機密        → 儲存在部署平台 / vault

CI 絕不應擁有正式環境機密。使用獨立的機密進行 CI 測試。

超越 CI 的自動化

Dependabot / Renovate

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

Build Cop 角色

指定某人負責保持 CI 綠色。當建置中斷時,Build Cop 的職責是修復或還原——而不是造成中斷的人。這可以防止建置中斷持續累積,而每個人都認為別人會去修復。

PR 檢查

  • 必要審查: 合併前至少 1 個核准
  • 必要狀態檢查: CI 必須通過才能合併
  • 分支保護: 禁止強制推送至 main
  • 自動合併: 如果所有檢查通過且已核准,自動合併

CI 最佳化

當管線超過 10 分鐘時,依影響程度依序套用以下策略:

CI 管線太慢?
├── 快取依賴
│   └── 使用 actions/cache 或 setup-node 的快取選項來快取 node_modules
├── 平行執行工作
│   └── 將 lint、型別檢查、測試、建置拆分為獨立的平行工作
├── 只執行有變更的部分
│   └── 使用路徑過濾器跳過不相關的工作(例如,僅文件變更的 PR 跳過 e2e)
├── 使用矩陣建置
│   └── 將測試套件分散到多個執行器
├── 最佳化測試套件
│   └── 將慢速測試移出關鍵路徑,改為排程執行
└── 使用更大的執行器
    └── GitHub 託管的更大執行器或自託管執行器,適用於 CPU 密集型建置

範例:快取與平行化

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 太慢了」 最佳化管線(見下方 CI 最佳化),不要跳過。5 分鐘的管線能避免數小時的除錯。
「這個變更很簡單,跳過 CI」 簡單的變更也會破壞建置。而且對簡單變更來說,CI 很快。
「測試不穩定,重新執行就好」 不穩定的測試會掩蓋真正的錯誤,並浪費大家的時間。請修正不穩定性。
「我們之後再加 CI」 沒有 CI 的專案會累積損壞狀態。請在第一天就設定好。
「手動測試就夠了」 手動測試無法擴展,也不可重複。請盡可能自動化。

紅旗

  • 專案中沒有 CI 管線
  • CI 失敗被忽略或靜默處理
  • 為了讓管線通過而在 CI 中停用測試
  • 未經暫存環境驗證就部署到正式環境
  • 沒有回滾機制
  • 機密儲存在程式碼或 CI 設定檔中(而非機密管理工具)
  • CI 時間過長且未嘗試最佳化

驗證

設定或修改 CI 後:

  • [ ] 所有品質關卡都已存在(lint、型別、測試、建置、稽核)
  • [ ] 管線在每個 PR 和推送至 main 時執行
  • [ ] 失敗會阻止合併(已設定分支保護)
  • [ ] CI 結果回饋到開發循環中
  • [ ] 機密儲存在機密管理工具中,而非程式碼中
  • [ ] 部署具有回滾機制
  • [ ] 管線在 10 分鐘內執行完測試套件