提示:本网站现在为维护调试状态

CI/CD Pipeline 設計:GitHub Actions + Cache + Matrix Build

Choyeon
Choyeon
2026年9月26日 1 分鐘閱讀 353 閱讀
890 字 3,868 字元 更新於 2026年11月8日
CI/CD Pipeline 設計:GitHub Actions + Cache + Matrix Build
目錄

CI/CD Pipeline 设计:GitHub Actions + Cache + Matrix Build

CI/CD 是研发效率的脊梁。设计差的流水线 PR 等 40 分钟、随机失败、无法复用;设计好的流水线 5 分钟内给出可信反馈,并发矩阵覆盖多版本多 OS,缓存命中让重复构建秒过。

阶段拆分与路径过滤

经典 5 阶段:(1) changes 路径过滤:未改动的子项目整段跳过(PR 只改文档不跑后端测试);(2) lint 阶段快失败优先(8 分钟内出结果);(3) test 多版本矩阵并发;(4) build 构建产物;(5) 打 tag 才执行 publish 推送镜像/发布包。concurrency 同 ref 自动取消旧运行,节省 Action 分钟。

.github/workflows/ci.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main, develop]
    tags: ['v*.*.*']
  pull_request:
    branches: [main, develop]

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      backend: ${{ steps.filter.outputs.backend }}
      frontend: ${{ steps.filter.outputs.frontend }}
      infra: ${{ steps.filter.outputs.infra }}
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            backend:
              - 'apps/api/**'
              - 'packages/shared/**'
              - 'pyproject.toml'
            frontend:
              - 'apps/web/**'
              - 'packages/ui/**'
              - 'pnpm-lock.yaml'
            infra:
              - 'infra/**'
              - 'Dockerfile*'

  lint:
    needs: changes
    if: needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true'
    runs-on: ubuntu-latest
    timeout-minutes: 8
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
        with: { version: 9 }
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: pnpm
          cache-dependency-path: pnpm-lock.yaml
      - name: Install Node deps
        run: pnpm install --frozen-lockfile --prefer-offline
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
          cache: pip
          cache-dependency-path: pyproject.toml
      - name: Install Python deps
        run: pip install -e ".[dev]" --retries 3
      - name: Run ESLint + Ruff
        run: |
          pnpm lint
          ruff check apps/api packages
      - name: Cache turbo setup
        uses: actions/cache@v4
        with:
          path: .turbo
          key: turbo-${{ github.sha }}
          restore-keys: turbo-

  test:
    needs: lint
    runs-on: ubuntu-latest
    timeout-minutes: 20
    strategy:
      fail-fast: false
      matrix:
        python-version: ['3.11', '3.12', '3.13']
        node-version: ['18', '20', '22']
        os: [ubuntu-latest]
        include:
          - os: macos-latest
            python-version: '3.12'
            node-version: '20'
    services:
      postgres:
        image: postgres:16-alpine
        env: { POSTGRES_USER: test, POSTGRES_PASSWORD: test, POSTGRES_DB: test }
        ports: ['5432:5432']
        options: >-
          --health-cmd pg_isready
          --health-interval 10s --health-timeout 5s --health-retries 5
      redis:
        image: redis:7-alpine
        ports: ['6379:6379']
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4; with: { version: 9 }
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: pnpm
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
          cache: pip
      - run: pnpm install --frozen-lockfile
      - run: pip install -e ".[test]"
      - name: Run tests with coverage
        run: |
          pnpm test -- --coverage --reporter=github
          pytest apps/api --cov=apps/api --cov-report=xml
        env:
          DATABASE_URL: postgresql://test:test@localhost:5432/test
          REDIS_URL: redis://localhost:6379
      - uses: codecov/codecov-action@v4
        if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20' && matrix.python-version == '3.12'
        with: { fail_ci_if_error: false, token: ${{ secrets.CODECOV_TOKEN }} }

  build-and-push-image:
    needs: test
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha,prefix=
      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          platforms: linux/amd64,linux/arm64
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

缓存矩阵构建加速三剑客

(1) 依赖缓存:setup-node + pnpm cache、pip cache 让 90% 构建免装依赖;(2) 任务产物缓存:turbo cache 跨工作流复用构建结果;(3) Docker 层缓存:buildx gha cache 复用层,推送时间从 5 分钟缩到 40 秒。Matrix 跨 OS/版本覆盖 Python 3.11-3.13 × Node 18-22,矩阵 include 注入 MacOS 单测确保 Unix 类兼容性。

优化项 未优化耗时 优化后耗时 节省比例
npm/pip 依赖安装 3min 20s (95%命中) 89%
Turborepo 构建 6min 15s (全命中) 96%
Docker 镜像推送 5min 40s 87%
Matrix 顺序执行 30min 6min (5并发) 80%
路径过滤跳过 20min/每次PR 3min 85%

最佳实践

timeout-minutes 每个 Job 强制上限防挂死;services 用 Postgres/Redis 健康检查等待就绪后再跑;fail-fast:false 保证所有组合跑完不提前中断;最终 semver tag 触发发布流程,main 分支仅 build+test 止。

X微博Telegram

本文作者

投票

你最希望 Rosetta 优先加入哪项功能?

社区投票(演示数据,可后台删除)

留言 (4)

0 / 3000
算法小菜鸟
算法小菜鸟2026年9月7日

建议可以再加一下关于成本优化的部分,云上资源如果不注意优化的话,账单真的会吓死个人。

DBA界的卷王
DBA界的卷王2026年9月7日

博主太懂运维的痛了!那个日志系统选型的部分我太有共鸣了,之前选型踩的坑和你说的一模一样。

奶茶味程序媛
奶茶味程序媛2026年9月7日

哈哈,备份不验证等于没备份那段我笑了,我之前就是吃了这个大亏,数据库备份了半年才发现根本恢复不了。

全栈打工人
全栈打工人2026年9月7日

想请教一下:生产环境的 etcd 集群一般推荐几个节点?3 个和 5 个在性能和可用性上该怎么权衡?

相關文章

Monorepo 工具鏈:Turborepo + pnpm workspace

Monorepo 工具鏈:Turborepo + pnpm workspace

單倉多包(Monorepo)管理大型前端全棧項目的完全指南:用 pnpm workspace 做依賴統一安裝和鏈接,Turborepo 做任務編排、增量構建和遠程緩存,對比 Nx/Lerna,附帶代碼複用與版本發佈最佳實踐。

1 分鐘閱讀
Git 高級工作流

Git 高級工作流

全面掌握 Git 進階操作:Interactive Rebase 整理提交歷史、Cherry-pick 精挑細選移植提交、Bisect 二分查找回歸 Bug 源頭,配合 reflog 與 reset 拯救誤操作。

1 分鐘閱讀
Docker Compose 生產部署實戰

Docker Compose 生產部署實戰

本文深入講解 Docker Compose 在生產環境中的最佳實踐,覆蓋多階段構建、健康檢查、資源限制、日誌配置、網絡隔離、密鑰管理等核心話題,助你構建穩定可擴展的容器化部署方案。

1 分鐘閱讀
Alembic 深度指南:數據庫遷移 + 自動生成 + 分支合併

Alembic 深度指南:數據庫遷移 + 自動生成 + 分支合併

SQLAlchemy 官方遷移工具 Alembic 完全指南:從 env.py 配置、autogenerate 自動檢測模型變更(字段、索引、約束)、批處理腳本、downgrade 回滾策略,到多人併發開發時 migration 分支衝突、head 分叉合併的標準操作流程,附生產部署檢查表。

1 分鐘閱讀
測試金字塔:單元/整合/E2E 測試比例與落地

測試金字塔:單元/整合/E2E 測試比例與落地

系統解析測試金字塔架構:從底層單元測試(大量快速、Mock 隔離依賴)、中層整合測試(服務/數據庫/消息協作真實交互)、頂層 E2E 測試(真實用戶路徑少量精測)的推薦比例 70% / 20% / 10%,附項目覆蓋率指標與落地實踐。

1 分鐘閱讀
JWT 認證安全最佳實踐 + OAuth2 vs SAML

JWT 認證安全最佳實踐 + OAuth2 vs SAML

系統性歸納 JWT 常見安全漏洞防護:算法混淆攻擊(none/RS256→HS256)、密鑰爆破、KID注入、重放攻擊防禦,再從多個維度對比 OAuth2(授權碼+PKCE)、OIDC、SAML 2.0 三種主流認證協議選型。

1 分鐘閱讀