CI / CD 入门 · 用我们自己的仓库讲

验一遍
送上线

CI 是质检员,拦住写坏的代码;CD 是快递员,把验过的代码送到用户面前。

// 面向团队所有人 · 没写过代码也能看懂
// 本文为公开版,具体标识已替换为占位符,账单与用量数字改为示意

GITHUB ACTIONS 计价币种 USD 多个 ORG TEAM 3000 · FREE 2000 按分钟计费
0min
Free 档每月免费分钟仅私有仓消耗 · 每月重置
0min
Team 档每月免费分钟超出部分才按分钟计费
$0
Linux 每分钟单价官方定价,美元
0min
每 5 分钟跑一次的脚本 · 一个月示意 · 不足 1 分钟按 1 分钟收
SCROLL / 向下滚动
01
Why It Exists

没有 CI 的那个下午

问题不在于代码会坏——代码总会坏。问题在于 三天后才发现,而这三天里所有人都在这份坏代码上继续写。

周一上午周一下午周三周三晚上 开发
01你改了 A 文件,本地跑通
02同事改了 B 文件,本地也跑通
05翻三天的提交,找是哪一改动
主干代码
03两份改动合到一起,没有任何人验
线上用户
04点开就报错,客服先知道

// 序号跨行跳一次 = 一次交接 · 01 → 04 之间隔了三天,中间没有任何一道闸

Point

各自本地都是好的,合到一起才坏——这就是 Integration(集成)这个词的由来。CI 要解决的就是「合起来这一刻没人验」。

02
Continuous Integration

CI:每次推代码,机器先验一遍

不用等谁想起来跑测试。代码一推上去,GitHub 就开一台干净的机器,把项目从头装一遍、编译一遍、测一遍。下面五步是我们这边的实际配置,别的团队顺序可能不同。

01 · 你推代码git push 到自己的分支
02 · 机器装依赖开一台干净机器,从零装
03 · 机器查类型和规范tsc 编译 + eslint 检查
04 · 机器跑测试所有单测跑一遍
05 · 闸门红了就拦住PR 上直接打红叉

// 琥珀 = 人或闸门 · 青 = 机器自动 · 流光点表示这条链路一直在跑

Continuous

「持续」的意思是每次推送都跑,不是每周跑一次。它的全部价值在快——坏了几分钟内就知道,而不是三天后从一堆改动里翻。

03
Continuous Delivery / Deployment

CD:验完了,怎么送上线

CD 有两个都对的展开,区别只有一个:最后那一下,是人点的,还是机器自己点的。

CI 全绿ALL CHECKS PASS 要人点一下吗 HUMAN GATE 要 · YES 不要 · NO 持续交付DELIVERY 打好包放在门口 等人点发布 持续部署DEPLOYMENT 合并即上线我们的 VERCEL

// 菱形 = 判断点 · 两条路都叫 CD,选哪条取决于这次上线错了有多贵

CONTINUOUS DELIVERY持续交付

机器把包打好、放在门口,人点一下才真的发布。适合上线成本高、要挑时间窗的场景。

CONTINUOUS DEPLOYMENT持续部署

CI 一绿直接自动上线,没有人工按钮。我们的 Vercel 走的是这条——但只有改到前端的提交才会真的触发部署(见下一章)。

04
End-to-End

一次改动的完整旅程

从你敲下 git push,到确认线上真的变了——我们这边的这六步,哪一步断了都不算送到


PUSH
改动推到自己的分支,不直接推 main
GITHUB
CI
Actions 自动开一台干净机器:装依赖 → 查类型 → 跑测试,结果打在 PR 上
你 / 同事
合并
CI 全绿才合进 main。改到核心目录(模型调用 / 定时任务 / 数据库结构 / 登录鉴权)还要额外的人工复核
GITHUB
部署
Actions 的 Deploy Vercel 调 Vercel API 打包(Vercel 自带的 git 监听已关掉);只动文档或后端时,这一步整个跳过
VERCEL
上线
构建产物推到 CDN,新版本对所有用户生效

验一眼
请求一条本次新增的路由 —— 404 就是没部署上去,别只看 CI 的绿灯

// 第 6 步不能省:前五步全绿,线上仍可能是旧版本

05
Two False Greens

两个最容易信错的绿灯

绿灯只说明「某件事跑完了」,不说明「你要的那件事成了」。下面这次事故和两类绿灯,我们都真踩过。

Resolved Incident · 2026-08-13

整个 GitHub 组织的 Actions 停摆 2.5 小时,43 个任务直接启动失败,而告警一条都没发出来——监控自己也跑在 GitHub Actions 上,跟着一起被闸断了。团队排查了代码、workflow 语法、GitHub 状态页,全部正常。真因是风控自动打的账号级计费锁,而所有计费页面当时都显示一切正常。当天解锁后重跑恢复;九月至今同类拦截 0 次

FALSE GREEN 01CI 绿 ≠ 代码是对的

CI 只验证了你写的那些测试。测试没覆盖到的地方,它一无所知。构建成功只说明能编译,不说明逻辑对

FALSE GREEN 02CI 绿 ≠ 线上已更新

部署是另一件事。额度用完、计费锁、配置漏了,都会让它悄悄没跑,而 CI 那边照样是绿的。九月 35 次部署有 21 次被跳过——绝大多数是该跳过的(改的是文档或后端,前端没变)。真正的陷阱是:你以为改了前端、但路径没匹配上,这两种从外面看一模一样

那怎么才算验过

别问 CI,去问生产:请求一条这次新增的路由,看它认不认。

curl -s -o /dev/null -w '%{http_code}' https://你的域名/本次新增的路由 # 404 → 没部署上去 200 / 401 → 部署了
06
The Bill · Priced in USD

这些机器时间,谁在付钱

GitHub 全球只用美元计价。国内卡付款时,是卡组织按当日汇率折成人民币扣——账单和发票本身始终是美元。

额度与消耗(示意)
单位:分钟 / 月 · 示意数据,非真实账单 · 仅 GitHub 托管 runner 的私有仓计费 · 自托管 runner 分钟不计费也不入此表
其余免费 orgFREE · 每月额度2,000
主力团队 orgTEAM · 每月额度3,000
*/30 定时脚本单个 JOB · 一个月1,440
*/5 定时脚本单个 JOB · 一个月8,640

// 条长按最大值 8,640 归一 · 灰 = 每月免费额度,青 = 消耗 · 一个每 5 分钟跑一次的小脚本,一个月就超过 4 个 Free 额度 · 把用量大的仓改跑自建 runner,这部分算力不再计入 GitHub 账单,但机器本身的成本是另一笔账

项目口径
计价币种GitHub 全球统一,无人民币计价USD
Linux 2 核单价每个 job 单独计,不足 1 分钟按 1 分钟收$0.006 / min
免费额度 · Free每月重置,仅私有仓消耗2,000 min
免费额度 · Team主力团队 org 用的是这一档3,000 min
公开仓标准 runner 不计入额度;大规格 runner 仍计费标准 runner 免费
自托管 runner机器自备,分钟不计入 GitHub 账单机器成本另算
最容易超的地方

不是大项目,是每 5 分钟跑一次的小脚本——跑 1 秒也按 1 分钟收。*/5 一个月就是 8,640 分钟,远超 2,000 的免费额度;改成 */30 就是 1,440 分钟,稳稳在内。

一句话记住:CI 是质检员,拦住坏东西;CD 是快递员,送出好东西。GitHub Actions 是雇他俩的平台,按分钟付美元。账单降到 $0 不一定是变免费了:把用量大的仓改跑自建 runner,GitHub 这侧的用量就会降到额度以内,而那台机器的成本是另一笔账