GitHub 上的 CI/CD 怎么用?从 GitHub Actions 到一条可上线的流水线
先把概念弄清楚
在 GitHub 生态里,大家说的 CI/CD,绝大多数场景指的就是 GitHub Actions:用仓库里的 YAML 描述「什么时候跑什么命令」,在 GitHub 托管的 Runner(或自建 Runner)上自动执行。
我这篇文章按「能跑 → 能看懂 → 能改」写:
触发器 → Workflow → Job → Step → 密钥与权限 → 一条常见前后端都能套用的流水线骨架。
说明: 以下 YAML 以 GitHub Actions 当前通用写法为准;若你读到旧教程仍写 ::set-output,请改用官方推荐的 $GITHUB_OUTPUT 写法(后文会提)。
一、核心概念:你写的不是“脚本网页”,是状态机
| 概念 | 一句话 |
|---|---|
| Workflow(工作流) | 仓库 .github/workflows/ 下的一个 YAML 文件,定义一整条流水线 |
| Event(事件) | 什么时候触发:push、pull_request、schedule、workflow_dispatch 等 |
| Job(任务) | 一组在同一 Runner 上顺序执行的 Steps;多个 Job 可并行或 needs 串联 |
| Step(步骤) | 真正跑命令或调用 Action 的最小单元 |
| Action | 别人封装好的可复用步骤(例如 checkout、setup-node) |
| Runner | 执行环境,常用 ubuntu-latest |
一句话结论:CI 多半是「每次提交自动验货」;CD 多半是「验货通过后自动发布」——可以写在同一个 Workflow,也可以拆成两个文件,团队怎么清晰怎么来。
二、最小可运行示例:PR / Push 时跑测试
在仓库创建:.github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install
run: npm ci
- name: Lint
run: npm run lint --if-present
- name: Test
run: npm test --if-present
这段在干什么:
on:有人往main推代码,或向main提 PR,就跑一遍permissions: contents: read:显式收紧权限(很多团队会要求默认最小权限)npm ci:比npm install更适合 CI(锁文件一致时更可复现)
如果你第一次跑失败,别慌:把本地 package.json 里的脚本名对照一下——很多项目不叫 lint/test。
三、CD:什么时候算“部署”
部署没有标准答案,常见三种触发:
- 推送到
main自动发布(快,但要配合分支保护与评审) - 打 Tag(v1.2.3)触发发布(更可控)
- 手动
workflow_dispatch(适合低频发布)
下面给一个「合并进 main 后构建产物」的骨架(部署动作因云平台而异,我用占位表达):
name: Release
on:
push:
branches: [main]
permissions:
contents: read
id-token: write # 若你用 OIDC 连云(常见),很多教程需要这一项
jobs:
deploy:
runs-on: ubuntu-latest
environment: production # 建议在仓库 Settings → Environments 配置保护规则
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
# 下面这一步因目标平台不同而不同:Vercel / OSS / K8s / 虚拟机……
# - name: Deploy
# run: ...
关键点: environment: production 不是摆设——你可以给生产环境加 required reviewers、wait timer,让 CD 不那么“误触”。
四、Secrets:别把密钥写进 YAML
你会在教程里看到:
env:
SOME_TOKEN: ${{ secrets.SOME_TOKEN }}
正确姿势:
- 在 GitHub 仓库 Settings → Secrets and variables → Actions 里配置
- YAML 里只引用
secrets.*,不要把真实 token 提交进 Git
如果是团队项目,还要分清:
- Repository secrets:本仓库可用
- Organization secrets:组织级统一下发(视权限)
五、矩阵构建:一次测多个版本
比如你要同时验证 Node 18/20:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: npm test --if-present
这类写法特别适合开源库:兼容性问题越早暴露越好。
六、缓存:省钱也省时间
前端项目常见瓶颈是依赖安装。setup-node 的 cache: npm 是一键方案;更复杂场景可以用 actions/cache 自己控 key(Monorepo 时常用)。
原则只有一句:缓存是为了快,不是为了“掩盖不稳定的构建”。 锁文件该锁还是要锁。
七、我踩过/见过的坑(建议你直接对照)
- 权限默认过宽:能
permissions:收紧就收紧;需要写内容、发 Release 再逐步放开。 - 把部署密钥塞仓库:哪怕私有仓也不建议;优先 OIDC 或短期令牌方案(依云厂商文档)。
- 同一 Workflow 里又测又发版:可以,但要清楚分支条件;很多人用
if:区分pull_request与push。 - Runner 时区/环境变量:CI 里“本地能跑”经常是因为本地有全局工具;把依赖写进项目与 Workflow。
- 输出变量:旧式
::set-output已不推荐,改用:
- name: Set version
id: ver
run: echo "version=$(node -p \"require('./package.json').version\")" >> $GITHUB_OUTPUT
Windows Runner 上路径/换行有差异时,要以官方文档为准(跨平台项目尤其要注意)。
八、总结:你怎么判断自己“会用 CI/CD 了”
你可以用这张清单自测:
- 能解释
on / jobs / steps / runs-on各自管什么 - 能给项目加一条 PR 必过的检查(至少 lint 或 test)
- 知道 Secrets 放哪、YAML 里怎么引用
- 知道生产部署要用
environment或等价门禁,而不是“谁 push 谁上线”
欢迎点赞关注,一起学习进步~~~
更多推荐


所有评论(0)