ci-cd-pipeline-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

CI/CD Pipeline Patterns

CI/CD流水线模式

A comprehensive skill for designing, implementing, and optimizing CI/CD pipelines using GitHub Actions and modern DevOps practices. Master workflow automation, testing strategies, deployment patterns, and release management for continuous software delivery.
这是一项利用GitHub Actions和现代DevOps实践来设计、实现和优化CI/CD流水线的全面技能。掌握工作流自动化、测试策略、部署模式以及持续软件交付的发布管理。

When to Use This Skill

何时使用此技能

Use this skill when:
  • Setting up continuous integration and deployment pipelines for projects
  • Automating build, test, and deployment workflows
  • Implementing multi-environment deployment strategies (staging, production)
  • Managing release automation and versioning
  • Configuring matrix builds for multi-platform testing
  • Securing CI/CD pipelines with secrets and OIDC
  • Optimizing pipeline performance with caching and parallelization
  • Building containerized applications with Docker in CI
  • Deploying to cloud platforms (AWS, Azure, GCP, Vercel, Netlify)
  • Implementing infrastructure as code with Terraform/CloudFormation
  • Setting up monorepo CI/CD patterns
  • Creating reusable workflow templates and custom actions
  • Implementing deployment strategies (blue-green, canary, rolling)
  • Automating changelog generation and semantic versioning
  • Integrating quality gates and code coverage checks
在以下场景使用此技能:
  • 为项目搭建持续集成与部署流水线
  • 自动化构建、测试和部署工作流
  • 实现多环境部署策略(预发布、生产)
  • 管理发布自动化与版本控制
  • 配置矩阵构建以实现多平台测试
  • 使用密钥和OIDC保障CI/CD流水线安全
  • 通过缓存和并行化优化流水线性能
  • 在CI中使用Docker构建容器化应用
  • 部署至云平台(AWS、Azure、GCP、Vercel、Netlify)
  • 使用Terraform/CloudFormation实现基础设施即代码
  • 搭建单体仓库(Monorepo)CI/CD模式
  • 创建可复用工作流模板和自定义Actions
  • 实现部署策略(蓝绿部署、金丝雀部署、滚动部署)
  • 自动化生成变更日志与语义化版本控制
  • 集成质量门禁与代码覆盖率检查

Core Concepts

核心概念

CI/CD Fundamentals

CI/CD基础

Continuous Integration (CI): Automatically building and testing code changes as developers commit to the repository.
Continuous Deployment (CD): Automatically deploying code changes to production after passing tests.
Continuous Delivery: Keeping code in a deployable state, with manual approval for production deployment.
持续集成(CI):开发者提交代码变更时,自动构建并测试代码。
持续部署(CD):代码通过测试后,自动部署至生产环境。
持续交付:保持代码处于可部署状态,生产环境部署需手动批准。

GitHub Actions Architecture

GitHub Actions架构

GitHub Actions provides event-driven automation directly integrated with your repository.
GitHub Actions提供与仓库直接集成的事件驱动自动化能力。

Workflows

工作流

YAML files in
.github/workflows/
that define automated processes:
yaml
name: CI Pipeline
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build project
        run: npm run build
Key Components:
  • name: Human-readable workflow name
  • on: Events that trigger the workflow (push, pull_request, schedule, workflow_dispatch)
  • jobs: Collection of steps that run in sequence or parallel
  • runs-on: The runner environment (ubuntu-latest, windows-latest, macos-latest)
位于
.github/workflows/
目录下的YAML文件,用于定义自动化流程:
yaml
name: CI Pipeline
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build project
        run: npm run build
核心组件:
  • name:易读的工作流名称
  • on:触发工作流的事件(push、pull_request、schedule、workflow_dispatch)
  • jobs:按顺序或并行运行的步骤集合
  • runs-on:运行环境(ubuntu-latest、windows-latest、macos-latest)

Jobs

任务(Jobs)

Groups of steps executed on the same runner:
yaml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test

  deploy:
    needs: test  # Runs after 'test' job completes
    runs-on: ubuntu-latest
    steps:
      - run: npm run deploy
Job Features:
  • needs: Define job dependencies (sequential execution)
  • if: Conditional execution based on expressions
  • strategy: Matrix builds for multiple configurations
  • outputs: Share data between jobs
  • environment: Deployment environments with protection rules
在同一运行器上执行的步骤组:
yaml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test

  deploy:
    needs: test  # 在'test'任务完成后运行
    runs-on: ubuntu-latest
    steps:
      - run: npm run deploy
任务特性:
  • needs:定义任务依赖(顺序执行)
  • if:基于表达式的条件执行
  • strategy:用于多配置的矩阵构建
  • outputs:在任务间共享数据
  • environment:带有保护规则的部署环境

Steps

步骤(Steps)

Individual tasks within a job:
yaml
steps:
  - name: Checkout code
    uses: actions/checkout@v4

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '20'

  - name: Install dependencies
    run: npm ci

  - name: Run tests
    run: npm test
Step Types:
  • uses: Run a pre-built action from marketplace or repository
  • run: Execute shell commands
  • with: Provide inputs to actions
  • env: Set environment variables for the step
任务中的单个操作:
yaml
steps:
  - name: Checkout code
    uses: actions/checkout@v4

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '20'

  - name: Install dependencies
    run: npm ci

  - name: Run tests
    run: npm test
步骤类型:
  • uses:运行来自市场或仓库的预构建Action
  • run:执行Shell命令
  • with:为Action提供输入参数
  • env:为步骤设置环境变量

Actions

Actions

Reusable units of code that perform specific tasks:
Official Actions:
  • actions/checkout@v4
    : Check out repository code
  • actions/setup-node@v4
    : Setup Node.js environment
  • actions/cache@v4
    : Cache dependencies
  • actions/upload-artifact@v4
    : Upload build artifacts
  • actions/download-artifact@v4
    : Download artifacts from previous jobs
Marketplace Actions:
  • docker/build-push-action@v5
    : Build and push Docker images
  • aws-actions/configure-aws-credentials@v4
    : Configure AWS credentials
  • codecov/codecov-action@v4
    : Upload code coverage
  • google-github-actions/auth@v2
    : Authenticate with Google Cloud
执行特定任务的可复用代码单元:
官方Actions:
  • actions/checkout@v4
    :拉取仓库代码
  • actions/setup-node@v4
    :配置Node.js环境
  • actions/cache@v4
    :缓存依赖
  • actions/upload-artifact@v4
    :上传构建产物
  • actions/download-artifact@v4
    :下载来自之前任务的产物
市场Actions:
  • docker/build-push-action@v5
    :构建并推送Docker镜像
  • aws-actions/configure-aws-credentials@v4
    :配置AWS凭证
  • codecov/codecov-action@v4
    :上传代码覆盖率
  • google-github-actions/auth@v2
    :认证Google Cloud

Secrets and Variables

密钥与变量

Secrets: Encrypted sensitive data (API keys, credentials, tokens)
yaml
steps:
  - name: Deploy to production
    env:
      API_KEY: ${{ secrets.API_KEY }}
      DATABASE_URL: ${{ secrets.DATABASE_URL }}
    run: npm run deploy
Variables: Non-sensitive configuration data
yaml
env:
  NODE_ENV: ${{ vars.NODE_ENV }}
  API_ENDPOINT: ${{ vars.API_ENDPOINT }}
Secret Types:
  • Repository secrets: Available to all workflows in a repository
  • Environment secrets: Scoped to specific environments (production, staging)
  • Organization secrets: Shared across repositories in an organization
密钥(Secrets):加密的敏感数据(API密钥、凭证、令牌)
yaml
steps:
  - name: Deploy to production
    env:
      API_KEY: ${{ secrets.API_KEY }}
      DATABASE_URL: ${{ secrets.DATABASE_URL }}
    run: npm run deploy
变量(Variables):非敏感配置数据
yaml
env:
  NODE_ENV: ${{ vars.NODE_ENV }}
  API_ENDPOINT: ${{ vars.API_ENDPOINT }}
密钥类型:
  • 仓库密钥:对仓库中所有工作流可用
  • 环境密钥:限定于特定环境(生产、预发布)
  • 组织密钥:在组织内的仓库间共享

Artifacts

构建产物(Artifacts)

Files produced by workflows that can be downloaded or used by other jobs:
yaml
- name: Upload build artifacts
  uses: actions/upload-artifact@v4
  with:
    name: dist-files
    path: dist/
    retention-days: 7

- name: Download artifacts
  uses: actions/download-artifact@v4
  with:
    name: dist-files
    path: ./dist
工作流生成的可下载或供其他任务使用的文件:
yaml
- name: Upload build artifacts
  uses: actions/upload-artifact@v4
  with:
    name: dist-files
    path: dist/
    retention-days: 7

- name: Download artifacts
  uses: actions/download-artifact@v4
  with:
    name: dist-files
    path: ./dist

Workflow Triggers

工作流触发器

Event Triggers

事件触发器

Push Events:
yaml
on:
  push:
    branches:
      - main
      - develop
      - 'release/**'
    paths:
      - 'src/**'
      - 'package.json'
    tags:
      - 'v*'
Pull Request Events:
yaml
on:
  pull_request:
    types: [opened, synchronize, reopened]
    branches:
      - main
    paths-ignore:
      - 'docs/**'
      - '**.md'
Schedule (Cron):
yaml
on:
  schedule:
    - cron: '0 0 * * *'  # Daily at midnight UTC
    - cron: '0 */6 * * *'  # Every 6 hours
Manual Triggers (workflow_dispatch):
yaml
on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment to deploy to'
        required: true
        type: choice
        options:
          - staging
          - production
      version:
        description: 'Version to deploy'
        required: true
        type: string
Release Events:
yaml
on:
  release:
    types: [published, created, released]
Workflow Call (Reusable Workflows):
yaml
on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string
    secrets:
      api-key:
        required: true
推送事件:
yaml
on:
  push:
    branches:
      - main
      - develop
      - 'release/**'
    paths:
      - 'src/**'
      - 'package.json'
    tags:
      - 'v*'
拉取请求事件:
yaml
on:
  pull_request:
    types: [opened, synchronize, reopened]
    branches:
      - main
    paths-ignore:
      - 'docs/**'
      - '**.md'
定时触发器(Cron):
yaml
on:
  schedule:
    - cron: '0 0 * * *'  # 每天UTC时间午夜执行
    - cron: '0 */6 * * *'  # 每6小时执行一次
手动触发器(workflow_dispatch):
yaml
on:
  workflow_dispatch:
    inputs:
      environment:
        description: '要部署的环境'
        required: true
        type: choice
        options:
          - staging
          - production
      version:
        description: '要部署的版本'
        required: true
        type: string
发布事件:
yaml
on:
  release:
    types: [published, created, released]
工作流调用(可复用工作流):
yaml
on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string
    secrets:
      api-key:
        required: true

Matrix Builds

矩阵构建

Run jobs across multiple configurations in parallel:
yaml
jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [18, 20, 22]
        include:
          - os: ubuntu-latest
            node-version: 20
            coverage: true
        exclude:
          - os: macos-latest
            node-version: 18
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm test
      - if: matrix.coverage
        run: npm run coverage
Matrix Features:
  • Parallel execution: All combinations run simultaneously
  • include: Add specific configurations
  • exclude: Remove specific combinations
  • fail-fast: Stop all jobs if one fails (default: true)
  • max-parallel: Limit concurrent jobs
并行运行多配置任务:
yaml
jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [18, 20, 22]
        include:
          - os: ubuntu-latest
            node-version: 20
            coverage: true
        exclude:
          - os: macos-latest
            node-version: 18
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm test
      - if: matrix.coverage
        run: npm run coverage
矩阵特性:
  • 并行执行:所有组合同时运行
  • include:添加特定配置
  • exclude:移除特定组合
  • fail-fast:若一个任务失败则停止所有任务(默认:开启)
  • max-parallel:限制并发任务数

Caching Strategies

缓存策略

Speed up workflows by caching dependencies:
Node.js Caching:
yaml
- uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'  # Automatically caches npm dependencies
Custom Caching:
yaml
- uses: actions/cache@v4
  with:
    path: |
      ~/.npm
      ~/.cache
      node_modules
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-
Docker Layer Caching:
yaml
- uses: docker/build-push-action@v5
  with:
    context: .
    cache-from: type=gha
    cache-to: type=gha,mode=max
通过缓存依赖加速工作流:
Node.js缓存:
yaml
- uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'  # 自动缓存npm依赖
自定义缓存:
yaml
- uses: actions/cache@v4
  with:
    path: |
      ~/.npm
      ~/.cache
      node_modules
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-
Docker层缓存:
yaml
- uses: docker/build-push-action@v5
  with:
    context: .
    cache-from: type=gha
    cache-to: type=gha,mode=max

Testing Strategies in CI

CI中的测试策略

Unit Testing

单元测试

Fast, isolated tests for individual components:
yaml
jobs:
  unit-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run unit tests
        run: npm run test:unit -- --coverage

      - name: Upload coverage
        uses: codecov/codecov-action@v4
        with:
          files: ./coverage/coverage-final.json
          flags: unit-tests
          token: ${{ secrets.CODECOV_TOKEN }}
针对单个组件的快速、隔离测试:
yaml
jobs:
  unit-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run unit tests
        run: npm run test:unit -- --coverage

      - name: Upload coverage
        uses: codecov/codecov-action@v4
        with:
          files: ./coverage/coverage-final.json
          flags: unit-tests
          token: ${{ secrets.CODECOV_TOKEN }}

Integration Testing

集成测试

Test interactions between components and services:
yaml
jobs:
  integration-tests:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432

      redis:
        image: redis:7
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 6379:6379

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run database migrations
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
        run: npm run migrate

      - name: Run integration tests
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
          REDIS_URL: redis://localhost:6379
        run: npm run test:integration
测试组件与服务间的交互:
yaml
jobs:
  integration-tests:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432

      redis:
        image: redis:7
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 6379:6379

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run database migrations
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
        run: npm run migrate

      - name: Run integration tests
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
          REDIS_URL: redis://localhost:6379
        run: npm run test:integration

End-to-End Testing

端到端测试

Test complete user workflows:
yaml
jobs:
  e2e-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Build application
        run: npm run build

      - name: Install Playwright browsers
        run: npx playwright install --with-deps

      - name: Run E2E tests
        run: npm run test:e2e

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30
测试完整用户工作流:
yaml
jobs:
  e2e-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Build application
        run: npm run build

      - name: Install Playwright browsers
        run: npx playwright install --with-deps

      - name: Run E2E tests
        run: npm run test:e2e

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30

Performance Testing

性能测试

Benchmark and performance regression testing:
yaml
jobs:
  performance-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Build for production
        run: npm run build

      - name: Run Lighthouse CI
        uses: treosh/lighthouse-ci-action@v11
        with:
          urls: |
            http://localhost:3000
            http://localhost:3000/dashboard
          uploadArtifacts: true
          temporaryPublicStorage: true

      - name: Run load tests
        run: npm run test:load
基准测试与性能回归测试:
yaml
jobs:
  performance-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Build for production
        run: npm run build

      - name: Run Lighthouse CI
        uses: treosh/lighthouse-ci-action@v11
        with:
          urls: |
            http://localhost:3000
            http://localhost:3000/dashboard
          uploadArtifacts: true
          temporaryPublicStorage: true

      - name: Run load tests
        run: npm run test:load

Code Quality and Linting

代码质量与代码检查

Enforce code standards and quality gates:
yaml
jobs:
  code-quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run ESLint
        run: npm run lint

      - name: Run Prettier check
        run: npm run format:check

      - name: Run TypeScript check
        run: npm run type-check

      - name: Run security audit
        run: npm audit --audit-level=moderate

      - name: SonarCloud Scan
        uses: SonarSource/sonarcloud-github-action@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
强制执行代码标准与质量门禁:
yaml
jobs:
  code-quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run ESLint
        run: npm run lint

      - name: Run Prettier check
        run: npm run format:check

      - name: Run TypeScript check
        run: npm run type-check

      - name: Run security audit
        run: npm audit --audit-level=moderate

      - name: SonarCloud Scan
        uses: SonarSource/sonarcloud-github-action@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

Deployment Patterns

部署模式

Blue-Green Deployment

蓝绿部署

Zero-downtime deployment by maintaining two identical environments:
yaml
jobs:
  deploy-blue-green:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Green environment
        run: |
          # Deploy new version to green environment
          ./deploy.sh green

      - name: Run smoke tests on Green
        run: |
          # Verify green environment is healthy
          curl -f https://green.example.com/health

      - name: Switch traffic to Green
        run: |
          # Update load balancer to point to green
          aws elbv2 modify-rule --rule-arn $RULE_ARN \
            --actions Type=forward,TargetGroupArn=$GREEN_TG

      - name: Monitor Green environment
        run: |
          # Monitor for 5 minutes
          ./monitor.sh green 300

      - name: Rollback if needed
        if: failure()
        run: |
          # Switch back to blue
          aws elbv2 modify-rule --rule-arn $RULE_ARN \
            --actions Type=forward,TargetGroupArn=$BLUE_TG
通过维护两个相同环境实现零停机部署:
yaml
jobs:
  deploy-blue-green:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Green environment
        run: |
          # Deploy new version to green environment
          ./deploy.sh green

      - name: Run smoke tests on Green
        run: |
          # Verify green environment is healthy
          curl -f https://green.example.com/health

      - name: Switch traffic to Green
        run: |
          # Update load balancer to point to green
          aws elbv2 modify-rule --rule-arn $RULE_ARN \
            --actions Type=forward,TargetGroupArn=$GREEN_TG

      - name: Monitor Green environment
        run: |
          # Monitor for 5 minutes
          ./monitor.sh green 300

      - name: Rollback if needed
        if: failure()
        run: |
          # Switch back to blue
          aws elbv2 modify-rule --rule-arn $RULE_ARN \
            --actions Type=forward,TargetGroupArn=$BLUE_TG

Canary Deployment

金丝雀部署

Gradual rollout to a subset of users:
yaml
jobs:
  canary-deployment:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy canary (10% traffic)
        run: |
          kubectl set image deployment/app app=myapp:${{ github.sha }}
          kubectl scale deployment/app-canary --replicas=1
          kubectl annotate service app-service \
            traffic-split='{"canary": 10, "stable": 90}'

      - name: Monitor canary metrics
        run: |
          # Monitor error rates, latency for 15 minutes
          ./monitor-canary.sh 900

      - name: Increase canary traffic (50%)
        run: |
          kubectl annotate service app-service \
            traffic-split='{"canary": 50, "stable": 50}' --overwrite

      - name: Monitor again
        run: ./monitor-canary.sh 600

      - name: Full rollout (100%)
        run: |
          kubectl set image deployment/app-stable app=myapp:${{ github.sha }}
          kubectl scale deployment/app-canary --replicas=0

      - name: Rollback canary
        if: failure()
        run: |
          kubectl scale deployment/app-canary --replicas=0
向部分用户逐步推出新版本:
yaml
jobs:
  canary-deployment:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy canary (10% traffic)
        run: |
          kubectl set image deployment/app app=myapp:${{ github.sha }}
          kubectl scale deployment/app-canary --replicas=1
          kubectl annotate service app-service \
            traffic-split='{"canary": 10, "stable": 90}'

      - name: Monitor canary metrics
        run: |
          # Monitor error rates, latency for 15 minutes
          ./monitor-canary.sh 900

      - name: Increase canary traffic (50%)
        run: |
          kubectl annotate service app-service \
            traffic-split='{"canary": 50, "stable": 50}' --overwrite

      - name: Monitor again
        run: ./monitor-canary.sh 600

      - name: Full rollout (100%)
        run: |
          kubectl set image deployment/app-stable app=myapp:${{ github.sha }}
          kubectl scale deployment/app-canary --replicas=0

      - name: Rollback canary
        if: failure()
        run: |
          kubectl scale deployment/app-canary --replicas=0

Rolling Deployment

滚动部署

Sequential update of instances:
yaml
jobs:
  rolling-deployment:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy with rolling update
        run: |
          kubectl set image deployment/app \
            app=myapp:${{ github.sha }} \
            --record

      - name: Wait for rollout to complete
        run: |
          kubectl rollout status deployment/app --timeout=10m

      - name: Verify deployment
        run: |
          kubectl get pods -l app=myapp
          curl -f https://api.example.com/health

      - name: Rollback on failure
        if: failure()
        run: |
          kubectl rollout undo deployment/app
按顺序更新实例:
yaml
jobs:
  rolling-deployment:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy with rolling update
        run: |
          kubectl set image deployment/app \
            app=myapp:${{ github.sha }} \
            --record

      - name: Wait for rollout to complete
        run: |
          kubectl rollout status deployment/app --timeout=10m

      - name: Verify deployment
        run: |
          kubectl get pods -l app=myapp
          curl -f https://api.example.com/health

      - name: Rollback on failure
        if: failure()
        run: |
          kubectl rollout undo deployment/app

Multi-Environment Deployment

多环境部署

Deploy to staging, then production with approvals:
yaml
jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment:
      name: staging
      url: https://staging.example.com
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to staging
        run: ./deploy.sh staging

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://example.com
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to production
        run: ./deploy.sh production
先部署至预发布环境,再手动批准后部署至生产环境:
yaml
jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment:
      name: staging
      url: https://staging.example.com
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to staging
        run: ./deploy.sh staging

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://example.com
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to production
        run: ./deploy.sh production

Security Best Practices

安全最佳实践

Secret Management

密钥管理

Using GitHub Secrets:
yaml
steps:
  - name: Configure AWS credentials
    uses: aws-actions/configure-aws-credentials@v4
    with:
      aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
      aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      aws-region: us-east-1
Environment-Scoped Secrets:
yaml
jobs:
  deploy:
    environment: production  # Uses production-scoped secrets
    steps:
      - name: Deploy
        env:
          API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
        run: ./deploy.sh
使用GitHub Secrets:
yaml
steps:
  - name: Configure AWS credentials
    uses: aws-actions/configure-aws-credentials@v4
    with:
      aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
      aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      aws-region: us-east-1
环境限定密钥:
yaml
jobs:
  deploy:
    environment: production  # 使用生产环境限定的密钥
    steps:
      - name: Deploy
        env:
          API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
        run: ./deploy.sh

OIDC (OpenID Connect)

OIDC(开放ID连接)

Authenticate without long-lived credentials:
yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials (OIDC)
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
          aws-region: us-east-1

      - name: Deploy to AWS
        run: aws s3 sync ./dist s3://my-bucket
Google Cloud OIDC:
yaml
- name: Authenticate to Google Cloud
  uses: google-github-actions/auth@v2
  with:
    workload_identity_provider: 'projects/123/locations/global/workloadIdentityPools/pool/providers/provider'
    service_account: 'github-actions@project.iam.gserviceaccount.com'
无需长期凭证即可完成认证:
yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials (OIDC)
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
          aws-region: us-east-1

      - name: Deploy to AWS
        run: aws s3 sync ./dist s3://my-bucket
Google Cloud OIDC:
yaml
- name: Authenticate to Google Cloud
  uses: google-github-actions/auth@v2
  with:
    workload_identity_provider: 'projects/123/locations/global/workloadIdentityPools/pool/providers/provider'
    service_account: 'github-actions@project.iam.gserviceaccount.com'

Secure Workflows

安全工作流

Restrict permissions:
yaml
permissions:
  contents: read      # Read repository contents
  pull-requests: write # Comment on PRs
  id-token: write     # OIDC token generation
  actions: read       # Read workflow runs
Pin action versions to SHA:
yaml
undefined
限制权限:
yaml
permissions:
  contents: read      # 读取仓库内容
  pull-requests: write # 对PR添加评论
  id-token: write     # 生成OIDC令牌
  actions: read       # 读取工作流运行状态
将Action版本固定为SHA:
yaml
undefined

Less secure (tag can be moved)

安全性较低(标签可被移动)

  • uses: actions/checkout@v4
  • uses: actions/checkout@v4

More secure (immutable SHA)

安全性更高(不可变SHA)

  • uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

**Prevent script injection:**
```yaml
  • uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

**防止脚本注入:**
```yaml

Vulnerable to injection

易受注入攻击

  • run: echo "Hello ${{ github.event.issue.title }}"
  • run: echo "Hello ${{ github.event.issue.title }}"

Safe approach

安全做法

  • run: echo "Hello $TITLE" env: TITLE: ${{ github.event.issue.title }}
undefined
  • run: echo "Hello $TITLE" env: TITLE: ${{ github.event.issue.title }}
undefined

Docker in CI/CD

CI/CD中的Docker

Building Docker Images

构建Docker镜像

yaml
jobs:
  build-docker:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: myorg/myapp
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha,prefix={{branch}}-

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
yaml
jobs:
  build-docker:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: myorg/myapp
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha,prefix={{branch}}-

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

Multi-Stage Docker Builds

多阶段Docker构建

dockerfile
undefined
dockerfile
undefined

Build stage

Build stage

FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build
FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build

Production stage

Production stage

FROM node:20-alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY package*.json ./ EXPOSE 3000 CMD ["npm", "start"]
undefined
FROM node:20-alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY package*.json ./ EXPOSE 3000 CMD ["npm", "start"]
undefined

Container Scanning

容器扫描

yaml
- name: Run Trivy vulnerability scanner
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: 'myorg/myapp:${{ github.sha }}'
    format: 'sarif'
    output: 'trivy-results.sarif'

- name: Upload Trivy results to GitHub Security
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: 'trivy-results.sarif'
yaml
- name: Run Trivy vulnerability scanner
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: 'myorg/myapp:${{ github.sha }}'
    format: 'sarif'
    output: 'trivy-results.sarif'

- name: Upload Trivy results to GitHub Security
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: 'trivy-results.sarif'

Release Automation

发布自动化

Semantic Versioning

语义化版本控制

Automatically version releases based on commit messages:
yaml
jobs:
  release:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Semantic Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npx semantic-release
Configuration (.releaserc.json):
json
{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/changelog",
    "@semantic-release/npm",
    "@semantic-release/github",
    ["@semantic-release/git", {
      "assets": ["CHANGELOG.md", "package.json"],
      "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
    }]
  ]
}
基于提交消息自动版本化发布:
yaml
jobs:
  release:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Semantic Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npx semantic-release
配置文件(.releaserc.json):
json
{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/changelog",
    "@semantic-release/npm",
    "@semantic-release/github",
    ["@semantic-release/git", {
      "assets": ["CHANGELOG.md", "package.json"],
      "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
    }]
  ]
}

Changelog Generation

变更日志生成

yaml
- name: Generate changelog
  uses: mikepenz/release-changelog-builder-action@v4
  with:
    configuration: '.github/changelog-config.json'
    outputFile: 'CHANGELOG.md'
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Create GitHub Release
  uses: ncipollo/release-action@v1
  with:
    tag: ${{ steps.version.outputs.tag }}
    name: Release ${{ steps.version.outputs.tag }}
    bodyFile: 'CHANGELOG.md'
    artifacts: 'dist/*'
yaml
- name: Generate changelog
  uses: mikepenz/release-changelog-builder-action@v4
  with:
    configuration: '.github/changelog-config.json'
    outputFile: 'CHANGELOG.md'
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Create GitHub Release
  uses: ncipollo/release-action@v1
  with:
    tag: ${{ steps.version.outputs.tag }}
    name: Release ${{ steps.version.outputs.tag }}
    bodyFile: 'CHANGELOG.md'
    artifacts: 'dist/*'

Release Notes Automation

发布说明自动化

yaml
- name: Build Release Notes
  id: release_notes
  uses: mikepenz/release-changelog-builder-action@v4
  with:
    configurationJson: |
      {
        "categories": [
          {
            "title": "## 🚀 Features",
            "labels": ["feature", "enhancement"]
          },
          {
            "title": "## 🐛 Fixes",
            "labels": ["bug", "fix"]
          },
          {
            "title": "## 📝 Documentation",
            "labels": ["documentation"]
          }
        ]
      }
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
yaml
- name: Build Release Notes
  id: release_notes
  uses: mikepenz/release-changelog-builder-action@v4
  with:
    configurationJson: |
      {
        "categories": [
          {
            "title": "## 🚀 Features",
            "labels": ["feature", "enhancement"]
          },
          {
            "title": "## 🐛 Fixes",
            "labels": ["bug", "fix"]
          },
          {
            "title": "## 📝 Documentation",
            "labels": ["documentation"]
          }
        ]
      }
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Monorepo CI/CD Patterns

单体仓库(Monorepo)CI/CD模式

Path-Based Triggers

基于路径的触发器

Run workflows only when specific packages change:
yaml
name: Frontend CI
on:
  push:
    paths:
      - 'packages/frontend/**'
      - 'package.json'
      - 'pnpm-lock.yaml'

jobs:
  test-frontend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Test frontend
        run: pnpm --filter frontend test
仅当特定包发生变更时运行工作流:
yaml
name: Frontend CI
on:
  push:
    paths:
      - 'packages/frontend/**'
      - 'package.json'
      - 'pnpm-lock.yaml'

jobs:
  test-frontend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Test frontend
        run: pnpm --filter frontend test

Affected Package Detection

变更包检测

yaml
jobs:
  detect-changes:
    runs-on: ubuntu-latest
    outputs:
      affected: ${{ steps.affected.outputs.packages }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Detect affected packages
        id: affected
        run: |
          # Use tools like Nx or Turborepo to detect changes
          AFFECTED=$(npx nx affected:apps --base=origin/main --plain)
          echo "packages=$AFFECTED" >> $GITHUB_OUTPUT

  test-affected:
    needs: detect-changes
    runs-on: ubuntu-latest
    strategy:
      matrix:
        package: ${{ fromJson(needs.detect-changes.outputs.affected) }}
    steps:
      - uses: actions/checkout@v4
      - name: Test ${{ matrix.package }}
        run: npm run test --workspace=${{ matrix.package }}
yaml
jobs:
  detect-changes:
    runs-on: ubuntu-latest
    outputs:
      affected: ${{ steps.affected.outputs.packages }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Detect affected packages
        id: affected
        run: |
          # 使用Nx或Turborepo等工具检测变更
          AFFECTED=$(npx nx affected:apps --base=origin/main --plain)
          echo "packages=$AFFECTED" >> $GITHUB_OUTPUT

  test-affected:
    needs: detect-changes
    runs-on: ubuntu-latest
    strategy:
      matrix:
        package: ${{ fromJson(needs.detect-changes.outputs.affected) }}
    steps:
      - uses: actions/checkout@v4
      - name: Test ${{ matrix.package }}
        run: npm run test --workspace=${{ matrix.package }}

Turborepo CI

Turborepo CI

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

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Build with Turborepo
        run: npx turbo build --cache-dir=.turbo

      - name: Cache Turbo
        uses: actions/cache@v4
        with:
          path: .turbo
          key: ${{ runner.os }}-turbo-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-turbo-
yaml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Build with Turborepo
        run: npx turbo build --cache-dir=.turbo

      - name: Cache Turbo
        uses: actions/cache@v4
        with:
          path: .turbo
          key: ${{ runner.os }}-turbo-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-turbo-

Performance Optimization

性能优化

Parallel Job Execution

任务并行执行

yaml
jobs:
  # These jobs run in parallel
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run lint

  unit-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run test:unit

  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run build

  # This job waits for all above to complete
  deploy:
    needs: [lint, unit-test, build]
    runs-on: ubuntu-latest
    steps:
      - run: npm run deploy
yaml
jobs:
  # 这些任务并行运行
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run lint

  unit-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run test:unit

  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run build

  # 此任务等待上述所有任务完成后运行
  deploy:
    needs: [lint, unit-test, build]
    runs-on: ubuntu-latest
    steps:
      - run: npm run deploy

Conditional Job Execution

条件任务执行

yaml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run build

  deploy-staging:
    needs: build
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh staging

  deploy-production:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh production
yaml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run build

  deploy-staging:
    needs: build
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh staging

  deploy-production:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh production

Dependency Caching

依赖缓存

yaml
steps:
  # Node.js with npm
  - uses: actions/setup-node@v4
    with:
      node-version: '20'
      cache: 'npm'

  # Python with pip
  - uses: actions/setup-python@v5
    with:
      python-version: '3.11'
      cache: 'pip'

  # Ruby with bundler
  - uses: ruby/setup-ruby@v1
    with:
      ruby-version: '3.2'
      bundler-cache: true

  # Go modules
  - uses: actions/setup-go@v5
    with:
      go-version: '1.21'
      cache: true
yaml
steps:
  # Node.js + npm
  - uses: actions/setup-node@v4
    with:
      node-version: '20'
      cache: 'npm'

  # Python + pip
  - uses: actions/setup-python@v5
    with:
      python-version: '3.11'
      cache: 'pip'

  # Ruby + bundler
  - uses: ruby/setup-ruby@v1
    with:
      ruby-version: '3.2'
      bundler-cache: true

  # Go模块
  - uses: actions/setup-go@v5
    with:
      go-version: '1.21'
      cache: true

Reusable Workflows

可复用工作流

Creating Reusable Workflows

创建可复用工作流

yaml
undefined
yaml
undefined

.github/workflows/reusable-deploy.yml

.github/workflows/reusable-deploy.yml

name: Reusable Deploy Workflow
on: workflow_call: inputs: environment: required: true type: string version: required: false type: string default: 'latest' secrets: deploy-key: required: true outputs: deployment-url: description: "URL of the deployment" value: ${{ jobs.deploy.outputs.url }}
jobs: deploy: runs-on: ubuntu-latest environment: ${{ inputs.environment }} outputs: url: ${{ steps.deploy.outputs.url }} steps: - uses: actions/checkout@v4
  - name: Deploy
    id: deploy
    env:
      DEPLOY_KEY: ${{ secrets.deploy-key }}
    run: |
      ./deploy.sh ${{ inputs.environment }} ${{ inputs.version }}
      echo "url=https://${{ inputs.environment }}.example.com" >> $GITHUB_OUTPUT
undefined
name: Reusable Deploy Workflow
on: workflow_call: inputs: environment: required: true type: string version: required: false type: string default: 'latest' secrets: deploy-key: required: true outputs: deployment-url: description: "部署的URL" value: ${{ jobs.deploy.outputs.url }}
jobs: deploy: runs-on: ubuntu-latest environment: ${{ inputs.environment }} outputs: url: ${{ steps.deploy.outputs.url }} steps: - uses: actions/checkout@v4
  - name: Deploy
    id: deploy
    env:
      DEPLOY_KEY: ${{ secrets.deploy-key }}
    run: |
      ./deploy.sh ${{ inputs.environment }} ${{ inputs.version }}
      echo "url=https://${{ inputs.environment }}.example.com" >> $GITHUB_OUTPUT
undefined

Calling Reusable Workflows

调用可复用工作流

yaml
undefined
yaml
undefined

.github/workflows/main.yml

.github/workflows/main.yml

name: Main Pipeline
on: [push]
jobs: deploy-staging: uses: ./.github/workflows/reusable-deploy.yml with: environment: staging version: ${{ github.sha }} secrets: deploy-key: ${{ secrets.STAGING_DEPLOY_KEY }}
deploy-production: needs: deploy-staging uses: ./.github/workflows/reusable-deploy.yml with: environment: production version: ${{ github.sha }} secrets: deploy-key: ${{ secrets.PRODUCTION_DEPLOY_KEY }}
undefined
name: Main Pipeline
on: [push]
jobs: deploy-staging: uses: ./.github/workflows/reusable-deploy.yml with: environment: staging version: ${{ github.sha }} secrets: deploy-key: ${{ secrets.STAGING_DEPLOY_KEY }}
deploy-production: needs: deploy-staging uses: ./.github/workflows/reusable-deploy.yml with: environment: production version: ${{ github.sha }} secrets: deploy-key: ${{ secrets.PRODUCTION_DEPLOY_KEY }}
undefined

Infrastructure as Code

基础设施即代码

Terraform Deployment

Terraform部署

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

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: 1.7.0

      - name: Terraform Format
        run: terraform fmt -check

      - name: Terraform Init
        run: terraform init
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

      - name: Terraform Validate
        run: terraform validate

      - name: Terraform Plan
        run: terraform plan -out=tfplan
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

      - name: Terraform Apply
        if: github.ref == 'refs/heads/main'
        run: terraform apply -auto-approve tfplan
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
yaml
jobs:
  terraform:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: 1.7.0

      - name: Terraform Format
        run: terraform fmt -check

      - name: Terraform Init
        run: terraform init
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

      - name: Terraform Validate
        run: terraform validate

      - name: Terraform Plan
        run: terraform plan -out=tfplan
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

      - name: Terraform Apply
        if: github.ref == 'refs/heads/main'
        run: terraform apply -auto-approve tfplan
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

AWS CloudFormation

AWS CloudFormation

yaml
jobs:
  deploy-cloudformation:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: us-east-1

      - name: Deploy CloudFormation stack
        run: |
          aws cloudformation deploy \
            --template-file infrastructure/template.yml \
            --stack-name my-app-stack \
            --parameter-overrides \
              Environment=production \
              Version=${{ github.sha }} \
            --capabilities CAPABILITY_IAM
yaml
jobs:
  deploy-cloudformation:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: us-east-1

      - name: Deploy CloudFormation stack
        run: |
          aws cloudformation deploy \
            --template-file infrastructure/template.yml \
            --stack-name my-app-stack \
            --parameter-overrides \
              Environment=production \
              Version=${{ github.sha }} \
            --capabilities CAPABILITY_IAM

Best Practices

最佳实践

Workflow Organization

工作流组织

  1. Separate concerns: Different workflows for CI, CD, and scheduled tasks
  2. Use descriptive names: Clear workflow and job names
  3. Organize with directories: Group related workflows
  4. Version control: Track workflow changes like code
  1. 关注点分离:为CI、CD和定时任务使用不同工作流
  2. 使用描述性名称:清晰的工作流和任务名称
  3. 按目录组织:将相关工作流分组
  4. 版本控制:像代码一样跟踪工作流变更

Efficiency

效率

  1. Cache dependencies: Reduce build times significantly
  2. Parallel execution: Run independent jobs simultaneously
  3. Conditional runs: Skip unnecessary jobs
  4. Matrix strategies: Test multiple configurations efficiently
  5. Artifact reuse: Share build outputs between jobs
  1. 缓存依赖:显著缩短构建时间
  2. 并行执行:同时运行独立任务
  3. 条件执行:跳过不必要的任务
  4. 矩阵策略:高效测试多配置
  5. 产物复用:在任务间共享构建输出

Security

安全性

  1. Minimize permissions: Use least-privilege principle
  2. Use OIDC: Avoid long-lived credentials
  3. Secret rotation: Regularly update secrets
  4. Pin dependencies: Use specific versions or SHAs
  5. Scan for vulnerabilities: Automated security checks
  1. 最小化权限:遵循最小权限原则
  2. 使用OIDC:避免长期凭证
  3. 密钥轮换:定期更新密钥
  4. 固定依赖版本:使用特定版本或SHA
  5. 漏洞扫描:自动化安全检查

Reliability

可靠性

  1. Timeout settings: Prevent hanging jobs
  2. Retry logic: Handle transient failures
  3. Failure notifications: Alert on critical failures
  4. Rollback mechanisms: Quick recovery from failed deployments
  5. Health checks: Verify deployments before marking complete
  1. 超时设置:防止任务挂起
  2. 重试逻辑:处理临时故障
  3. 故障通知:关键故障时发出警报
  4. 回滚机制:从失败部署中快速恢复
  5. 健康检查:在标记完成前验证部署状态

Observability

可观测性

  1. Detailed logging: Clear, actionable logs
  2. Status checks: Prevent merging failing builds
  3. Deployment tracking: Know what's deployed where
  4. Metrics collection: Track pipeline performance
  5. Audit trails: Track who deployed what and when
  1. 详细日志:清晰、可操作的日志
  2. 状态检查:防止合并失败的构建
  3. 部署跟踪:了解各环境部署内容
  4. 指标收集:跟踪流水线性能
  5. 审计追踪:记录谁在何时部署了什么

Failure Handling

故障处理

Retry Failed Steps

重试失败步骤

yaml
steps:
  - name: Deploy with retry
    uses: nick-fields/retry-action@v2
    with:
      timeout_minutes: 10
      max_attempts: 3
      retry_wait_seconds: 30
      command: npm run deploy
yaml
steps:
  - name: Deploy with retry
    uses: nick-fields/retry-action@v2
    with:
      timeout_minutes: 10
      max_attempts: 3
      retry_wait_seconds: 30
      command: npm run deploy

Continue on Error

错误后继续执行

yaml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Run optional check
        continue-on-error: true
        run: npm run optional-check

      - name: Run required tests
        run: npm test
yaml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Run optional check
        continue-on-error: true
        run: npm run optional-check

      - name: Run required tests
        run: npm test

Conditional Cleanup

条件清理

yaml
steps:
  - name: Deploy
    id: deploy
    run: ./deploy.sh

  - name: Rollback on failure
    if: failure() && steps.deploy.conclusion == 'failure'
    run: ./rollback.sh

  - name: Cleanup
    if: always()
    run: ./cleanup.sh
yaml
steps:
  - name: Deploy
    id: deploy
    run: ./deploy.sh

  - name: Rollback on failure
    if: failure() && steps.deploy.conclusion == 'failure'
    run: ./rollback.sh

  - name: Cleanup
    if: always()
    run: ./cleanup.sh

Advanced Patterns

高级模式

Dynamic Matrix Generation

动态矩阵生成

yaml
jobs:
  generate-matrix:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - uses: actions/checkout@v4
      - id: set-matrix
        run: |
          # Generate matrix based on project structure
          MATRIX=$(find packages -maxdepth 1 -type d -not -name packages | \
            jq -R -s -c 'split("\n")[:-1]')
          echo "matrix=$MATRIX" >> $GITHUB_OUTPUT

  test:
    needs: generate-matrix
    runs-on: ubuntu-latest
    strategy:
      matrix:
        package: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
    steps:
      - uses: actions/checkout@v4
      - run: npm test --workspace=${{ matrix.package }}
yaml
jobs:
  generate-matrix:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - uses: actions/checkout@v4
      - id: set-matrix
        run: |
          # 基于项目结构生成矩阵
          MATRIX=$(find packages -maxdepth 1 -type d -not -name packages | \
            jq -R -s -c 'split("\n")[:-1]')
          echo "matrix=$MATRIX" >> $GITHUB_OUTPUT

  test:
    needs: generate-matrix
    runs-on: ubuntu-latest
    strategy:
      matrix:
        package: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
    steps:
      - uses: actions/checkout@v4
      - run: npm test --workspace=${{ matrix.package }}

Composite Actions

复合Actions

Create reusable action combinations:
yaml
undefined
创建可复用的Action组合:
yaml
undefined

.github/actions/setup-project/action.yml

.github/actions/setup-project/action.yml

name: 'Setup Project' description: 'Setup Node.js and install dependencies' inputs: node-version: description: 'Node.js version' required: false default: '20' runs: using: 'composite' steps: - uses: actions/setup-node@v4 with: node-version: ${{ inputs.node-version }} cache: 'npm'
- run: npm ci
  shell: bash

- run: npm run build
  shell: bash

**Usage:**
```yaml
steps:
  - uses: actions/checkout@v4
  - uses: ./.github/actions/setup-project
    with:
      node-version: '20'
name: '项目初始化' description: '配置Node.js并安装依赖' inputs: node-version: description: 'Node.js版本' required: false default: '20' runs: using: 'composite' steps: - uses: actions/setup-node@v4 with: node-version: ${{ inputs.node-version }} cache: 'npm'
- run: npm ci
  shell: bash

- run: npm run build
  shell: bash

**使用方式:**
```yaml
steps:
  - uses: actions/checkout@v4
  - uses: ./.github/actions/setup-project
    with:
      node-version: '20'

Self-Hosted Runners

自托管运行器

yaml
jobs:
  deploy:
    runs-on: [self-hosted, linux, production]
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to production
        run: ./deploy.sh
Benefits:
  • Custom hardware/software requirements
  • Faster builds (pre-cached dependencies)
  • Access to internal networks
  • Cost savings for high-volume CI/CD
yaml
jobs:
  deploy:
    runs-on: [self-hosted, linux, production]
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to production
        run: ./deploy.sh
优势:
  • 自定义硬件/软件需求
  • 构建更快(预缓存依赖)
  • 可访问内部网络
  • 高流量CI/CD场景下节省成本

Platform-Specific Deployments

特定平台部署

Vercel Deployment

Vercel部署

yaml
jobs:
  deploy-vercel:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: '--prod'
yaml
jobs:
  deploy-vercel:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: '--prod'

Netlify Deployment

Netlify部署

yaml
jobs:
  deploy-netlify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build
        run: npm run build

      - name: Deploy to Netlify
        uses: nwtgck/actions-netlify@v3
        with:
          publish-dir: './dist'
          production-branch: main
          github-token: ${{ secrets.GITHUB_TOKEN }}
          deploy-message: 'Deploy from GitHub Actions'
        env:
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
yaml
jobs:
  deploy-netlify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build
        run: npm run build

      - name: Deploy to Netlify
        uses: nwtgck/actions-netlify@v3
        with:
          publish-dir: './dist'
          production-branch: main
          github-token: ${{ secrets.GITHUB_TOKEN }}
          deploy-message: 'Deploy from GitHub Actions'
        env:
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}

AWS ECS Deployment

AWS ECS部署

yaml
jobs:
  deploy-ecs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: us-east-1

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      - name: Build and push Docker image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: my-app
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

      - name: Update ECS service
        run: |
          aws ecs update-service \
            --cluster my-cluster \
            --service my-service \
            --force-new-deployment
yaml
jobs:
  deploy-ecs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: us-east-1

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      - name: Build and push Docker image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: my-app
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

      - name: Update ECS service
        run: |
          aws ecs update-service \
            --cluster my-cluster \
            --service my-service \
            --force-new-deployment

Kubernetes Deployment

Kubernetes部署

yaml
jobs:
  deploy-k8s:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup kubectl
        uses: azure/setup-kubectl@v3
        with:
          version: 'v1.28.0'

      - name: Configure kubeconfig
        run: |
          echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > kubeconfig.yml
          echo "KUBECONFIG=$(pwd)/kubeconfig.yml" >> $GITHUB_ENV

      - name: Deploy to Kubernetes
        run: |
          kubectl set image deployment/myapp \
            myapp=myregistry/myapp:${{ github.sha }}
          kubectl rollout status deployment/myapp

Skill Version: 1.0.0 Last Updated: October 2025 Skill Category: DevOps, CI/CD, Automation, Deployment Compatible With: GitHub Actions, Docker, Kubernetes, AWS, Azure, GCP, Vercel, Netlify
yaml
jobs:
  deploy-k8s:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup kubectl
        uses: azure/setup-kubectl@v3
        with:
          version: 'v1.28.0'

      - name: Configure kubeconfig
        run: |
          echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > kubeconfig.yml
          echo "KUBECONFIG=$(pwd)/kubeconfig.yml" >> $GITHUB_ENV

      - name: Deploy to Kubernetes
        run: |
          kubectl set image deployment/myapp \
            myapp=myregistry/myapp:${{ github.sha }}
          kubectl rollout status deployment/myapp

技能版本:1.0.0 最后更新:2025年10月 技能分类:DevOps、CI/CD、自动化、部署 兼容平台:GitHub Actions、Docker、Kubernetes、AWS、Azure、GCP、Vercel、Netlify