Skip to content

预计时间

1 周

学习目标

  • 掌握 GitHub Actions 工作流
  • 实现 Push → Build → Test → Deploy 自动化
  • 理解滚动更新 vs 蓝绿部署

一、没有 CI/CD 的痛

text
手动部署流程:
  1. 本地改代码
  2. npm run build
  3. docker build -t my-app:v1.2.3 .
  4. docker push my-registry/my-app:v1.2.3
  5. SSH 到服务器
  6. docker pull my-registry/my-app:v1.2.3
  7. docker compose down && docker compose up -d
  8. 忘了跑测试 → 线上崩了
  9. 忘了改环境变量 → 连不上数据库
  10. 客户打电话过来 → 回滚 → 不记得上一个版本号

有 CI/CD:
  git push → 自动构建 → 自动测试 → 自动部署 → Slack 通知
  出问题 → 一键回滚

二、GitHub Actions 基础

2.1 工作流文件

yaml
# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]       # main 分支 push 时触发
  pull_request:
    branches: [main]       # PR 到 main 也触发(只跑测试)

env:
  NODE_VERSION: '20'
  REGISTRY: ghcr.io         # GitHub Container Registry
  IMAGE_NAME: ${{ github.repository }}

jobs:
  # ===== Job 1: 测试 =====
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'

      - run: npm ci
      - run: npm run lint
      - run: npm run test

  # ===== Job 2: 构建镜像 =====
  build:
    needs: test              # 等 test 过了才构建
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build Docker image
        run: |
          docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest .
          docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} .

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Push Docker image
        run: docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} --all-tags

  # ===== Job 3: 部署 =====
  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'  # 只有 main 分支才部署
    steps:
      - name: Deploy to server
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SERVER_SSH_KEY }}
          script: |
            cd /app
            docker compose pull
            docker compose up -d --remove-orphans
            docker image prune -f

2.2 关键概念

text
Workflow: 整个自动化流程(.github/workflows/xxx.yml)
Job:      一个独立执行的任务(在独立 VM 上跑)
Step:     Job 中的每个步骤
Action:   可复用的步骤(如 actions/checkout、setup-node)

触发器:
  on: push              → 代码推送到仓库
  on: pull_request      → 创建 PR
  on: schedule          → 定时(cron)
  on: workflow_dispatch → 手动触发

三、环境与密钥管理

yaml
# 密钥在 GitHub → Settings → Secrets and variables → Actions 中配置
# 代码中用 ${{ secrets.XXX }} 引用,不会暴露

# 分环境部署
deploy-staging:
  if: github.ref == 'refs/heads/develop'
  environment: staging
  steps:
    - run: deploy to staging server

deploy-production:
  if: github.ref == 'refs/heads/main'
  environment: production
  steps:
    - run: deploy to production server
text
GitHub Environments:
  可以设置环境专属的 Secrets
  可以设置保护规则(如部署前需要 reviewer 审批)
  production 环境可以设:必须某人 approve 才能部署

四、部署策略

4.1 滚动更新(最常用)

yaml
# docker compose 中
deploy:
  replicas: 3
  update_config:
    parallelism: 1      # 一次更新 1 个
    delay: 10s           # 间隔 10 秒
    order: start-first   # 先启动新的,再停旧的
text
过程:
  1. 启动新容器 v2
  2. 等 v2 健康检查通过
  3. 停掉一个 v1
  4. 重复 → 直到全部替换

优点:服务不中断
缺点:更新过程中新旧版本共存,兼容性要注意

4.2 蓝绿部署

text
蓝环境(当前 v1)在跑 → 部署 v2 到另一个环境(绿)
验证绿环境没问题 → 一键切流量到绿
出问题 → 切回蓝

优点:回滚最快(秒级)
缺点:需要双倍资源

4.3 金丝雀发布

text
v2 先放给 5% 用户 → 观察 → 放给 25% → 观察 → 放给 100%

优点:渐进式验证,影响面小
缺点:需要流量控制基础设施

五、完整 CI/CD Pipeline

text
                    git push (main)

              ┌──── Job: test ──────┐
              │  npm ci             │
              │  npm run lint       │
              │  npm run test       │
              └─────────────────────┘
                         ↓ 通过
              ┌──── Job: build ─────┐
              │  docker build       │
              │  tag: latest + sha  │
              │  push to registry   │
              └─────────────────────┘

              ┌──── Job: deploy ────┐
              │  SSH to server      │
              │  docker pull        │
              │  docker up -d       │
              │  health check       │
              └─────────────────────┘

                    Slack 通知

实践

  1. 创建 .github/workflows/deploy.yml
  2. 在 GitHub 仓库 Settings 中配置 Secrets
  3. 推代码到 main → 观察 Actions 面板
  4. 故意写个失败的测试 → 观察 Pipeline 中断
  5. 设置 environment: production + 审批规则