GitHub Actions CI/CD 自动化部署完全指南
文章目录
- [GitHub Actions CI/CD 自动化部署完全指南](#GitHub Actions CI/CD 自动化部署完全指南)
 - 
- [什么是 CI/CD 和 GitHub Actions](#什么是 CI/CD 和 GitHub Actions)
 - 
- [CI/CD 概念](#CI/CD 概念)
 - [GitHub Actions 简介](#GitHub Actions 简介)
 - 
- [🚀 主要优势](#🚀 主要优势)
 - [📊 使用统计](#📊 使用统计)
 
 
 - [GitHub Actions 核心概念](#GitHub Actions 核心概念)
 - 基础工作流配置
 - 
- 创建第一个工作流
 - 
- [1. 创建工作流文件](#1. 创建工作流文件)
 - [2. 常用触发事件](#2. 常用触发事件)
 - [3. 环境变量配置](#3. 环境变量配置)
 
 
 - [前端项目 CI/CD 实践](#前端项目 CI/CD 实践)
 - 
- [React 项目完整工作流](#React 项目完整工作流)
 - [Vue.js 项目工作流](#Vue.js 项目工作流)
 
 - [后端项目 CI/CD 实践](#后端项目 CI/CD 实践)
 - 
- [Node.js Express 应用](#Node.js Express 应用)
 - [Python Django 应用](#Python Django 应用)
 
 - [全栈项目 CI/CD 实践](#全栈项目 CI/CD 实践)
 - 
- [Monorepo 项目结构](#Monorepo 项目结构)
 
 - 安全性和性能优化
 - 常见问题和解决方案
 - 总结
 
 - 部署
 - 
- 总结
 - 
- [🎯 核心收获](#🎯 核心收获)
 - [📈 进阶建议](#📈 进阶建议)
 - [🔗 有用资源](#🔗 有用资源)
 - [🚀 下一步行动](#🚀 下一步行动)
 
 
 - 部署
 - 
- 安全性和性能优化
 - 常见问题和解决方案
 - 
- [问题 1:工作流执行时间过长](#问题 1:工作流执行时间过长)
 - [问题 2:Secrets 管理混乱](#问题 2:Secrets 管理混乱)
 - [问题 3:依赖冲突和版本问题](#问题 3:依赖冲突和版本问题)
 - [问题 4:环境变量和配置管理](#问题 4:环境变量和配置管理)
 - [问题 5:Docker 构建优化](#问题 5:Docker 构建优化)
 
 - 实用配置模板
 - 
- [模板 1:React + TypeScript 项目](#模板 1:React + TypeScript 项目)
 - [模板 2:Node.js API 项目](#模板 2:Node.js API 项目)
 
 
 
什么是 CI/CD 和 GitHub Actions
CI/CD 概念
持续集成(Continuous Integration, CI) 是一种开发实践,开发者频繁地将代码集成到主分支中,每次集成都通过自动化构建来验证,从而尽早发现集成错误。
持续部署(Continuous Deployment, CD) 是在持续集成的基础上,将通过测试的代码自动部署到生产环境的实践。
GitHub Actions 简介
GitHub Actions 是 GitHub 提供的 CI/CD 平台,允许您直接在 GitHub 仓库中自动化软件开发工作流程。
🚀 主要优势
- 原生集成:与 GitHub 仓库无缝集成
 - 免费额度:公共仓库免费,私有仓库每月 2000 分钟免费
 - 丰富的 Actions 市场:数千个预构建的 Actions 可供使用
 - 多平台支持:支持 Linux、Windows、macOS
 - 灵活配置:支持复杂的工作流程和条件执行
 
📊 使用统计
GitHub Actions 使用数据:
- 超过 300 万个组织在使用
- 每月执行超过 10 亿次工作流
- 市场中有超过 20,000 个 Actions
        GitHub Actions 核心概念
基本组件
1. Workflow(工作流)
- 定义在 
.github/workflows/目录下的 YAML 文件 - 包含一个或多个 Jobs
 - 由特定事件触发
 
2. Event(事件)
- 触发工作流的特定活动
 - 常见事件:
push、pull_request、schedule、workflow_dispatch 
3. Job(作业)
- 工作流中的一组步骤
 - 在同一个运行器上执行
 - 可以并行或串行执行
 
4. Step(步骤)
- Job 中的单个任务
 - 可以运行命令或使用 Action
 
5. Action(动作)
- 可重用的代码单元
 - 可以是自定义的或来自市场
 
6. Runner(运行器)
- 执行工作流的服务器
 - GitHub 提供托管运行器,也可以自托管
 
工作流语法结构
            
            
              yaml
              
              
            
          
          name: 工作流名称
# 触发条件
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
# 环境变量
env:
  NODE_VERSION: '18'
# 作业定义
jobs:
  job-name:
    runs-on: ubuntu-latest
    
    steps:
    - name: 步骤名称
      uses: actions/checkout@v4
      
    - name: 另一个步骤
      run: echo "Hello World"
        基础工作流配置
创建第一个工作流
1. 创建工作流文件
在项目根目录创建 .github/workflows/ci.yml:
            
            
              yaml
              
              
            
          
          name: Basic CI
# 触发条件:推送到 main 分支或创建 PR
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
jobs:
  test:
    name: 运行测试
    runs-on: ubuntu-latest
    
    steps:
    # 检出代码
    - name: Checkout code
      uses: actions/checkout@v4
    
    # 设置 Node.js 环境
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: '18'
        cache: 'npm'
    
    # 安装依赖
    - name: Install dependencies
      run: npm ci
    
    # 运行测试
    - name: Run tests
      run: npm test
    
    # 运行代码检查
    - name: Run linting
      run: npm run lint
        2. 常用触发事件
            
            
              yaml
              
              
            
          
          on:
  # 推送到指定分支
  push:
    branches: [ main, develop ]
    paths:
      - 'src/**'
      - 'package.json'
  
  # Pull Request
  pull_request:
    branches: [ main ]
    types: [opened, synchronize, reopened]
  
  # 定时执行
  schedule:
    - cron: '0 2 * * *'  # 每天凌晨2点
  
  # 手动触发
  workflow_dispatch:
    inputs:
      environment:
        description: '部署环境'
        required: true
        default: 'staging'
        type: choice
        options:
        - staging
        - production
  
  # 发布 Release
  release:
    types: [published]
        3. 环境变量配置
            
            
              yaml
              
              
            
          
          env:
  # 全局环境变量
  NODE_VERSION: '18'
  REGISTRY_URL: 'https://registry.npmjs.org'
jobs:
  build:
    runs-on: ubuntu-latest
    
    env:
      # Job 级别环境变量
      BUILD_ENV: production
    
    steps:
    - name: Build application
      env:
        # Step 级别环境变量
        API_URL: ${{ secrets.API_URL }}
      run: |
        echo "Node version: $NODE_VERSION"
        echo "Build environment: $BUILD_ENV"
        echo "API URL: $API_URL"
        前端项目 CI/CD 实践
React 项目完整工作流
            
            
              yaml
              
              
            
          
          name: React App CI/CD
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
env:
  NODE_VERSION: '18'
  REGISTRY_URL: 'https://registry.npmjs.org'
jobs:
  # 代码质量检查
  quality-check:
    name: 代码质量检查
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ env.NODE_VERSION }}
        cache: 'npm'
        registry-url: ${{ env.REGISTRY_URL }}
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run ESLint
      run: npm run lint
    
    - name: Run Prettier check
      run: npm run format:check
    
    - name: Run type check
      run: npm run type-check
    
    - name: Run tests with coverage
      run: npm run test:coverage
    
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage/lcov.info
        flags: unittests
        name: codecov-umbrella
  # 构建应用
  build:
    name: 构建应用
    runs-on: ubuntu-latest
    needs: quality-check
    
    strategy:
      matrix:
        environment: [staging, production]
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ env.NODE_VERSION }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Build for ${{ matrix.environment }}
      env:
        REACT_APP_ENV: ${{ matrix.environment }}
        REACT_APP_API_URL: ${{ secrets[format('API_URL_{0}', matrix.environment)] }}
      run: npm run build
    
    - name: Upload build artifacts
      uses: actions/upload-artifact@v3
      with:
        name: build-${{ matrix.environment }}
        path: build/
        retention-days: 7
  # 部署到 Vercel
  deploy-vercel:
    name: 部署到 Vercel
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/main'
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Download build artifacts
      uses: actions/download-artifact@v3
      with:
        name: build-production
        path: build/
    
    - 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 }}
        working-directory: ./
        vercel-args: '--prod'
  # 部署到 Netlify
  deploy-netlify:
    name: 部署到 Netlify
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/develop'
    
    steps:
    - name: Download build artifacts
      uses: actions/download-artifact@v3
      with:
        name: build-staging
        path: build/
    
    - name: Deploy to Netlify
      uses: nwtgck/actions-netlify@v2.0
      with:
        publish-dir: './build'
        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 }}
        Vue.js 项目工作流
            
            
              yaml
              
              
            
          
          name: Vue.js App CI/CD
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
jobs:
  test-and-build:
    name: 测试和构建
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [16, 18, 20]
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v4
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run unit tests
      run: npm run test:unit
    
    - name: Run e2e tests
      run: npm run test:e2e:headless
    
    - name: Build application
      run: npm run build
    
    - name: Upload build artifacts
      if: matrix.node-version == 18
      uses: actions/upload-artifact@v3
      with:
        name: vue-build
        path: dist/
  deploy:
    name: 部署应用
    runs-on: ubuntu-latest
    needs: test-and-build
    if: github.ref == 'refs/heads/main'
    
    steps:
    - name: Download build artifacts
      uses: actions/download-artifact@v3
      with:
        name: vue-build
        path: dist/
    
    - name: Deploy to GitHub Pages
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./dist
        后端项目 CI/CD 实践
Node.js Express 应用
            
            
              yaml
              
              
            
          
          name: Node.js Express API CI/CD
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
env:
  NODE_VERSION: '18'
  DOCKER_REGISTRY: 'ghcr.io'
jobs:
  # 测试阶段
  test:
    name: 运行测试
    runs-on: ubuntu-latest
    
    services:
      # PostgreSQL 服务
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: test_db
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
      
      # Redis 服务
      redis:
        image: redis:7
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 6379:6379
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ env.NODE_VERSION }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run database migrations
      env:
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
      run: npm run db:migrate
    
    - name: Run unit tests
      env:
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
        REDIS_URL: redis://localhost:6379
      run: npm run test
    
    - name: Run integration tests
      env:
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
        REDIS_URL: redis://localhost:6379
      run: npm run test:integration
    
    - name: Generate test coverage
      run: npm run test:coverage
    
    - name: Upload coverage reports
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage/lcov.info
  # 安全扫描
  security-scan:
    name: 安全扫描
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Run npm audit
      run: npm audit --audit-level moderate
    
    - name: Run Snyk security scan
      uses: snyk/actions/node@master
      env:
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      with:
        args: --severity-threshold=high
  # 构建 Docker 镜像
  build-docker:
    name: 构建 Docker 镜像
    runs-on: ubuntu-latest
    needs: [test, security-scan]
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3
    
    - name: Login to Container Registry
      uses: docker/login-action@v3
      with:
        registry: ${{ env.DOCKER_REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}
    
    - name: Extract metadata
      id: meta
      uses: docker/metadata-action@v5
      with:
        images: ${{ env.DOCKER_REGISTRY }}/${{ github.repository }}
        tags: |
          type=ref,event=branch
          type=ref,event=pr
          type=sha,prefix={{branch}}-
          type=raw,value=latest,enable={{is_default_branch}}
    
    - name: Build and push Docker image
      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
  # 部署到 staging
  deploy-staging:
    name: 部署到 Staging
    runs-on: ubuntu-latest
    needs: build-docker
    if: github.ref == 'refs/heads/develop'
    environment: staging
    
    steps:
    - name: Deploy to staging server
      uses: appleboy/ssh-action@v1.0.0
      with:
        host: ${{ secrets.STAGING_HOST }}
        username: ${{ secrets.STAGING_USER }}
        key: ${{ secrets.STAGING_SSH_KEY }}
        script: |
          docker pull ${{ env.DOCKER_REGISTRY }}/${{ github.repository }}:develop
          docker stop api-staging || true
          docker rm api-staging || true
          docker run -d \
            --name api-staging \
            --restart unless-stopped \
            -p 3000:3000 \
            -e NODE_ENV=staging \
            -e DATABASE_URL=${{ secrets.STAGING_DATABASE_URL }} \
            ${{ env.DOCKER_REGISTRY }}/${{ github.repository }}:develop
  # 部署到 production
  deploy-production:
    name: 部署到 Production
    runs-on: ubuntu-latest
    needs: build-docker
    if: github.ref == 'refs/heads/main'
    environment: production
    
    steps:
    - name: Deploy to Kubernetes
      uses: azure/k8s-deploy@v1
      with:
        manifests: |
          k8s/deployment.yaml
          k8s/service.yaml
        images: |
          ${{ env.DOCKER_REGISTRY }}/${{ github.repository }}:latest
        kubeconfig: ${{ secrets.KUBE_CONFIG }}
        Python Django 应用
            
            
              yaml
              
              
            
          
          name: Django App CI/CD
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
jobs:
  test:
    name: 测试 Django 应用
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        python-version: [3.9, 3.10, 3.11]
    
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: django_test
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v4
      with:
        python-version: ${{ matrix.python-version }}
    
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
        pip install -r requirements-dev.txt
    
    - name: Run migrations
      env:
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/django_test
      run: python manage.py migrate
    
    - name: Run tests
      env:
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/django_test
      run: |
        python manage.py test
        coverage run --source='.' manage.py test
        coverage xml
    
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage.xml
  deploy:
    name: 部署到 Heroku
    runs-on: ubuntu-latest
    needs: test
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Deploy to Heroku
      uses: akhileshns/heroku-deploy@v3.12.14
      with:
        heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
        heroku_app_name: "your-django-app"
        heroku_email: "your-email@example.com"
        全栈项目 CI/CD 实践
Monorepo 项目结构
            
            
              yaml
              
              
            
          
          name: Full Stack Monorepo CI/CD
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
env:
  NODE_VERSION: '18'
  PYTHON_VERSION: '3.11'
jobs:
  # 检测变更
  detect-changes:
    name: 检测文件变更
    runs-on: ubuntu-latest
    outputs:
      frontend: ${{ steps.changes.outputs.frontend }}
      backend: ${{ steps.changes.outputs.backend }}
      shared: ${{ steps.changes.outputs.shared }}
    
    steps:
    - uses: actions/checkout@v4
    
    - uses: dorny/paths-filter@v2
      id: changes
      with:
        filters: |
          frontend:
            - 'frontend/**'
            - 'shared/**'
          backend:
            - 'backend/**'
            - 'shared/**'
          shared:
            - 'shared/**'
  # 前端测试和构建
  frontend-ci:
    name: 前端 CI
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.frontend == 'true'
    
    defaults:
      run:
        working-directory: ./frontend
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ env.NODE_VERSION }}
        cache: 'npm'
        cache-dependency-path: frontend/package-lock.json
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run tests
      run: npm test
    
    - name: Build application
      run: npm run build
    
    - name: Upload build artifacts
      uses: actions/upload-artifact@v3
      with:
        name: frontend-build
        path: frontend/dist/
  # 后端测试
  backend-ci:
    name: 后端 CI
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.backend == 'true'
    
    defaults:
      run:
        working-directory: ./backend
    
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: test_db
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Python
      uses: actions/setup-python@v4
      with:
        python-version: ${{ env.PYTHON_VERSION }}
    
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    
    - name: Run tests
      env:
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
      run: pytest
  # 集成测试
  integration-test:
    name: 集成测试
    runs-on: ubuntu-latest
    needs: [frontend-ci, backend-ci]
    if: always() && (needs.frontend-ci.result == 'success' || needs.frontend-ci.result == 'skipped') && (needs.backend-ci.result == 'success' || needs.backend-ci.result == 'skipped')
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ env.NODE_VERSION }}
    
    - name: Install Playwright
      run: |
        npm install -g @playwright/test
        npx playwright install
    
    - name: Start services with Docker Compose
      run: docker-compose -f docker-compose.test.yml up -d
    
    - name: Wait for services
      run: |
        timeout 60 bash -c 'until curl -f http://localhost:3000/health; do sleep 2; done'
        timeout 60 bash -c 'until curl -f http://localhost:8000/health; do sleep 2; done'
    
    - name: Run E2E tests
      run: npx playwright test
    
    - name: Upload test results
      uses: actions/upload-artifact@v3
      if: always()
      with:
        name: playwright-report
        path: playwright-report/
  # 部署
  deploy:
    name: 部署
    runs-on: ubuntu-latest
    needs: [frontend, backend, e2e]
    if: github.ref == 'refs/heads/main' && success()
    
    steps:
    - name: Download frontend build
      uses: actions/download-artifact@v3
      with:
        name: frontend-build
        path: frontend-dist/
    
    - name: Deploy frontend to CDN
      run: |
        # 部署前端到 CDN
        echo "Deploying frontend to CDN..."
    
    - name: Deploy backend to Kubernetes
      run: |
        # 部署后端到 K8s
        echo "Deploying backend to Kubernetes..."
        安全性和性能优化
安全最佳实践
1. Secrets 管理
            
            
              yaml
              
              
            
          
          name: Secure CI/CD
on:
  push:
    branches: [ main ]
jobs:
  secure-build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    # ✅ 正确的 secrets 使用
    - 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
    
    # ❌ 错误:不要在日志中暴露敏感信息
    # - name: Debug secrets
    #   run: echo "API Key: ${{ secrets.API_KEY }}"
    
    # ✅ 正确:使用环境变量
    - name: Deploy with secrets
      env:
        API_KEY: ${{ secrets.API_KEY }}
        DATABASE_URL: ${{ secrets.DATABASE_URL }}
      run: |
        # 使用环境变量而不是直接引用 secrets
        ./deploy.sh
        2. 权限最小化
            
            
              yaml
              
              
            
          
          name: Minimal Permissions
on:
  push:
    branches: [ main ]
# 设置最小权限
permissions:
  contents: read
  packages: write
  security-events: write
jobs:
  build:
    runs-on: ubuntu-latest
    
    # Job 级别权限覆盖
    permissions:
      contents: read
      packages: write
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Build and push Docker image
      uses: docker/build-push-action@v5
      with:
        context: .
        push: true
        tags: ghcr.io/${{ github.repository }}:latest
        3. 依赖安全扫描
            
            
              yaml
              
              
            
          
          name: Security Scanning
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  schedule:
    - cron: '0 6 * * 1'  # 每周一早上6点
jobs:
  security-scan:
    name: 安全扫描
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    # npm 审计
    - name: Run npm audit
      run: |
        npm audit --audit-level moderate
        npm audit fix --dry-run
    
    # Snyk 安全扫描
    - name: Run Snyk to check for vulnerabilities
      uses: snyk/actions/node@master
      env:
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      with:
        args: --severity-threshold=high --fail-on=upgradable
    
    # CodeQL 代码分析
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v2
      with:
        languages: javascript, typescript
    
    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v2
    
    # 容器镜像扫描
    - name: Run Trivy vulnerability scanner
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: 'myapp:latest'
        format: 'sarif'
        output: 'trivy-results.sarif'
    
    - name: Upload Trivy scan results
      uses: github/codeql-action/upload-sarif@v2
      with:
        sarif_file: 'trivy-results.sarif'
        4. 环境隔离和保护
            
            
              yaml
              
              
            
          
          name: Environment Protection
on:
  push:
    branches: [ main, develop ]
jobs:
  deploy-staging:
    name: 部署到 Staging
    runs-on: ubuntu-latest
    environment: staging
    if: github.ref == 'refs/heads/develop'
    
    steps:
    - name: Deploy to staging
      run: echo "Deploying to staging environment"
  deploy-production:
    name: 部署到 Production
    runs-on: ubuntu-latest
    environment: 
      name: production
      url: https://myapp.com
    if: github.ref == 'refs/heads/main'
    
    steps:
    - name: Deploy to production
      run: echo "Deploying to production environment"
        性能优化策略
1. 缓存优化
            
            
              yaml
              
              
            
          
          name: Optimized Caching
on:
  push:
    branches: [ main ]
jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    # Node.js 依赖缓存
    - name: Setup Node.js with cache
      uses: actions/setup-node@v4
      with:
        node-version: '18'
        cache: 'npm'
        cache-dependency-path: |
          package-lock.json
          frontend/package-lock.json
          backend/package-lock.json
    
    # 自定义缓存
    - name: Cache node modules
      uses: actions/cache@v3
      with:
        path: |
          ~/.npm
          node_modules
          */node_modules
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.os }}-node-
    
    # Docker 层缓存
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3
    
    - name: Build with cache
      uses: docker/build-push-action@v5
      with:
        context: .
        cache-from: type=gha
        cache-to: type=gha,mode=max
        push: true
        tags: myapp:latest
        2. 并行执行优化
            
            
              yaml
              
              
            
          
          name: Parallel Execution
on:
  push:
    branches: [ main ]
jobs:
  # 并行测试矩阵
  test:
    name: 测试
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [16, 18, 20]
        test-suite: [unit, integration, e2e]
      fail-fast: false  # 不因单个失败而停止所有任务
      max-parallel: 6   # 最大并行数
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v4
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run ${{ matrix.test-suite }} tests
      run: npm run test:${{ matrix.test-suite }}
  # 并行构建不同平台
  build:
    name: 构建
    runs-on: ubuntu-latest
    needs: test
    
    strategy:
      matrix:
        platform: [linux/amd64, linux/arm64]
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Set up QEMU
      uses: docker/setup-qemu-action@v3
    
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3
    
    - name: Build for ${{ matrix.platform }}
      uses: docker/build-push-action@v5
      with:
        context: .
        platforms: ${{ matrix.platform }}
        push: true
        tags: myapp:${{ matrix.platform }}
        3. 资源优化
            
            
              yaml
              
              
            
          
          name: Resource Optimization
on:
  push:
    branches: [ main ]
jobs:
  optimized-build:
    name: 优化构建
    runs-on: ubuntu-latest
    
    # 设置超时时间
    timeout-minutes: 30
    
    steps:
    - uses: actions/checkout@v4
      with:
        # 浅克隆以减少下载时间
        fetch-depth: 1
    
    # 只在需要时安装依赖
    - name: Check if dependencies changed
      uses: dorny/paths-filter@v2
      id: changes
      with:
        filters: |
          deps:
            - 'package*.json'
            - 'yarn.lock'
    
    - name: Setup Node.js
      if: steps.changes.outputs.deps == 'true'
      uses: actions/setup-node@v4
      with:
        node-version: '18'
        cache: 'npm'
    
    - name: Install dependencies
      if: steps.changes.outputs.deps == 'true'
      run: npm ci --prefer-offline --no-audit
    
    # 条件执行构建
    - name: Build application
      if: steps.changes.outputs.deps == 'true' || github.event_name == 'push'
      run: npm run build
        常见问题和解决方案
构建和部署问题
1. 依赖安装失败
问题描述 :npm ci 或 npm install 失败
常见原因和解决方案:
            
            
              yaml
              
              
            
          
          # 解决方案 1:清理缓存
- name: Clear npm cache
  run: npm cache clean --force
- name: Install dependencies
  run: npm ci
# 解决方案 2:使用不同的 registry
- name: Setup Node.js
  uses: actions/setup-node@v4
  with:
    node-version: '18'
    registry-url: 'https://registry.npmmirror.com'
# 解决方案 3:忽略可选依赖
- name: Install dependencies
  run: npm ci --no-optional
# 解决方案 4:增加超时时间
- name: Install dependencies
  run: npm ci --timeout=300000
        2. Docker 构建失败
问题描述:Docker 镜像构建过程中出错
            
            
              yaml
              
              
            
          
          # 解决方案 1:多阶段构建优化
# Dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
FROM node:18-alpine AS runtime
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
# 解决方案 2:增加构建资源
- name: Build Docker image
  uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: myapp:latest
    build-args: |
      BUILDKIT_INLINE_CACHE=1
    cache-from: type=gha
    cache-to: type=gha,mode=max
        3. 测试超时或失败
            
            
              yaml
              
              
            
          
          # 解决方案 1:增加测试超时时间
- name: Run tests
  run: npm test
  timeout-minutes: 10
# 解决方案 2:并行测试
- name: Run tests in parallel
  run: npm test -- --maxWorkers=2
# 解决方案 3:重试机制
- name: Run tests with retry
  uses: nick-invision/retry@v2
  with:
    timeout_minutes: 5
    max_attempts: 3
    command: npm test
        权限和安全问题
1. 权限被拒绝错误
            
            
              yaml
              
              
            
          
          # 问题:Permission denied
# 解决方案:设置正确的权限
permissions:
  contents: read
  packages: write
  deployments: write
# 或者在 job 级别设置
jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
    # ...
        2. Secrets 访问问题
            
            
              yaml
              
              
            
          
          # 问题:无法访问 secrets
# 解决方案 1:检查 secrets 名称
- name: Use secret
  env:
    API_KEY: ${{ secrets.API_KEY }}  # 确保名称正确
  run: echo "Using API key"
# 解决方案 2:环境级别的 secrets
jobs:
  deploy:
    environment: production  # 使用环境级别的 secrets
    steps:
    - name: Deploy
      env:
        DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
      run: ./deploy.sh
        性能问题
1. 构建时间过长
            
            
              yaml
              
              
            
          
          # 解决方案 1:使用缓存
- name: Cache dependencies
  uses: actions/cache@v3
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
# 解决方案 2:并行构建
strategy:
  matrix:
    component: [frontend, backend, api]
  max-parallel: 3
# 解决方案 3:条件执行
- name: Build only if changed
  if: steps.changes.outputs.src == 'true'
  run: npm run build
        2. 资源限制问题
            
            
              yaml
              
              
            
          
          # 解决方案 1:使用更大的运行器
jobs:
  build:
    runs-on: ubuntu-latest-4-cores  # 使用更多 CPU 核心
# 解决方案 2:优化内存使用
- name: Build with memory optimization
  run: |
    export NODE_OPTIONS="--max-old-space-size=4096"
    npm run build
        调试技巧
1. 启用调试日志
            
            
              yaml
              
              
            
          
          # 启用 Actions 调试
- name: Debug information
  run: |
    echo "Runner OS: ${{ runner.os }}"
    echo "GitHub ref: ${{ github.ref }}"
    echo "Event name: ${{ github.event_name }}"
    env
# 启用 npm 调试
- name: Install with debug
  run: npm ci --loglevel verbose
# 启用 Docker 调试
- name: Build Docker with debug
  run: |
    export DOCKER_BUILDKIT=1
    export BUILDKIT_PROGRESS=plain
    docker build --progress=plain .
        2. 条件调试
            
            
              yaml
              
              
            
          
          - name: Debug on failure
  if: failure()
  run: |
    echo "Build failed, collecting debug info..."
    ls -la
    cat package.json
    npm ls --depth=0
        总结
关键要点
- 渐进式采用:从简单的 CI 开始,逐步添加 CD 功能
 - 安全第一:始终遵循安全最佳实践,保护敏感信息
 - 性能优化:合理使用缓存和并行执行提高效率
 - 监控和反馈:建立完善的监控和通知机制
 - 文档化:维护清晰的工作流文档和最佳实践
 
最佳实践总结
✅ 推荐做法
- 使用语义化的工作流和作业名称
 - 合理设置触发条件,避免不必要的执行
 - 充分利用缓存机制提高构建速度
 - 实施全面的测试策略(单元测试、集成测试、E2E 测试)
 - 使用环境保护和审批流程
 - 定期更新 Actions 版本
 - 监控工作流执行时间和成本
 
❌ 避免的做法
- 在日志中暴露敏感信息
 - 使用过于宽泛的权限
 - 忽略安全扫描和依赖更新
 - 创建过于复杂的单一工作流
 - 缺乏错误处理和重试机制
 - 不使用环境变量管理配置
 
进阶学习路径
- 
基础阶段
- 掌握 YAML 语法和 GitHub Actions 基本概念
 - 创建简单的 CI 工作流
 - 学习常用的官方 Actions
 
 - 
中级阶段
- 实现完整的 CI/CD 流水线
 - 掌握矩阵构建和并行执行
 - 学习 Docker 集成和容器化部署
 
 - 
高级阶段
- 创建自定义 Actions
 - 实现复杂的部署策略(蓝绿部署、金丝雀发布)
 - 集成监控和可观测性工具
 
 
参考资料
官方文档
社区资源
工具和服务
博客和教程
结语
GitHub Actions 为现代软件开发提供了强大而灵活的 CI/CD 解决方案。通过本指南的学习和实践,您应该能够:
- 理解 CI/CD 的核心概念和价值
 - 掌握 GitHub Actions 的基本使用方法
 - 为不同类型的项目设计合适的工作流
 - 实施安全和性能最佳实践
 - 解决常见的构建和部署问题
 
记住,CI/CD 是一个持续改进的过程。随着项目的发展和团队的成长,您的工作流也应该不断优化和完善。保持学习新的工具和实践,关注社区的最新发展,这将帮助您构建更加高效和可靠的软件交付流水线。
Happy Coding! 🚀
name: playwright-report
path: playwright-report/
部署
deploy:
name: 部署
runs-on: ubuntu-latest
needs: [frontend, backend, e2e]
if: github.ref == 'refs/heads/main' && success()
steps:
- name: Download frontend build
  uses: actions/download-artifact@v3
  with:
    name: frontend-build
    path: frontend-dist/
- name: Deploy frontend to CDN
  run: |
    # 部署前端到 CDN
    echo "Deploying frontend to CDN..."
- name: Deploy backend to Kubernetes
  run: |
    # 部署后端到 K8s
    echo "Deploying backend to Kubernetes..."
### 模板 4:Python Django 项目
```yaml
name: Django CI/CD
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
env:
  PYTHON_VERSION: '3.11'
jobs:
  test:
    name: 测试
    runs-on: ubuntu-latest
    
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: django_test
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Python
      uses: actions/setup-python@v4
      with:
        python-version: ${{ env.PYTHON_VERSION }}
        cache: 'pip'
    
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
        pip install -r requirements-dev.txt
    
    - name: Run migrations
      env:
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/django_test
      run: python manage.py migrate
    
    - name: Run tests
      env:
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/django_test
      run: |
        coverage run --source='.' manage.py test
        coverage xml
    
    - name: Upload coverage
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage.xml
  deploy:
    name: 部署到 Heroku
    runs-on: ubuntu-latest
    needs: test
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Deploy to Heroku
      uses: akhileshns/heroku-deploy@v3.12.14
      with:
        heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
        heroku_app_name: "your-django-app"
        heroku_email: "your-email@example.com"
        总结
GitHub Actions 作为现代 CI/CD 的重要工具,为开发团队提供了强大而灵活的自动化能力。通过本指南,您应该能够:
🎯 核心收获
- 理解 CI/CD 概念:掌握持续集成和持续部署的基本原理
 - 熟练使用 GitHub Actions:了解工作流、作业、步骤等核心概念
 - 实践最佳实践:应用安全性、性能优化和错误处理策略
 - 解决常见问题:快速诊断和解决工作流中的典型问题
 
📈 进阶建议
- 持续学习:关注 GitHub Actions 的新功能和社区最佳实践
 - 监控优化:定期审查工作流性能,优化执行时间和资源使用
 - 安全第一:始终遵循安全最佳实践,保护敏感信息
 - 团队协作:建立团队 CI/CD 规范,确保一致性
 
🔗 有用资源
🚀 下一步行动
- 选择适合您项目的模板开始实践
 - 根据项目需求定制工作流
 - 逐步添加高级功能和优化
 - 与团队分享经验和最佳实践
 
记住,优秀的 CI/CD 流程不是一蹴而就的,需要持续改进和优化。从简单开始,逐步完善,最终构建出适合您团队的完美自动化流程。
本指南将持续更新,以反映 GitHub Actions 的最新功能和社区最佳实践。如有问题或建议,欢迎提出反馈。
name: playwright-report
path: playwright-report/
部署
deploy:
name: 部署应用
runs-on: ubuntu-latest
needs: [frontend-ci, backend-ci, integration-test]
if: github.ref == 'refs/heads/main' && success()
steps:
- uses: actions/checkout@v4
- name: Download frontend build
  uses: actions/download-artifact@v3
  with:
    name: frontend-build
    path: frontend/dist/
- name: Deploy to AWS
  env:
    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    AWS_REGION: us-east-1
  run: |
    # 部署前端到 S3
    aws s3 sync frontend/dist/ s3://your-frontend-bucket --delete
    
    # 部署后端到 ECS
    aws ecs update-service --cluster your-cluster --service your-service --force-new-deployment
---
## 高级功能和最佳实践
### 矩阵构建策略
```yaml
name: Matrix Build Strategy
on: [push, pull_request]
jobs:
  test:
    name: Test on ${{ matrix.os }} with Node ${{ matrix.node-version }}
    runs-on: ${{ matrix.os }}
    
    strategy:
      # 失败时不停止其他任务
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [16, 18, 20]
        # 排除特定组合
        exclude:
          - os: windows-latest
            node-version: 16
        # 包含特定组合
        include:
          - os: ubuntu-latest
            node-version: 21
            experimental: true
    
    # 允许实验性构建失败
    continue-on-error: ${{ matrix.experimental || false }}
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v4
      with:
        node-version: ${{ matrix.node-version }}
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run tests
      run: npm test
        条件执行和依赖管理
            
            
              yaml
              
              
            
          
          name: Conditional Execution
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
jobs:
  # 基础检查
  lint:
    name: 代码检查
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Run linting
      run: npm run lint
  # 单元测试
  unit-test:
    name: 单元测试
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Run unit tests
      run: npm run test:unit
  # 集成测试(依赖于前面的任务)
  integration-test:
    name: 集成测试
    runs-on: ubuntu-latest
    needs: [lint, unit-test]
    steps:
    - uses: actions/checkout@v4
    - name: Run integration tests
      run: npm run test:integration
  # 构建(只在主分支)
  build:
    name: 构建应用
    runs-on: ubuntu-latest
    needs: [lint, unit-test]
    if: github.ref == 'refs/heads/main'
    steps:
    - uses: actions/checkout@v4
    - name: Build application
      run: npm run build
  # 部署(只在构建成功后)
  deploy:
    name: 部署应用
    runs-on: ubuntu-latest
    needs: [build, integration-test]
    if: success() && github.ref == 'refs/heads/main'
    environment: production
    steps:
    - name: Deploy to production
      run: echo "Deploying to production..."
  # 通知(总是执行)
  notify:
    name: 发送通知
    runs-on: ubuntu-latest
    needs: [deploy]
    if: always()
    steps:
    - name: Send notification
      env:
        STATUS: ${{ needs.deploy.result }}
      run: |
        if [ "$STATUS" == "success" ]; then
          echo "部署成功!"
        else
          echo "部署失败!"
        fi
        缓存策略优化
            
            
              yaml
              
              
            
          
          name: Advanced Caching
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    # Node.js 依赖缓存
    - name: Setup Node.js with cache
      uses: actions/setup-node@v4
      with:
        node-version: '18'
        cache: 'npm'
    
    # 自定义缓存
    - name: Cache node modules
      uses: actions/cache@v3
      with:
        path: |
          ~/.npm
          node_modules
          */*/node_modules
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.os }}-node-
    
    # 构建缓存
    - name: Cache build output
      uses: actions/cache@v3
      with:
        path: |
          .next/cache
          dist
          build
        key: ${{ runner.os }}-build-${{ github.sha }}
        restore-keys: |
          ${{ runner.os }}-build-
    
    # Docker 层缓存
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3
    
    - name: Build Docker image with cache
      uses: docker/build-push-action@v5
      with:
        context: .
        cache-from: type=gha
        cache-to: type=gha,mode=max
        tags: myapp:latest
        并行任务和工作流复用
            
            
              yaml
              
              
            
          
          # .github/workflows/reusable-test.yml
name: Reusable Test Workflow
on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string
      working-directory:
        required: false
        type: string
        default: '.'
    secrets:
      NPM_TOKEN:
        required: false
jobs:
  test:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ${{ inputs.working-directory }}
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
        registry-url: 'https://registry.npmjs.org'
    
    - name: Install dependencies
      env:
        NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
      run: npm ci
    
    - name: Run tests
      run: npm test
        
            
            
              yaml
              
              
            
          
          # .github/workflows/main.yml
name: Main Workflow
on: [push, pull_request]
jobs:
  # 使用可复用工作流
  test-frontend:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: '18'
      working-directory: './frontend'
    secrets:
      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
  
  test-backend:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: '18'
      working-directory: './backend'
  
  # 并行执行多个任务
  parallel-tasks:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Run parallel commands
      run: |
        # 后台运行多个命令
        npm run lint &
        npm run type-check &
        npm run test:unit &
        
        # 等待所有后台任务完成
        wait
        安全性和性能优化
Secrets 管理最佳实践
1. 环境级别的 Secrets
            
            
              yaml
              
              
            
          
          name: Secure Deployment
on:
  push:
    branches: [ main ]
jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging
    steps:
    - name: Deploy to staging
      env:
        # 环境特定的 secrets
        API_KEY: ${{ secrets.STAGING_API_KEY }}
        DATABASE_URL: ${{ secrets.STAGING_DATABASE_URL }}
      run: |
        echo "Deploying to staging with secure credentials"
  deploy-production:
    runs-on: ubuntu-latest
    environment: production
    # 需要手动批准
    steps:
    - name: Deploy to production
      env:
        API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
        DATABASE_URL: ${{ secrets.PRODUCTION_DATABASE_URL }}
      run: |
        echo "Deploying to production with secure credentials"
        2. 动态 Secrets 引用
            
            
              yaml
              
              
            
          
          jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        environment: [staging, production]
    
    steps:
    - name: Deploy to ${{ matrix.environment }}
      env:
        # 动态引用不同环境的 secrets
        API_KEY: ${{ secrets[format('{0}_API_KEY', matrix.environment)] }}
        DB_URL: ${{ secrets[format('{0}_DATABASE_URL', matrix.environment)] }}
      run: |
        echo "Deploying to ${{ matrix.environment }}"
        权限最小化原则
            
            
              yaml
              
              
            
          
          name: Minimal Permissions
on: [push, pull_request]
# 全局权限设置
permissions:
  contents: read
jobs:
  test:
    runs-on: ubuntu-latest
    # 作业级别权限
    permissions:
      contents: read
      checks: write
    steps:
    - uses: actions/checkout@v4
    - name: Run tests
      run: npm test
  publish:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    permissions:
      contents: read
      packages: write
    steps:
    - uses: actions/checkout@v4
    - name: Publish package
      run: npm publish
        安全扫描集成
            
            
              yaml
              
              
            
          
          name: Security Scanning
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  schedule:
    - cron: '0 2 * * 1'  # 每周一凌晨2点
jobs:
  # 依赖漏洞扫描
  dependency-scan:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Run npm audit
      run: npm audit --audit-level moderate
    
    - name: Snyk security scan
      uses: snyk/actions/node@master
      env:
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      with:
        args: --severity-threshold=high
        command: test
  # 代码安全扫描
  code-scan:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
    steps:
    - uses: actions/checkout@v4
    
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v2
      with:
        languages: javascript, typescript
    
    - name: Autobuild
      uses: github/codeql-action/autobuild@v2
    
    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v2
  # Docker 镜像安全扫描
  docker-scan:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Build Docker image
      run: docker build -t myapp:latest .
    
    - name: Scan Docker image
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: 'myapp:latest'
        format: 'sarif'
        output: 'trivy-results.sarif'
    
    - name: Upload Trivy scan results
      uses: github/codeql-action/upload-sarif@v2
      with:
        sarif_file: 'trivy-results.sarif'
        性能优化策略
1. 并行化优化
            
            
              yaml
              
              
            
          
          name: Performance Optimized
on: [push, pull_request]
jobs:
  # 快速反馈任务
  quick-checks:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Quick lint check
      run: npm run lint:fast
    - name: Type check
      run: npm run type-check
  # 并行测试
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        shard: [1, 2, 3, 4]
    steps:
    - uses: actions/checkout@v4
    - name: Run test shard ${{ matrix.shard }}
      run: npm run test -- --shard=${{ matrix.shard }}/4
  # 并行构建
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        target: [web, mobile, desktop]
    steps:
    - uses: actions/checkout@v4
    - name: Build ${{ matrix.target }}
      run: npm run build:${{ matrix.target }}
        2. 智能缓存策略
            
            
              yaml
              
              
            
          
          name: Smart Caching
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    # 分层缓存策略
    - name: Cache dependencies
      uses: actions/cache@v3
      with:
        path: node_modules
        key: deps-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
        restore-keys: deps-${{ runner.os }}-
    
    - name: Cache build artifacts
      uses: actions/cache@v3
      with:
        path: |
          .next/cache
          dist
        key: build-${{ runner.os }}-${{ github.sha }}
        restore-keys: |
          build-${{ runner.os }}-${{ github.ref_name }}-
          build-${{ runner.os }}-
    
    # 条件性安装
    - name: Install dependencies
      if: steps.cache-deps.outputs.cache-hit != 'true'
      run: npm ci
    
    # 增量构建
    - name: Build application
      run: |
        if [ -d "dist" ]; then
          echo "Using incremental build"
          npm run build:incremental
        else
          echo "Full build required"
          npm run build
        fi
        常见问题和解决方案
问题 1:工作流执行时间过长
症状:
- 工作流执行超过 30 分钟
 - 频繁超时失败
 - 资源使用效率低
 
解决方案:
            
            
              yaml
              
              
            
          
          name: Optimized Workflow
on: [push, pull_request]
jobs:
  # 1. 使用并行执行
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        shard: [1, 2, 3, 4]
    steps:
    - uses: actions/checkout@v4
    - name: Run tests in parallel
      run: npm run test -- --shard=${{ matrix.shard }}/4
  # 2. 优化缓存策略
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Restore cache
      uses: actions/cache@v3
      with:
        path: |
          node_modules
          ~/.npm
        key: ${{ runner.os }}-${{ hashFiles('package-lock.json') }}
    
    # 3. 使用更快的包管理器
    - name: Setup pnpm
      uses: pnpm/action-setup@v2
      with:
        version: 8
    
    - name: Install dependencies
      run: pnpm install --frozen-lockfile
  # 4. 条件执行
  deploy:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    steps:
    - name: Deploy only when necessary
      run: echo "Deploying..."
        问题 2:Secrets 管理混乱
症状:
- Secrets 命名不规范
 - 环境间 Secrets 混用
 - 安全性问题
 
解决方案:
            
            
              yaml
              
              
            
          
          name: Proper Secrets Management
on: [push]
jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        environment: [staging, production]
    
    environment: ${{ matrix.environment }}
    
    steps:
    - name: Deploy with proper secrets
      env:
        # 使用环境特定的 secrets
        API_KEY: ${{ secrets.API_KEY }}
        DATABASE_URL: ${{ secrets.DATABASE_URL }}
        # 或者使用动态引用
        DYNAMIC_SECRET: ${{ secrets[format('{0}_SECRET', matrix.environment)] }}
      run: |
        echo "Deploying to ${{ matrix.environment }}"
        echo "API Key length: ${#API_KEY}"
        Secrets 命名规范:
# 环境特定
STAGING_API_KEY
PRODUCTION_API_KEY
# 服务特定
GITHUB_TOKEN
DOCKER_REGISTRY_TOKEN
AWS_ACCESS_KEY_ID
# 功能特定
CODECOV_TOKEN
SNYK_TOKEN
        问题 3:依赖冲突和版本问题
症状:
- 不同环境构建结果不一致
 - 依赖版本冲突
 - 构建失败
 
解决方案:
            
            
              yaml
              
              
            
          
          name: Dependency Management
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    # 1. 锁定 Node.js 版本
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version-file: '.nvmrc'  # 使用项目指定版本
        cache: 'npm'
    
    # 2. 使用精确的依赖安装
    - name: Install dependencies
      run: |
        # 使用 ci 而不是 install
        npm ci
        # 验证依赖完整性
        npm audit --audit-level moderate
    
    # 3. 版本一致性检查
    - name: Check dependency versions
      run: |
        npm ls --depth=0
        npm outdated || true
    
    # 4. 多版本测试
  multi-version-test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [16, 18, 20]
    
    steps:
    - uses: actions/checkout@v4
    - name: Setup Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v4
      with:
        node-version: ${{ matrix.node-version }}
    
    - name: Test compatibility
      run: |
        npm ci
        npm test
        问题 4:环境变量和配置管理
症状:
- 环境变量混乱
 - 配置在不同环境不一致
 - 敏感信息泄露
 
解决方案:
            
            
              yaml
              
              
            
          
          name: Environment Management
on: [push]
env:
  # 全局环境变量
  NODE_ENV: production
  LOG_LEVEL: info
jobs:
  deploy:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        environment: [staging, production]
    
    environment: ${{ matrix.environment }}
    
    steps:
    - uses: actions/checkout@v4
    
    # 1. 环境特定配置
    - name: Setup environment config
      run: |
        case "${{ matrix.environment }}" in
          staging)
            echo "API_URL=https://api-staging.example.com" >> $GITHUB_ENV
            echo "DEBUG=true" >> $GITHUB_ENV
            ;;
          production)
            echo "API_URL=https://api.example.com" >> $GITHUB_ENV
            echo "DEBUG=false" >> $GITHUB_ENV
            ;;
        esac
    
    # 2. 配置验证
    - name: Validate configuration
      env:
        DATABASE_URL: ${{ secrets.DATABASE_URL }}
      run: |
        # 检查必需的环境变量
        required_vars=("API_URL" "DATABASE_URL" "NODE_ENV")
        for var in "${required_vars[@]}"; do
          if [ -z "${!var}" ]; then
            echo "Error: $var is not set"
            exit 1
          fi
        done
    
    # 3. 安全的配置文件生成
    - name: Generate config file
      env:
        API_KEY: ${{ secrets.API_KEY }}
      run: |
        cat > config.json << EOF
        {
          "environment": "${{ matrix.environment }}",
          "apiUrl": "$API_URL",
          "debug": $DEBUG,
          "version": "${{ github.sha }}"
        }
        EOF
        
        # 不在日志中显示敏感信息
        echo "Config file generated successfully"
        问题 5:Docker 构建优化
症状:
- Docker 构建时间过长
 - 镜像体积过大
 - 缓存效率低
 
解决方案:
            
            
              yaml
              
              
            
          
          name: Optimized Docker Build
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    # 1. 设置 Docker Buildx
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3
    
    # 2. 登录到镜像仓库
    - name: Login to registry
      uses: docker/login-action@v3
      with:
        registry: ghcr.io
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}
    
    # 3. 优化的多阶段构建
    - name: Build and push
      uses: docker/build-push-action@v5
      with:
        context: .
        file: ./Dockerfile.optimized
        platforms: linux/amd64,linux/arm64
        push: true
        tags: |
          ghcr.io/${{ github.repository }}:latest
          ghcr.io/${{ github.repository }}:${{ github.sha }}
        # 使用 GitHub Actions 缓存
        cache-from: type=gha
        cache-to: type=gha,mode=max
        # 构建参数
        build-args: |
          NODE_VERSION=18
          BUILD_DATE=${{ github.event.head_commit.timestamp }}
          VCS_REF=${{ github.sha }}
        优化的 Dockerfile:
            
            
              dockerfile
              
              
            
          
          # Dockerfile.optimized
FROM node:18-alpine AS base
WORKDIR /app
COPY package*.json ./
FROM base AS deps
RUN npm ci --only=production && npm cache clean --force
FROM base AS build
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine AS runtime
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY package*.json ./
EXPOSE 3000
CMD ["npm", "start"]
        实用配置模板
模板 1:React + TypeScript 项目
            
            
              yaml
              
              
            
          
          name: React TypeScript CI/CD
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
env:
  NODE_VERSION: '18'
  CACHE_KEY_PREFIX: 'react-app'
jobs:
  # 代码质量检查
  quality:
    name: 代码质量检查
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout
      uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ env.NODE_VERSION }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Type check
      run: npm run type-check
    
    - name: Lint
      run: npm run lint
    
    - name: Format check
      run: npm run format:check
    
    - name: Unit tests
      run: npm run test:coverage
    
    - name: Upload coverage
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage/lcov.info
  # 构建
  build:
    name: 构建应用
    runs-on: ubuntu-latest
    needs: quality
    
    steps:
    - name: Checkout
      uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ env.NODE_VERSION }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Build
      run: npm run build
    
    - name: Upload build artifacts
      uses: actions/upload-artifact@v3
      with:
        name: build-files
        path: build/
        retention-days: 7
  # 部署
  deploy:
    name: 部署到 Vercel
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/main'
    
    steps:
    - name: Checkout
      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'
        模板 2:Node.js API 项目
            
            
              yaml
              
              
            
          
          name: Node.js API CI/CD
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
env:
  NODE_VERSION: '18'
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}
jobs:
  # 测试
  test:
    name: 测试
    runs-on: ubuntu-latest
    
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: test_db
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
    
    steps:
    - name: Checkout
      uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ env.NODE_VERSION }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run migrations
      env:
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
      run: npm run db:migrate
    
    - name: Run tests
      env:
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
      run: npm run test:coverage
    
    - name: Upload coverage
      uses: codecov/codecov-action@v3
  # 构建 Docker 镜像
  build:
    name: 构建镜像
    runs-on: ubuntu-latest
    needs: test
    
    steps:
    - name: Checkout
      uses: actions/checkout@v4
    
    - name: Setup Docker Buildx
      uses: docker/setup-buildx-action@v3
    
    - name: Login to registry
      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=ref,event=branch
          type=ref,event=pr
          type=sha
    
    - name: Build and push
      uses: docker/build-push-action@v5
      with:
        context: .
        push: true
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}
        cache-from: type=gha
        cache-to: type=gha,mode=max
  # 部署
  deploy:
    name: 部署
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/main'
    environment: production
    
    steps:
    - name: Deploy to server
      uses: appleboy/ssh-action@v1.0.0
      with:
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        key: ${{ secrets.SSH_KEY }}
        script: |
          docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main
          docker stop api || true
          docker rm api || true
          docker run -d \
            --name api \
            --restart unless-stopped \
            -p 3000:3000 \
            -e DATABASE_URL=${{ secrets.DATABASE_URL }} \
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main
        本指南涵盖了 GitHub Actions CI/CD 的核心概念、实践案例和最佳实践。通过学习和应用这些知识,您将能够构建高效、安全、可靠的自动化部署流程。