CI/CD 概念详解

1. 什么是 CI/CD?

CI/CD 是现代软件工程中的核心实践,代表:

bash 复制代码
CI  →  Continuous Integration   (持续集成)
CD  →  Continuous Delivery       (持续交付)
     / Continuous Deployment     (持续部署)

2. 核心概念拆解

2.1 CI - 持续集成

核心思想:开发者频繁地将代码合并到主分支,每次合并都自动触发构建和测试

解决的问题:

  • 传统开发中,团队各自开发,最后合并时产生大量冲突("集成地狱")
  • 缺陷发现太晚,修复成本高

包含的环节:

bash 复制代码
代码提交 → 自动构建 → 自动测试 → 结果反馈

2. CD - 持续交付(Continuous Delivery)

在 CI 基础上,确保代码随时可以部署到生产环境

  • 部署动作需要人工触发(手动点击按钮)
  • 保证每个版本都是"可发布状态"

2.3 CD - 持续部署(Continuous Deployment)

在持续交付基础上,通过所有测试后自动部署到生产环境,无需人工干预

bash 复制代码
持续集成 ⊂ 持续交付 ⊂ 持续部署

3. 完整流水线图示

bash 复制代码
┌─────────────────────────────────────────────────────────────────┐
│                         CI/CD Pipeline                          │
├──────────────┬──────────────────────────┬───────────────────────┤
│     CI 阶段   │       CD 交付阶段         │      CD 部署阶段       │
│              │                          │                       │
│  ┌─────────┐ │  ┌──────┐  ┌─────────┐  │  ┌──────────────────┐ │
│  │ 代码提交 │ │  │ 打包  │  │  预发布  │  │  │   自动/手动部署   │ │
│  └────┬────┘ │  │ 镜像  │  │环境测试  │  │  │   到生产环境      │ │
│       │      │  └──┬───┘  └────┬────┘  │  └──────────────────┘ │
│  ┌────▼────┐ │     │           │       │                       │
│  │ 自动构建 │ │     └─────┬─────┘       │                       │
│  └────┬────┘ │           │             │                       │
│       │      │      ┌────▼────┐        │                       │
│  ┌────▼────┐ │      │ 制品仓库 │        │                       │
│  │单元测试  │ │      └─────────┘        │                       │
│  │集成测试  │ │                          │                       │
│  │代码扫描  │ │                          │                       │
│  └─────────┘ │                          │                       │
└──────────────┴──────────────────────────┴───────────────────────┘

4. 实际案例:电商网站的 CI/CD

4.1 场景描述

一个电商团队,10 名开发者,使用 GitHub + GitHub Actions + Docker + AWS

4.2 项目结构

bash 复制代码
ecommerce-app/
├── src/
│   ├── api/
│   └── frontend/
├── tests/
│   ├── unit/
│   └── integration/
├── Dockerfile
├── docker-compose.yml
└── .github/
    └── workflows/
        └── ci-cd.yml          ← 流水线配置文件

4.3 CI/CD 配置文件示例

bash 复制代码
# .github/workflows/ci-cd.yml

name: CI/CD Pipeline

# 触发条件:Push 到任意分支,或 PR 到 main 分支
on:
  push:
    branches: [ "*" ]
  pull_request:
    branches: [ "main" ]

jobs:
  # ============================================
  # 阶段一:CI - 持续集成
  # ============================================
  
  build-and-test:
    name: 🔨 构建与测试
    runs-on: ubuntu-latest
    
    steps:
      # 1. 拉取代码
      - name: 检出代码
        uses: actions/checkout@v3
      
      # 2. 安装依赖
      - name: 安装 Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'
      
      - name: 安装依赖包
        run: npm ci
      
      # 3. 代码质量检查
      - name: ESLint 代码规范检查
        run: npm run lint
      
      # 4. 运行单元测试
      - name: 运行单元测试
        run: npm run test:unit -- --coverage
      
      # 5. 运行集成测试
      - name: 运行集成测试
        run: npm run test:integration
        env:
          DB_URL: ${{ secrets.TEST_DB_URL }}
      
      # 6. 上传测试覆盖率报告
      - name: 上传覆盖率到 Codecov
        uses: codecov/codecov-action@v3
  
  # ============================================
  # 阶段二:安全扫描
  # ============================================
  
  security-scan:
    name: 🔐 安全扫描
    runs-on: ubuntu-latest
    needs: build-and-test      # 依赖上一阶段成功
    
    steps:
      - uses: actions/checkout@v3
      
      # 扫描依赖漏洞
      - name: 依赖安全审计
        run: npm audit --audit-level=high
      
      # SAST 静态代码安全分析
      - name: 代码安全扫描
        uses: github/codeql-action/analyze@v2
  
  # ============================================
  # 阶段三:构建 Docker 镜像
  # ============================================
  
  build-image:
    name: 🐳 构建镜像
    runs-on: ubuntu-latest
    needs: security-scan
    
    steps:
      - uses: actions/checkout@v3
      
      - name: 登录镜像仓库
        uses: docker/login-action@v2
        with:
          registry: registry.example.com
          username: ${{ secrets.REGISTRY_USER }}
          password: ${{ secrets.REGISTRY_PASSWORD }}
      
      - name: 构建并推送 Docker 镜像
        uses: docker/build-push-action@v4
        with:
          push: true
          # 用 git commit hash 作为镜像版本标签,确保可追溯
          tags: |
            registry.example.com/ecommerce:latest
            registry.example.com/ecommerce:${{ github.sha }}
  
  # ============================================
  # 阶段四:CD - 部署到预发布环境(自动)
  # ============================================
  
  deploy-staging:
    name: 🚀 部署到预发布环境
    runs-on: ubuntu-latest
    needs: build-image
    environment: staging          # 关联 GitHub 环境配置
    
    steps:
      - name: 部署到 AWS ECS Staging
        run: |
          aws ecs update-service \
            --cluster staging-cluster \
            --service ecommerce-service \
            --force-new-deployment \
            --region us-east-1
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET }}
      
      # 等待部署完成并做冒烟测试
      - name: 冒烟测试
        run: |
          sleep 30
          curl -f https://staging.ecommerce.com/health || exit 1
  
  # ============================================
  # 阶段五:CD - 部署到生产环境(需人工审批)
  # ============================================
  
  deploy-production:
    name: 🎯 部署到生产环境
    runs-on: ubuntu-latest
    needs: deploy-staging
    # 只有 main 分支才部署到生产
    if: github.ref == 'refs/heads/main'
    environment:
      name: production
      url: https://www.ecommerce.com
    # ⚠️ 这里配置了 required reviewers,需要人工审批后才执行
    
    steps:
      - name: 蓝绿部署到 AWS ECS Production
        run: |
          aws ecs update-service \
            --cluster prod-cluster \
            --service ecommerce-service \
            --force-new-deployment
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.PROD_AWS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.PROD_AWS_SECRET }}
      
      # 部署后通知
      - name: 发送 Slack 通知
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "✅ 生产部署成功!版本: ${{ github.sha }}"
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

4.4 完整工作流演示

bash 复制代码
【第一步】开发者提交代码
─────────────────────────────
  张三:修复了购物车 Bug
  
  $ git add .
  $ git commit -m "fix: 修复购物车数量计算错误 #Bug-234"
  $ git push origin feature/fix-cart-bug

  ↓ 自动触发 CI 流水线

【第二步】CI 自动执行(约 8 分钟)
─────────────────────────────
  ✅ 代码检出
  ✅ 依赖安装
  ✅ ESLint 检查通过(0 errors)
  ✅ 单元测试通过(156/156)
  ✅ 集成测试通过(32/32)
  ✅ 测试覆盖率 87%(> 80% 阈值)
  ✅ 安全扫描无高危漏洞
  ✅ Docker 镜像构建成功

  → 张三在 GitHub 看到绿色 ✅,可以发起 PR

【第三步】代码审查 + 合并
─────────────────────────────
  张三发起 PR → main 分支
  李四(Tech Lead)Review 代码 → 批准
  合并到 main 分支

  ↓ 再次触发完整流水线

【第四步】自动部署到预发布环境
─────────────────────────────
  ✅ 所有测试再次通过
  ✅ 镜像推送到仓库(标签: abc123f)
  ✅ 自动部署到 staging.ecommerce.com
  ✅ 冒烟测试通过(/health 返回 200)

  → 通知 QA 团队:预发布环境已更新

【第五步】人工审批 → 生产部署
─────────────────────────────
  QA 在预发布环境验证功能 ✅
  
  产品经理在 GitHub Actions 点击 [Approve]
  
  ✅ 自动部署到生产环境(蓝绿部署)
  ✅ Slack 通知:"购物车 Bug 修复已上线 🎉"

  整个过程:代码提交 → 生产上线 ≈ 1-2 小时

5.总结

bash 复制代码
CI/CD 的本质是:
  将软件交付过程中的 "人工、重复、易错" 的环节
  转变为 "自动化、标准化、可追溯" 的流水线

核心理念:
  • 小步快跑,频繁集成
  • 快速失败,快速反馈  
  • 一切即代码(Pipeline as Code)
  • 构建一次,部署多处

5.1 CI/CD 带来的价值对比

指标 传统开发 CI/CD
发布频率 每月/每季度 每天多次
每次发布范围 大量功能堆积 小而精准
缺陷发现时间 发布前/后 提交后几分钟
修复成本 高(问题积累) 低(即时反馈)
回滚能力 困难 快速(分钟级)
团队信心 发布是噩梦 发布是常态

5.2 常用 CI/CD 工具全景

bash 复制代码
┌─────────────────────────────────────────────────────┐
│                   CI/CD 工具生态                      │
├─────────────────┬───────────────────────────────────┤
│   CI/CD 平台     │  GitHub Actions / GitLab CI       │
│                 │  Jenkins / CircleCI / Travis CI   │
│                 │  Azure DevOps / AWS CodePipeline  │
├─────────────────┼───────────────────────────────────┤
│   容器化          │  Docker / Podman                  │
│   容器编排        │  Kubernetes / AWS ECS             │
├─────────────────┼───────────────────────────────────┤
│   代码质量        │  SonarQube / ESLint / Checkstyle  │
│   安全扫描        │  Snyk / OWASP / CodeQL            │
├─────────────────┼───────────────────────────────────┤
│   制品管理        │  JFrog Artifactory / Nexus        │
│   镜像仓库        │  Docker Hub / ECR / Harbor        │
├─────────────────┼───────────────────────────────────┤
│   监控告警        │  Prometheus + Grafana             │
│   日志           │  ELK Stack / Datadog              │
└─────────────────┴───────────────────────────────────┘

6.附录

6.1 ci-cd.yml 文件关键信息介绍

runs-onusesrun 这三个关键字处于不同的层级,作用完全不同。

bash 复制代码
jobs:
  build-and-test:          
    runs-on: ubuntu-latest   # ← Job 级别:指定运行环境(机器)
    
    steps:
      - name: 安装 Node.js
        uses: actions/setup-node@v3   # ← Step 级别:调用现成的 Action
        
      - name: 安装依赖包
        run: npm ci                   # ← Step 级别:直接执行 Shell 命令

6.1.1 runs-on:指定运行环境

  • Job 级别,回答"在哪台机器上跑?"
bash 复制代码
jobs:
  my-job:
    runs-on: ubuntu-latest   # 使用 GitHub 提供的 Ubuntu 虚拟机

可选的运行环境:

bash 复制代码
runs-on: ubuntu-latest    # Linux(最常用)
runs-on: windows-latest   # Windows
runs-on: macos-latest     # macOS(如 iOS 应用打包)
runs-on: self-hosted      # 你自己公司的服务器

6.1.2 uses:调用现成的 Action 插件

  • Step 级别,回答"用哪个现成工具?"
bash 复制代码
steps:
  - uses: actions/checkout@v3        # 官方:拉取代码
  - uses: actions/setup-node@v3      # 官方:安装 Node.js 环境
  - uses: docker/login-action@v2     # 第三方:登录 Docker
  - uses: codecov/codecov-action@v3  # 第三方:上传测试覆盖率

Action 格式解析

bash 复制代码
actions / setup-node @ v3
   │           │         │
   │           │         └── 版本号(锁定版本,防止自动升级破坏流水线)
   │           └──────────── Action 名称
   └──────────────────────── 作者/组织名(actions = GitHub 官方)

uses 配合 with 传参:

bash 复制代码
- uses: actions/setup-node@v3
  with:                        # ← with 是给这个 Action 传入参数
    node-version: '18'         #   就像调用函数时传参数
    cache: 'npm'

6.1.3 run: 直接执行 Shell 命令

  • Step 级别,回答"执行什么命令?"
bash 复制代码
steps:
  - run: npm ci                          # 单行命令
  
  - run: npm run lint                    # 另一个命令
  
  - run: |                              # 多行命令用 | 符号
      echo "开始部署..."
      aws ecs update-service \
        --cluster prod-cluster \
        --service my-service
      echo "部署完成!"

run 配合 env 注入环境变量

bash 复制代码
- run: npm run test:integration
  env:                                  # ← 注入环境变量给这条命令用
    DB_URL: ${{ secrets.TEST_DB_URL }}  #   从 GitHub Secrets 读取敏感信息

6.1.4 三者对比总结

关键字 层级 作用 类比
runs-on Job 级 指定运行的虚拟机环境 选择在哪台电脑上工作
uses Step 级 调用现成的 Action 插件 调用封装好的函数
run Step 级 直接执行 Shell 命令 在终端手动输入命令

6.1.5 什么时候用 uses,什么时候用 run

bash 复制代码
需要做一件事时,问自己:

有没有现成的 Action?
    │
    ├── 有 → 用 uses(更简单、有维护保障)
    │         例:安装 Node.js、登录 Docker、上传到 S3
    │
    └── 没有 / 逻辑很简单 → 用 run(直接写命令)
                            例:npm ci、自定义脚本、aws cli 命令

适合使用uses的场景:

bash 复制代码
# ✅ 用 uses:安装 Node.js(复杂操作,有现成 Action)
- uses: actions/setup-node@v3
  with:
    node-version: '18'

# ❌ 用 run 自己装(麻烦,容易出错)
- run: |
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
    nvm install 18
    nvm use 18
    # ... 还有一堆配置

适合使用run场景:

bash 复制代码
# ✅ 用 run:执行 npm 命令(简单直接)
- run: npm ci
- run: npm run lint

# ❌ 用 uses 反而奇怪(没必要封装这么简单的命令)
- uses: someone/npm-ci-action@v1   # 没有必要
相关推荐
puamac2 小时前
GitLab CI/CD 故障排查手册
ci/cd·gitlab
Bigger4 小时前
实战:搭建 AI Code Review 自动化流水线
前端·ci/cd·自动化运维
wb043072014 小时前
从接单到出餐——从阿明的“手写菜单“到自动化流水线,看 CI/CD 与 DevOps 的完整旅程
ci/cd·架构·自动化·devops
JackSparrow4142 天前
使用Ansible批量管理+更新产品环境服务器配置
运维·服务器·ci/cd·kubernetes·自动化·ansible·sre
smartpi_ai2 天前
CI-73T 裸片方案 MICBIAS 电容 C11 设计:模块与芯片的差异解析
ci/cd
lili00122 天前
AI编程三件套CI集成与质量门禁:从“看起来对“到“证据确凿“
java·人工智能·python·ci/cd·ai编程
隔窗听雨眠3 天前
GitLab CI前端加载慢优化实录
ci/cd·gitlab
jiayong233 天前
MySQL 排序规则冲突问题与 utf8mb4_general_ci 统一方案
android·mysql·ci/cd
若鱼文化创意3 天前
品牌设计CI规划使用后交付偏差先分项核对验收标准
python·ci/cd