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

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

Choyeon
Choyeon
2026年9月26日 1 分钟阅读 360 阅读
890 字 3,868 字符 更新于 2026年11月8日
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 分钟阅读