CI/CD管道Skill ci-cd-pipeline

CI/CD 管道技能用于设置和维护持续集成与持续部署流程,自动化软件构建、测试和部署。它涉及使用GitHub Actions、GitLab CI、Jenkins等工具来提升开发效率和软件交付质量。关键词:CI/CD, 自动化, DevOps, 测试自动化, 部署策略, 构建管道, 持续集成, 持续部署。

CI/CD 0 次安装 0 次浏览 更新于 3/18/2026

名称: ci-cd-pipeline 描述: 使用GitHub Actions、GitLab CI、Jenkins或类似工具设置和维护持续集成和持续部署管道,以自动化测试、构建和部署。在配置自动化构建、设置测试自动化、实现部署自动化、创建发布工作流、管理环境部署、配置构建缓存、实现蓝绿部署、设置回滚策略或自动化整个软件交付管道时使用。

CI/CD 管道 - 自动化构建、测试和部署

包管理器检测

重要:在创建CI/CD配置之前,通过检查锁文件检测项目的包管理器,并相应地调整所有命令。

检测顺序(第一个匹配项为准):

  1. bun.lockb → 使用 bun
  2. pnpm-lock.yaml → 使用 pnpm
  3. yarn.lock → 使用 yarn
  4. package-lock.json → 使用 npm

命令映射 - 将本技能中的示例调整为使用检测到的包管理器:

操作 npm yarn pnpm bun
安装(CI) npm ci yarn install --frozen-lockfile pnpm install --frozen-lockfile bun install --frozen-lockfile
运行脚本 npm run <script> yarn <script> pnpm <script> bun run <script>
执行二进制 npx <cmd> yarn dlx <cmd> pnpm dlx <cmd> bunx <cmd>
缓存键 package-lock.json yarn.lock pnpm-lock.yaml bun.lockb
缓存路径 ~/.npm ~/.yarn/cache ~/.pnpm-store ~/.bun/install/cache

注意:以下示例默认使用npm。实施时,请替换为适用于您检测到的包管理器的相应命令。


何时使用此技能

  • 设置GitHub Actions或GitLab CI工作流
  • 每次提交时自动执行测试
  • 实现自动化构建和部署
  • 创建发布和版本控制工作流
  • 管理暂存和生产部署
  • 配置构建缓存以加速管道
  • 实现蓝绿或金丝雀部署
  • 设置失败时自动回滚
  • 在CI中运行代码检查和类型检查
  • 在管道中自动化数据库迁移
  • 在CI中实现安全扫描
  • 创建部署审批工作流

何时使用此技能

  • 设置持续集成、自动化部署、配置构建管道或实现DevOps工作流。
  • 处理相关任务或功能时
  • 在需要此专业知识的开发期间

使用时机:设置持续集成、自动化部署、配置构建管道或实现DevOps工作流。

核心原则

  1. 自动化一切 - 手动步骤容易出错
  2. 快速失败 - 在管道早期发现问题
  3. 部署前测试 - 切勿部署未测试的代码
  4. 可重复构建 - 相同输入 = 相同输出
  5. 零停机部署 - 用户不受影响

GitHub Actions

1. 基本CI工作流

# .github/workflows/ci.yml
名称: CI

触发条件:
  push:
    分支: [main, develop]
  pull_request:
    分支: [main]

任务:
  测试:
    运行环境: ubuntu-latest
    
    步骤:
      - 使用: actions/checkout@v4
      
      - 名称: 设置Node.js
        使用: actions/setup-node@v4
        参数:
          node-version: '20'
          cache: 'npm'
      
      - 名称: 安装依赖
        运行: npm ci
      
      - 名称: 运行代码检查
        运行: npm run lint
      
      - 名称: 运行类型检查
        运行: npm run typecheck
      
      - 名称: 运行测试
        运行: npm test -- --coverage
      
      - 名称: 上传覆盖率
        使用: codecov/codecov-action@v3
        参数:
          文件: ./coverage/lcov.info

2. 矩阵测试

# 跨多个版本测试
任务:
  测试:
    运行环境: ${{ matrix.os }}
    策略:
      矩阵:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [18, 20, 21]
    
    步骤:
      - 使用: actions/checkout@v4
      
      - 名称: 设置Node.js ${{ matrix.node-version }}
        使用: actions/setup-node@v4
        参数:
          node-version: ${{ matrix.node-version }}
      
      - 运行: npm ci
      - 运行: npm test

3. 部署工作流

# .github/workflows/deploy.yml
名称: 部署

触发条件:
  push:
    分支: [main]

任务:
  部署:
    运行环境: ubuntu-latest
    
    步骤:
      - 使用: actions/checkout@v4
      
      - 名称: 设置Node.js
        使用: actions/setup-node@v4
        参数:
          node-version: '20'
      
      - 运行: npm ci
      - 运行: npm run build
      
      - 名称: 部署到Vercel
        使用: amondnet/vercel-action@v25
        参数:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: '--prod'

4. Docker构建与推送

名称: Docker

触发条件:
  push:
    标签: ['v*']

任务:
  构建:
    运行环境: ubuntu-latest
    
    步骤:
      - 使用: actions/checkout@v4
      
      - 名称: 设置Docker Buildx
        使用: docker/setup-buildx-action@v3
      
      - 名称: 登录到Docker Hub
        使用: docker/login-action@v3
        参数:
          用户名: ${{ secrets.DOCKER_USERNAME }}
          密码: ${{ secrets.DOCKER_PASSWORD }}
      
      - 名称: 提取元数据
        id: meta
        使用: docker/metadata-action@v5
        参数:
          镜像: myorg/myapp
          标签: |
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
      
      - 名称: 构建和推送
        使用: docker/build-push-action@v5
        参数:
          context: .
          push: true
          标签: ${{ steps.meta.outputs.tags }}
          cache-from: type=registry,ref=myorg/myapp:buildcache
          cache-to: type=registry,ref=myorg/myapp:buildcache,mode=max

5. 端到端测试

名称: 端到端测试

触发条件:
  pull_request:

任务:
  端到端测试:
    运行环境: ubuntu-latest
    
    服务:
      postgres:
        镜像: postgres:15
        环境变量:
          POSTGRES_PASSWORD: postgres
        选项: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    
    步骤:
      - 使用: actions/checkout@v4
      
      - 名称: 设置Node.js
        使用: actions/setup-node@v4
        参数:
          node-version: '20'
      
      - 运行: npm ci
      
      - 名称: 安装Playwright
        运行: npx playwright install --with-deps
      
      - 名称: 运行端到端测试
        运行: npm run test:e2e
        环境变量:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
      
      - 名称: 上传测试结果
        if: always()
        使用: actions/upload-artifact@v3
        参数:
          名称: playwright-report
          路径: playwright-report/

GitLab CI

# .gitlab-ci.yml
阶段:
  - 代码检查
  - 测试
  - 构建
  - 部署

变量:
  NODE_VERSION: "20"

代码检查:
  阶段: 代码检查
  镜像: node:${NODE_VERSION}
  脚本:
    - npm ci
    - npm run lint
    - npm run typecheck

测试:
  阶段: 测试
  镜像: node:${NODE_VERSION}
  服务:
    - postgres:15
  变量:
    POSTGRES_DB: test
    POSTGRES_USER: postgres
    POSTGRES_PASSWORD: postgres
  脚本:
    - npm ci
    - npm test -- --coverage
  覆盖率: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
  工件:
    报告:
      覆盖率报告:
        coverage_format: cobertura
        路径: coverage/cobertura-coverage.xml

构建:
  阶段: 构建
  镜像: node:${NODE_VERSION}
  脚本:
    - npm ci
    - npm run build
  工件:
    路径:
      - dist/

部署生产:
  阶段: 部署
  镜像: node:${NODE_VERSION}
  脚本:
    - npm install -g vercel
    - vercel --prod --token=$VERCEL_TOKEN
  only:
    - main

部署策略

1. 蓝绿部署

# 先部署到暂存槽
- 名称: 部署到暂存
  运行: |
    az webapp deployment slot create \
      --name myapp \
      --resource-group mygroup \
      --slot staging
    
    az webapp deployment source config-zip \
      --name myapp \
      --resource-group mygroup \
      --slot staging \
      --src ./dist.zip

# 对暂存环境运行冒烟测试
- 名称: 冒烟测试
  运行: npm run test:smoke -- --url=https://myapp-staging.azurewebsites.net

# 将暂存切换到生产(即时切换)
- 名称: 切换到生产
  运行: |
    az webapp deployment slot swap \
      --name myapp \
      --resource-group mygroup \
      --slot staging \
      --target-slot production

2. 金丝雀部署

# 先部署到10%的服务器
- 名称: 部署金丝雀
  运行: |
    kubectl set image deployment/myapp \
      myapp=myapp:${{ github.sha }} \
      --record
    
    kubectl patch deployment myapp \
      -p '{"spec":{"replicas":1}}'

# 监控10分钟
- 名称: 监控金丝雀
  运行: |
    sleep 600
    ERROR_RATE=$(kubectl logs -l app=myapp --tail=1000 | grep ERROR | wc -l)
    if [ $ERROR_RATE -gt 10 ]; then
      echo "高错误率,正在回滚"
      kubectl rollout undo deployment/myapp
      exit 1
    fi

# 如果健康,扩展到100%
- 名称: 完整部署
  运行: kubectl scale deployment myapp --replicas=5

3. 滚动部署

# Kubernetes滚动更新(零停机)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1        # 更新期间最多1个额外pod
      maxUnavailable: 1  # 任何时候最多1个pod不可用
  template:
    spec:
      containers:
      - name: myapp
        image: myapp:latest
        readinessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5

管道最佳实践

1. 缓存

# 缓存依赖
- 名称: 缓存node模块
  使用: actions/cache@v3
  参数:
    路径: ~/.npm
    键: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

# 缓存构建输出
- 名称: 缓存构建
  使用: actions/cache@v3
  参数:
    路径: .next/cache
    键: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}

2. 密钥管理

# ✅ 将密钥存储在CI/CD平台中
任务:
  部署:
    步骤:
      - 名称: 部署
        环境变量:
          API_KEY: ${{ secrets.API_KEY }}
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
        运行: |
          echo "API_KEY is set: ${API_KEY:+yes}"
          npm run deploy

# ✅ 使用保险库存储敏感数据
- 名称: 导入密钥
  使用: hashicorp/vault-action@v2
  参数:
    url: https://vault.example.com
    token: ${{ secrets.VAULT_TOKEN }}
    secrets: |
      secret/data/prod api_key | API_KEY ;
      secret/data/prod db_url | DATABASE_URL

3. 质量门

任务:
  质量检查:
    运行环境: ubuntu-latest
    步骤:
      - 使用: actions/checkout@v4
      
      - 名称: 运行测试并计算覆盖率
        运行: npm test -- --coverage
      
      - 名称: 检查覆盖率阈值
        运行: |
          COVERAGE=$(cat coverage/coverage-summary.json | jq '.total.lines.pct')
          if (( $(echo "$COVERAGE < 80" | bc -l) )); then
            echo "覆盖率 $COVERAGE% 低于80%"
            exit 1
          fi
      
      - 名称: SonarQube扫描
        使用: sonarsource/sonarcloud-github-action@master
        环境变量:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
      
      - 名称: 检查质量门
        运行: |
          STATUS=$(curl -u $SONAR_TOKEN: \
            "https://sonarcloud.io/api/qualitygates/project_status?projectKey=myproject" \
            | jq -r '.projectStatus.status')
          
          if [ "$STATUS" != "OK" ]; then
            echo "质量门失败"
            exit 1
          fi

4. 通知

任务:
  通知:
    运行环境: ubuntu-latest
    if: always()
    needs: [测试, 构建, 部署]
    步骤:
      - 名称: Slack通知
        使用: 8398a7/action-slack@v3
        参数:
          status: ${{ job.status }}
          text: '部署 ${{ job.status }}'
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}
      
      - 名称: 邮件通知
        if: failure()
        使用: dawidd6/action-send-mail@v3
        参数:
          server_address: smtp.gmail.com
          server_port: 465
          username: ${{ secrets.MAIL_USERNAME }}
          password: ${{ secrets.MAIL_PASSWORD }}
          subject: 'CI/CD 失败: ${{ github.workflow }}'
          body: '${{ github.ref }} 上的构建失败'
          to: team@example.com

CI/CD 检查清单

构建管道:
□ 每次提交自动运行
□ 运行代码检查和类型检查
□ 执行所有测试
□ 生成代码覆盖率报告
□ 构建生产工件
□ 缓存依赖以加速

质量门:
□ 最低代码覆盖率阈值(例如80%)
□ 无关键漏洞(npm audit, Snyk)
□ 代码质量检查(SonarQube)
□ 无代码检查错误
□ 所有测试通过

部署:
□ 自动化部署到暂存环境
□ 生产部署需要手动批准
□ 流量切换前进行健康检查
□ 支持回滚能力
□ 零停机策略(蓝绿、金丝雀、滚动)

安全:
□ 密钥安全存储(不在代码中)
□ 依赖扫描(Dependabot)
□ 容器漏洞扫描
□ SAST/DAST安全扫描
□ 要求签名提交

监控:
□ 构建状态通知(Slack, 邮件)
□ 部署通知
□ 部署后错误率监控
□ 错误时自动回滚
□ 维护审计日志

资源


记住:优秀的CI/CD管道速度快、可靠,让开发人员有信心频繁部署。