持续集成 (CI)

概念

持续集成(Continuous Integration,CI)是一种软件开发实践,旨在通过频繁地将代码集成到共享仓库中,并进行自动化构建和测试,从而尽早发现和解决集成问题,提高软件开发效率和质量。

流程

一个典型的 CI/CD 流程包括以下步骤:

  1. 代码提交: 开发人员将代码提交到代码仓库(如 GitHub)。
  2. 触发构建: 代码提交触发 CI 系统(如 GitHub Actions)。
  3. 自动化构建: CI 系统自动构建项目,包括编译、打包等步骤。
  4. 自动化测试: CI 系统自动运行单元测试、集成测试等,确保代码质量。
  5. 代码检查: CI 系统进行代码风格检查和静态代码分析。
  6. 构建结果反馈: CI 系统将构建和测试结果反馈给开发人员。

GitHub Actions

GitHub Actions 是 GitHub 提供的 CI/CD 服务,可以直接在 GitHub 仓库中配置和运行 CI/CD 流程。

核心概念

  • Workflow(工作流): 一个 Workflow 定义了一个自动化流程,包含一个或多个 Jobs。Workflow 配置文件通常位于 .github/workflows 目录下,使用 YAML 格式。
  • Job(任务): 一个 Job 是一组在同一个 runner 上执行的 steps。
  • Step(步骤): 一个 Step 可以是一个 shell 命令,也可以是一个 Action。
  • Action(动作): 一个 Action 是一个可重用的组件,可以执行特定的任务,例如代码检查、构建、测试、部署等。
  • Runner(运行器): 一个 Runner 是一个运行 Job 的服务器。GitHub 提供了托管的 Runner,也可以使用自建的 Runner。
  • Event(事件): 触发 Workflow 运行的事件,例如 pushpull_request 等。

示例 Workflow

name: CI
 
on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]
 
jobs:
  build:
    runs-on: ubuntu-latest
 
    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js 16
        uses: actions/setup-node@v3
        with:
          node-version: 16
      - name: Install dependencies
        run: npm install
      - name: Run tests
        run: npm test
      - name: Build
        run: npm run build

这个 Workflow 定义了一个名为 “CI” 的流程,当 main 分支有代码提交或 Pull Request 时触发。它包含一个名为 “build” 的 Job,在 ubuntu-latest 运行器上执行。Job 包含以下步骤:

  1. 使用 actions/checkout@v3 Action 检出代码。
  2. 使用 actions/setup-node@v3 Action 安装 Node.js 16。
  3. 使用 npm install 命令安装项目依赖。
  4. 使用 npm test 命令运行测试。
  5. 使用 npm run build 命令构建项目。

最佳实践

  • 保持 Workflow 简洁: 将复杂的任务分解为多个小的 Step 或 Action,提高可读性和可维护性。
  • 使用 Action: 尽量使用现有的 Action,避免重复造轮子。
  • 缓存依赖: 使用 actions/cache Action 缓存依赖,加快构建速度。
  • 并行执行 Job: 将独立的 Job 并行执行,缩短构建时间。
  • 使用矩阵构建: 使用矩阵构建在不同的环境或配置下运行测试。
  • 安全地存储密钥: 使用 GitHub Secrets 安全地存储敏感信息,例如 API 密钥、数据库密码等。
  • 监控 Workflow: 监控 Workflow 的运行状态,及时发现和解决问题。
  • 编写测试: 编写充分的单元测试和集成测试,确保代码质量。
  • 代码检查: 使用 ESLint、Prettier 等工具进行代码检查,保持代码风格一致。
  • 及时修复: 一旦发现构建或测试失败,及时修复问题,避免问题积累。

持续部署 (CD)

概念

持续部署(Continuous Deployment,CD)是持续交付的更进一步,它指的是将通过了所有自动化测试的代码更改自动发布到生产环境。这意味着每次代码提交通过 CI 流程后,都会自动部署到生产环境,无需人工干预。

持续交付 vs 持续部署

  • 持续交付(Continuous Delivery): 确保软件可以可靠地发布,但发布需要手动触发。
  • 持续部署(Continuous Deployment): 自动将每个通过测试的代码更改发布到生产环境。

流程

一个典型的持续部署流程包括以下步骤:

  1. 代码提交: 开发人员将代码提交到代码仓库(如 GitHub)。
  2. 触发 CI/CD: 代码提交触发 CI/CD 系统(如 GitHub Actions)。
  3. 自动化构建: CI/CD 系统自动构建项目,包括编译、打包等步骤。
  4. 自动化测试: CI/CD 系统自动运行单元测试、集成测试、端到端测试等,确保代码质量。
  5. 代码检查: CI/CD 系统进行代码风格检查和静态代码分析。
  6. 部署前准备: CI/CD 系统进行部署前的准备工作,例如备份数据库、创建部署目录等。
  7. 部署到生产环境: CI/CD 系统将构建好的代码部署到生产环境。
  8. 自动化测试(生产环境): 在生产环境运行自动化测试,确保部署成功。
  9. 监控: 监控应用程序的性能和错误,及时发现和解决问题。
  10. 回滚(可选): 如果部署失败或出现问题,自动回滚到上一个版本。

部署策略

  • 蓝绿部署(Blue-Green Deployment): 维护两个相同的环境,一个为蓝色环境(当前生产环境),一个为绿色环境(新版本)。将新版本部署到绿色环境,测试通过后,将流量切换到绿色环境,蓝色环境作为备用。
  • 滚动部署(Rolling Deployment): 逐步将新版本部署到生产环境,每次只更新一部分服务器。
  • 金丝雀发布(Canary Release): 将新版本部署到一小部分用户,收集反馈并监控性能,如果一切正常,逐步将新版本推广到所有用户。
  • 特性开关(Feature Flags): 将新特性部署到生产环境,但默认关闭。通过特性开关控制新特性的启用和禁用。

GitHub Actions 实现持续部署

可以使用 GitHub Actions 实现持续部署。以下是一个示例 Workflow:

name: CD
 
on:
  push:
    branches: [ "main" ]
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    needs: build # 依赖于 build job
 
    steps:
      - uses: actions/checkout@v3
      - name: Deploy to production
        run: |
          # 你的部署脚本
          echo "Deploying to production..."
          # 例如:
          # ssh user@your-server "cd /var/www/your-app && git pull && npm install && npm run build && pm2 restart your-app"

这个 Workflow 定义了一个名为 “CD” 的流程,当 main 分支有代码提交时触发。它包含一个名为 “deploy” 的 Job,在 ubuntu-latest 运行器上执行。Job 包含以下步骤:

  1. 使用 actions/checkout@v3 Action 检出代码。
  2. 运行部署脚本,将代码部署到生产环境。

注意: 上述示例只是一个简单的示例,实际的部署脚本需要根据你的具体情况进行编写。

最佳实践

  • 自动化一切: 尽可能自动化所有部署步骤,减少人工干预。
  • 监控: 监控应用程序的性能和错误,及时发现和解决问题。
  • 回滚: 确保可以快速回滚到上一个版本,以应对部署失败或出现问题的情况。
  • 安全: 确保部署过程的安全性,例如使用 SSH 密钥进行身份验证,保护敏感信息。
  • 测试: 在生产环境运行自动化测试,确保部署成功。
  • 小批量发布: 采用小批量发布策略,例如金丝雀发布,降低风险。
  • 文档: 编写详细的部署文档,方便团队成员理解和维护。
  • 基础设施即代码(Infrastructure as Code): 使用代码管理基础设施,例如 Terraform、Ansible 等,提高可维护性和可重复性。