CI/CD 入门:让代码自动飞

你还在手动打包、手动部署、手动祈祷不出错?这篇带你用最通俗的方式搞懂 CI/CD,并用 GitHub Actions 搭一条能跑的流水线。

4 分钟阅读
小明

CI/CD 入门:让代码自动飞

你有没有经历过这种“人类式部署”?

  • 本地 pnpm build 跑了一遍:没报错,心情不错。
  • 服务器上再跑一遍:报错了,心情爆炸。
  • 你开始怀疑人生:到底是我变了,还是服务器变了?
  • 最后你发现:哦,服务器的 Node 版本跟本地不一样。

小明先替你总结一句话:

你以为你在部署,其实你在开盲盒。

CI/CD 的目标,就是把“盲盒”变成“流水线”。把那些重复、容易出错、又必须做的事情,交给机器。


一、先把人话说清楚:CI/CD 到底是啥?

别被缩写吓到。

  • CI(Continuous Integration,持续集成):代码一提交,就自动拉起一套流程:装依赖、跑 lint、跑测试、打包……目的是尽早发现问题。
  • CD(Continuous Delivery / Deployment,持续交付 / 持续部署):CI 通过后,把产物“交付出去”。
    • Delivery:产物准备好,随时可以点按钮上线。
    • Deployment:产物准备好,并且自动上线。

你可以把它想象成:

  • CI 是“出厂质检”,不合格就别想出门。
  • CD 是“物流配送”,合格了就自动发货。

二、为什么你需要它:不是为了高级,而是为了少背锅

2.1 你现在的成本,其实是“重复劳动 + 不确定性”

手动部署最大的坑不是累,而是不可复现

  • 今天你手动改了环境变量,明天忘了。
  • 今天你临时在服务器上装了个依赖,后来谁也说不清。
  • 今天你靠记忆敲命令,明天靠运气。

CI/CD 做的事很朴素:

  • 把步骤写下来(版本化)
  • 把步骤标准化(所有人跑同一套)
  • 把步骤自动化(机器帮你跑)

2.2 更隐蔽的收益:让团队协作变简单

当你有了 CI:

  • PR 上来先过一遍 lint/test,减少“低级错误”进入主干
  • 代码风格不再靠吵架,靠机器人
  • 新人进组不需要背诵“部署咒语”

三、一条最小可用的流水线长什么样?(MVP)

如果你刚入门,小明建议先做最小闭环:

  1. 拉代码
  2. 安装依赖
  3. 静态检查(lint)
  4. 单元测试(test)
  5. 构建(build)

至于部署(CD)先别急,先把“质检”搞定。否则你会自动把 bug 部署上去,效率是上去了,血压也上去了。


四、实战:用 GitHub Actions 做一条能跑的 CI

你仓库里只要有 .github/workflows/xxx.yml,GitHub 就会在指定事件(push / PR)发生时帮你跑。

下面是一个对 Node 项目非常常见的 CI 工作流。你可以直接复制,然后按你的包管理器和脚本名改。

4.1 示例:ci.yml

name: CI

on:
  pull_request:
  push:
    branches:
      - main

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: pnpm

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 9

      - name: Install
        run: pnpm install --frozen-lockfile

      - name: Lint
        run: pnpm lint

      - name: Test
        run: pnpm test

      - name: Build
        run: pnpm build

这段配置做了几件事:

  • on.pull_request:有人提 PR 就跑一遍,避免“合并后才炸”。
  • on.push.branches=main:主分支有变更也跑一遍,确保主干健康。
  • setup-node:固定 Node 版本,避免“本地 18,线上 20”。
  • cache: pnpm:利用缓存加速安装(第一次慢点,后面会快)。
  • --frozen-lockfile:锁定依赖版本,避免 lockfile 不一致。

4.2 常见坑位(提前避雷)

  • 坑 1:脚本名不一致
    • 你的 package.json 里可能叫 test:unitlint:fix
    • package.json 里实际脚本为准。
  • 坑 2:Node 版本没锁
    • 一定要在 CI 里指定 node-version
    • 否则你会遇到“本地过,CI 不过”。
  • 坑 3:把 Build 当成可选项
    • 很多项目 lint/test 过了,但 build 会因为 TS 类型或打包配置挂掉。
    • 所以 Build 也应该是 CI 的一部分。

五、从 CI 到 CD:什么时候该自动部署?

小明给你一个很实用的判断标准:

  • 你如果每天/每周都要上线,并且上线步骤重复、明确、可脚本化 —— 就值得做 CD。
  • 如果你还在频繁改架构、改环境、甚至服务器都不稳定 —— 先把 CI 稳住。

5.1 常见的 CD 形态

  • 发布到静态站点:构建后把产物推到对象存储或 GitHub Pages。
  • 发布到服务器:构建镜像 → 推到镜像仓库 → 服务器拉取并重启。
  • 发布到云平台:Vercel/Netlify/Cloudflare Pages 这类平台,基本是“推代码=上线”。

六、最后给你一张“心智地图”:CI/CD 其实就是把流程当代码

当你把“流程”写进仓库里,它就具备了代码同款能力:

  • 可以 review(同事能看到你怎么部署)
  • 可以回滚(坏了就退回上一个版本)
  • 可以复用(新项目复制一份就能跑)
  • 可以自动执行(机器不摸鱼)

总结一下今天这篇的重点:

  • CI 负责“尽早发现问题”,别让坏代码进主干
  • CD 负责“交付到用户”,让上线不再靠手工
  • 先做最小可用 CI:install → lint → test → build
  • 锁 Node 版本、锁依赖版本,是防锅的基本功

小明冷笑话收尾:

没上 CI/CD 的团队,就像没装安全带的司机——不是一定出事,但出事就很精彩。