CI/CD 流水线

用自动化生产线替代手工操作,让每次发版不再手忙脚乱

前置知识:Git 基本操作 + 基本的命令行使用


阅读指南(初学者必看)

为什么你需要学习 CI/CD?

你一定经历过这些场景:

  • 改了一行代码,手动打包→手动上传→手动重启,结果忘了一步出问题了
  • 上线后发现有个低级 Bug,但这个 Bug 本来可以自动检测出来
  • 凌晨 2 点紧急修复,迷迷糊糊打包出错了

CI/CD 就是让机器替你做这些重复又容易出错的事。 代码推送后自动检测、自动构建、自动部署,不会漏步、不会出错。

学完本章,你能回答:

  • CI 和 CD 分别是什么?有什么区别?
  • 怎么用 GitHub Actions 搭建一条完整的游戏 CI/CD 流水线?
  • 游戏项目的 CI/CD 和普通 Web 项目有什么不同?
  • Git Flow 和 GitHub Flow 怎么选?

本文结构

第一部分:CI/CD 核心概念(建立认知)
第二部分:分支策略(团队协作基础)
第三部分:GitHub Actions 实战(动手搭建)
第四部分:GitLab CI 与 Jenkins(工具选型)
第五部分:游戏项目 CI/CD 的特殊考虑(游戏特有挑战)

一、什么是 CI/CD?

生活类比:CI/CD 就像"汽车工厂的自动化生产线"。

  • CI(持续集成)= 零件自动检测:每个零件上线前自动检查质量
  • CD(持续交付)= 自动组装出厂:检测通过的零件自动组装成整车
没有 CI/CD 时:
1. 开发者写代码
2. 手动运行测试
3. 手动打包
4. 手动上传到服务器
5. 手动重启服务
→ 容易出错、效率低、忘了某步就出问题

有 CI/CD 时:
1. 开发者推送代码到 Git
2. 自动触发流水线
3. 自动运行测试
4. 自动构建
5. 自动部署
→ 全自动,不会漏步
对比项 手动流程 CI/CD 流程
测试 容易忘记 每次自动运行
构建 手动执行命令 自动触发
部署 手动上传+重启 自动部署+健康检查
出错率 高(人为疏漏) 低(流程固定)
回滚 麻烦 一键回滚

二、分支策略

Git Flow(适合大型项目)

使用 main、develop、feature、release、hotfix 多条分支,流程严谨但复杂。

分支 说明
master/main 线上环境!稳定!只能合入,不能直接提交!
develop 开发环境!最新的开发代码!
feature/xxx 功能分支!从 develop 切!开发完合回 develop!
release/xxx 发布分支!从 develop 切!发布前测试!测完合 master+develop!
hotfix/xxx 紧急修复!从 master 切!修完合 master+develop!
# 开发新功能
git checkout develop
git checkout -b feature/add-shop
# ... 开发 ...
git checkout develop
git merge feature/add-shop

# 发布
git checkout develop
git checkout -b release/1.0.0
# ... 测试 ...
git checkout master
git merge release/1.0.0
git tag 1.0.0

GitHub Flow(适合敏捷团队)

只有 main 和 feature 分支,简单直接:

  • 从 main 拉 feature 分支
  • 开发完成后提 PR
  • PR 合并后自动触发 CI/CD 部署

选型建议:10 人以下团队用 GitHub Flow;大型项目用 Git Flow。


三、GitHub Actions 实战

# .github/workflows/game-ci.yml
name: Game CI/CD

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  # 阶段1:代码检查和测试
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Lint
        run: npm run lint
      
      - name: Unit tests
        run: npm run test:unit
      
      - name: Integration tests
        run: npm run test:integration

  # 阶段2:构建
  build:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Build game client
        run: |
          npm ci
          npm run build:prod
      
      - name: Build game server
        run: |
          cd server
          mvn package -DskipTests
      
      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: game-build
          path: |
            dist/
            server/target/*.jar

  # 阶段3:部署
  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - name: Deploy to staging
        run: |
          # 部署到预发布环境
          ssh deploy@staging.example.com << 'EOF'
          cd /opt/game
          docker-compose pull
          docker-compose up -d
          EOF
      
      - name: Run smoke tests
        run: |
          curl -f http://staging.example.com/health || exit 1
      
      - name: Deploy to production
        if: success()
        run: |
          # 灰度发布:先更新 10% 的服务器
          # 确认无异常后全量发布

流水线三阶段解读

阶段 做什么 失败了怎么办
Test Lint + 单元测试 + 集成测试 阻止代码合并,开发者修复后重新推送
Build 构建客户端 + 服务端 + 上传产物 不进入部署阶段,检查构建配置
Deploy 部署到预发布 → 冒烟测试 → 部署到生产 自动回滚到上一版本

缓存与产物

缓存 = 把常用的东西放在手边,加速下次构建

- name: Cache dependencies
  uses: actions/cache@v3
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

产物 = 流水线中间产出的半成品,供后续阶段使用

- name: Upload build artifacts
  uses: actions/upload-artifact@v4
  with:
    name: game-build
    path: dist/

四、GitLab CI 与 Jenkins

GitLab CI 示例

# .gitlab-ci.yml
stages:
  - build
  - test
  - deploy

build:
  stage: build
  image: node:20-alpine
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour

test:
  stage: test
  image: node:20-alpine
  script:
    - npm ci
    - npm run test

deploy:
  stage: deploy
  script:
    - echo "Deploying to production..."
  only:
    - main

工具选型建议

工具 特点 推荐场景
GitHub Actions GitHub 自带,生态丰富 代码在 GitHub 的项目
GitLab CI GitLab 自带,自托管友好 代码在 GitLab 或需要私有化部署
Jenkins 老牌,插件极多 复杂流水线、多项目统一管理

五、游戏项目 CI/CD 的特殊考虑

游戏和普通 Web 项目的区别:

1. 客户端构建
   - Cocos/Laya 构建耗时长(5~15 分钟)
   - 需要构建多平台(Web/微信/Android/iOS)
   - 资源压缩和加密

2. 服务端部署
   - 不能直接停机更新(玩家在线!)
   - 需要优雅停机(等当前战斗结束)
   - 热更新 vs 全量更新

3. 版本兼容
   - 老版本客户端需要兼容新版本服务器
   - 协议版本号管理
   - 强更 vs 非强更策略

4. 回滚
   - 游戏回滚比 Web 复杂(涉及数据迁移)
   - 需要数据库备份和回滚方案

5. 安全扫描
   - 依赖漏洞扫描(Trivy, Snyk)
   - 镜像签名确保可信

游戏 CI/CD 与普通 Web CI/CD 对比

对比项 普通 Web 游戏项目
构建时间 1-3 分钟 5-15 分钟(多平台)
部署方式 直接替换 优雅停机 + 热更新
版本兼容 通常只管最新 新服务器兼容老客户端
回滚难度 简单(切换版本) 复杂(可能涉及数据迁移)
测试重点 功能正确性 功能 + 性能 + 弱网
安全要求 常规 更高(防充值漏洞、物品复制)

自问自答

Q:CI 和 CD 有什么区别? A:CI(持续集成)关注的是"代码合并后自动检测问题"——自动运行测试、Lint 等。CD(持续交付/持续部署)关注的是"检测通过后自动部署到环境"。CI 是 CD 的前提。

Q:GitHub Actions 的流水线在什么时候触发? A:可以在 on 字段配置。常见的触发条件:push(代码推送时)、pull_request(创建 PR 时)、schedule(定时触发)、workflow_dispatch(手动触发)。游戏项目通常在 push 到 main/develop 时自动触发。

Q:游戏服务端为什么不能直接停机更新? A:因为玩家可能正在进行战斗!直接停机会导致玩家战斗中断、数据丢失。需要"优雅停机":先停止接受新连接,等当前战斗结束后再关闭。

Q:什么是灰度发布?为什么游戏需要灰度发布? A:灰度发布是逐步扩大新版本的覆盖范围(1%→5%→10%→100%)。游戏需要灰度发布因为:1)新版本可能有未发现的 Bug,灰度可以控制影响范围;2)游戏涉及真实充值,出问题损失大;3)游戏用户量大,全量出问题影响面太广。

Q:GitHub Actions 和 GitLab CI 选哪个? A:看你代码放在哪。GitHub 项目用 Actions,GitLab 项目用 GitLab CI。两者概念相似,会一个很容易迁移到另一个。


实践任务

  • 任务1:搭建 GitHub Actions 流水线,实现推送代码后自动运行 Lint 和测试
  • 任务2:实现多平台自动构建(Web + 微信小游戏),上传构建产物
  • 任务3:实现自动部署 + 健康检查,部署失败自动回滚
  • 任务4:配置流水线通知(部署成功/失败发钉钉或企业微信消息)
  • 任务5:集成安全扫描(Trivy 扫描 Docker 镜像漏洞)
  • 任务6:编写流水线 README 文档,记录触发条件、阶段说明、常见问题

初学者常见错误

错误1:YAML 缩进错误

问题: YAML 对缩进极其敏感,多空格或少空格都会报错。 解决: 使用编辑器显示空格字符;用在线 YAML 校验工具。

错误2:缓存配置不当

问题: 没有缓存依赖,每次构建都重新下载,耗时很长。 解决: 正确配置 actions/cache,缓存 ~/.npm~/.m2 等目录。

错误3:在代码中提交密钥

问题: 把密码、API Key 直接写在配置文件里提交到仓库。 解决: 使用仓库 Secrets(GitHub Settings → Secrets and variables → Actions)。

错误4:流水线没有失败通知

问题: 流水线失败了但没人知道,问题被掩盖。 解决: 配置通知渠道(钉钉/企业微信/邮件),失败时立即通知。


与其他章节的关联

本章内容 关联章节 关联点
Docker 构建 第02章 Docker 容器化 CI/CD 的构建阶段产出 Docker 镜像
K8s 部署 第03章 Kubernetes 编排 CI/CD 的部署阶段将镜像部署到 K8s
测试阶段 第05章 游戏自动化测试 CI/CD 自动运行单元测试和压力测试
灰度发布 第09章 版本管理与灰度发布 CI/CD 部署阶段实现灰度发布策略
Git 规范 第04章 代码质量与工程实践 分支策略是 CI/CD 触发的基础

上一章:学习路线图 | 下一章:02-Docker容器化