GitHub Actions / GitLab CI 从入门到实战:流水线设计、常见场景与配置示例

当一个项目从“个人写着玩”进入“多人协作、频繁提交、需要稳定上线”的阶段,手工构建、手工测试、手工发布很快就会变成瓶颈。

这时候,GitHub ActionsGitLab CI 的价值就会真正显现出来。

它们解决的核心问题不是“会不会写 YAML”,而是:

  • 每次提交后,怎么自动检查代码质量
  • 每次合并后,怎么自动构建产物
  • 每次发布前,怎么自动执行一套稳定流程
  • 出问题时,怎么让发布和回滚更可控

这篇文章从入门概念开始,逐步讲到:

  1. CI/CD 到底是什么,和日常开发有什么关系
  2. GitHub Actions 与 GitLab CI 的核心概念怎么对应
  3. 最小可用流水线怎么写
  4. 前端、Node 项目、博客项目常见流水线怎么设计
  5. 真正进入团队后,流水线应该怎么做得更稳

1) 先把概念说清楚:CI/CD 是什么

很多人第一次接触 CI/CD,会觉得它离自己很远。其实只要你做过下面这些事,就已经在做“手工版 CI/CD”了:

  • 提交代码前先跑测试
  • 合并分支前先执行构建
  • 发布前先打包
  • 上线前先检查环境变量

所谓 CI/CD,本质上只是把这些重复动作标准化、自动化。

1.1 CI:Continuous Integration

持续集成,重点在“集成”。

意思是:

  • 代码一提交,就自动帮你检查
  • 代码一合并,就自动验证有没有问题

常见动作包括:

  • 安装依赖
  • 跑单元测试
  • 跑 lint
  • 执行构建

1.2 CD:Continuous Delivery / Deployment

CD 常见有两种解释:

  • Continuous Delivery:持续交付,表示随时具备发布能力
  • Continuous Deployment:持续部署,表示满足条件后自动发布

简单理解:

  • CI 关注“代码质量和集成正确性”
  • CD 关注“如何更稳定地交付到环境”

2) GitHub Actions 和 GitLab CI 有什么区别

它们的目标非常像,都是围绕代码仓库做自动化流程。

2.1 GitHub Actions 的特点

  • 与 GitHub 仓库深度集成
  • 上手快,适合开源和中小团队
  • 社区 Action 丰富,生态很好
  • 配置通常在 .github/workflows/*.yml

2.2 GitLab CI 的特点

  • 和 GitLab 仓库、权限、环境、Runner 集成很深
  • 企业内网、自托管场景很常见
  • 更像“一体化 DevOps 平台”
  • 配置通常在 .gitlab-ci.yml

2.3 一句话对比

  • GitHub Actions:更像“仓库内自动化编排器”
  • GitLab CI:更像“和平台深度绑定的流水线系统”

但从学习角度看,它们的核心思想是高度一致的。


3) 流水线最核心的几个概念

不管你用哪一个平台,下面这几个概念都要先懂。

3.1 Trigger:什么时候触发

常见触发方式:

  • push
  • pull_request
  • merge_request
  • tag
  • 定时任务
  • 手工触发

也就是说,流水线不是“永远自动跑”,而是“在指定事件发生时运行”。

3.2 Job:一组任务

一个 Job 可以理解为“同一台执行环境里的一组步骤”。

例如:

  • 安装依赖
  • 执行测试
  • 执行构建

这些步骤可以放在同一个 Job 里。

3.3 Step:具体动作

Step 是更细粒度的执行单元。

例如:

1
checkout code -> install deps -> run tests -> build

3.4 Runner / Executor:谁来执行

流水线不是凭空运行的,它需要执行环境。

例如:

  • GitHub-hosted runner
  • GitLab runner
  • 你自己维护的自托管执行机

这决定了:

  • 能用什么系统
  • 能装什么依赖
  • 有多少权限

3.5 Artifact:流水线产物

例如:

  • 构建生成的静态文件
  • 打包好的压缩包
  • 测试报告
  • 覆盖率报告

产物常用于:

  • 下载查看
  • 交给下一个 Job 使用
  • 后续发布部署

4) GitHub Actions 与 GitLab CI 概念对照

下面这张表很适合建立映射关系:

概念GitHub ActionsGitLab CI
配置文件位置.github/workflows/*.yml.gitlab-ci.yml
触发器ononly / rules / pipeline source
任务单元jobjob
任务步骤stepsscript
执行环境runs-onrunner / tags / executor
复用单元actioninclude / template / reusable config
构建产物artifactsartifacts
环境变量 / 密钥secrets / variablesCI/CD variables

你会发现它们其实只是名字和组织方式不完全一样,思想基本相通。


5) 第一个最小可用示例

5.1 GitHub Actions 最小示例

下面是一个最小的 Node.js 工作流:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
name: Node CI

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

jobs:
build:
runs-on: ubuntu-latest

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

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

- name: Install
run: npm ci

- name: Test
run: npm test

这段配置表达的意思很简单:

  • main 分支有 push,或者有人向 main 提 PR 时
  • 启动一条 Job
  • 拉代码
  • 安装 Node
  • 安装依赖
  • 跑测试

5.2 GitLab CI 最小示例

对应的 GitLab CI 版本可以写成:

1
2
3
4
5
6
7
8
9
10
11
12
stages:
- test

node_test:
stage: test
image: node:20
script:
- npm ci
- npm test
only:
- merge_requests
- main

思路一样,只是写法不同。


6) 什么时候该拆多个 Job

初学者常见问题是:所有步骤都写进一个 Job,行不行?

当然可以,但当项目变复杂后,拆 Job 会更清晰。

例如可以拆成:

  • lint
  • test
  • build
  • deploy

好处是:

  • 职责更清楚
  • 失败更容易定位
  • 某些任务可以并行跑

GitHub Actions 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run lint

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm test

当你再进一步时,就可以让 deploy 依赖 build 完成之后再执行。


7) 缓存为什么重要

如果每次流水线都重新下载依赖,速度会很慢。

所以很多项目都会加缓存。

7.1 GitHub Actions 中的缓存思路

典型方式:

  • 缓存 ~/.npm
  • 或缓存包管理器目录

示例:

1
2
3
4
5
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

7.2 GitLab CI 中的缓存思路

1
2
3
cache:
paths:
- node_modules/

注意:

  • 缓存能提速
  • 但缓存策略不当也会带来“脏依赖”问题

所以缓存不是越多越好,而是“缓存真正稳定且昂贵的部分”。


8) 密钥、环境变量、权限控制

这一节非常重要,因为很多流水线事故都不是出在 YAML 语法,而是出在权限和密钥管理。

8.1 不要把敏感信息写进仓库

例如:

  • API Token
  • SSH 私钥
  • 云厂商密钥
  • 数据库密码

正确做法是放到平台的密钥管理里:

  • GitHub:Secrets and variables
  • GitLab:CI/CD Variables

8.2 权限要最小化

建议:

  • 只给流水线需要的最小权限
  • 区分测试环境和生产环境密钥
  • 部署密钥和个人账号分离

8.3 不同环境分开管理

例如:

  • DEV_API_URL
  • STAGING_API_URL
  • PROD_API_URL

不要让测试环境和生产环境共用一套变量。


9) 前端项目实战:构建与质量检查

对于 React、Vue、Next.js、Vite 这类项目,最常见的流水线需求通常是:

  • 安装依赖
  • 跑 lint
  • 跑单测
  • 执行构建

9.1 GitHub Actions 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
name: Frontend CI

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

jobs:
frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run test -- --runInBand
- run: npm run build

9.2 GitLab CI 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
stages:
- check

frontend_check:
stage: check
image: node:20
script:
- npm ci
- npm run lint
- npm run test -- --runInBand
- npm run build
artifacts:
paths:
- dist/

如果你是纯静态前端项目,dist/ 往往就是后续部署的核心产物。


10) Hexo / 博客项目实战

像这个博客项目,最典型的流水线目标通常是:

  • 安装依赖
  • 执行 hexo clean && hexo generate
  • 检查静态生成是否成功
  • 有需要的话自动部署

10.1 GitHub Actions 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
name: Hexo CI

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

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npx hexo clean
- run: npx hexo generate

10.2 如果还要自动部署

你可以在构建成功后再增加部署步骤,例如:

  • 发布到 GitHub Pages
  • 部署到对象存储
  • 同步到服务器

这时候建议把部署条件卡严一些,例如只在:

  • pushmain
  • 打 tag
  • 手工触发

时才执行部署。

不要让每个 PR 都直接触发正式发布。


11) 后端项目实战

后端服务的 CI 往往更关注:

  • 单元测试
  • 集成测试
  • 镜像构建
  • 制品上传

一个简化版思路:

  1. 拉代码
  2. 安装依赖
  3. 跑测试
  4. 构建产物
  5. 打 Docker 镜像
  6. 推送镜像仓库
  7. 部署到测试或生产环境

这里最容易踩坑的是:

  • 测试依赖外部服务
  • 构建环境与线上环境差异太大
  • 镜像版本不可追溯

所以实践上建议:

  • 镜像 Tag 带 commit sha 或版本号
  • 区分测试镜像和正式镜像
  • 关键部署步骤加审批或受保护分支限制

12) 什么时候该自动部署,什么时候不该

不是所有项目都适合一合并就自动发布。

12.1 适合自动部署的场景

  • 文档站
  • 个人博客
  • 测试环境
  • 演示环境

12.2 需要谨慎自动部署的场景

  • 核心支付系统
  • 涉及数据库迁移的后端服务
  • 多服务联动的大型系统
  • 高峰期不能随意变更的生产环境

一个很务实的建议是:

  • CI 尽量自动化
  • CD 按项目风险级别分层设计

也就是说:

  • 检查、构建、测试尽量全自动
  • 部署可以按环境决定是否需要人工确认

13) 常见优化点

当你的流水线已经能跑起来后,下一步通常不是“继续加步骤”,而是做优化。

13.1 降低重复执行

例如:

  • 文档改动不跑完整后端测试
  • 只改前端时不跑无关服务构建

13.2 提升可观测性

建议保留:

  • 构建日志
  • 测试报告
  • 构建产物
  • 失败截图或错误上下文

13.3 让失败更容易理解

不要让流水线失败信息只剩一句:

1
Process completed with exit code 1

更好的做法是:

  • 拆小步骤
  • 给每步起清晰名字
  • 在关键步骤输出必要上下文

14) GitHub Actions 与 GitLab CI 的常见坑

14.1 把流水线写成“大杂烩”

一个文件上千行,所有逻辑混在一起,后期会非常难维护。

建议:

  • 分阶段
  • 分任务
  • 适度抽模板

14.2 权限给太大

例如:

  • 所有分支都能触发生产部署
  • 所有 Runner 都能拿到生产密钥

这类问题比“构建失败”更危险。

14.3 只追求快,不追求稳

例如:

  • 为了快跳过测试
  • 为了省事跳过构建校验
  • 为了少写规则把所有分支都混在一起

最终结果通常是:

  • 速度暂时快了
  • 故障成本更高了

14.4 流水线没人维护

很多团队把 CI/CD 当成“一次性配置”,其实这是错的。

真正健康的状态应该是:

  • 依赖版本会更新
  • 流水线规则会演进
  • 失败率会被关注
  • 模板会逐步沉淀

15) 一套适合多数团队的落地建议

如果你现在准备开始建设 CI/CD,我建议按这个顺序:

15.1 第一阶段:先跑通最小链路

只做这些:

  • 拉代码
  • 安装依赖
  • 跑测试
  • 跑构建

目标是先形成“提交即验证”的习惯。

15.2 第二阶段:增加质量门槛

开始补:

  • lint
  • 单测覆盖率
  • 分支保护
  • PR / MR 必须通过 CI 才能合并

15.3 第三阶段:引入部署和制品管理

再逐步加入:

  • 自动打包
  • 自动上传构建产物
  • 自动部署测试环境
  • 条件式部署正式环境

15.4 第四阶段:做平台化沉淀

最后再考虑:

  • 统一模板
  • 复用工作流
  • 公共 Action / 公共 CI 模板
  • 统一日志和告警

这比一上来就写一个“很完整但没人能维护”的超大流水线更靠谱。


16) 总结:CI/CD 的重点不是工具,而是稳定、可重复、可审计

很多人学 GitHub Actions / GitLab CI 时,最容易把注意力放在:

  • YAML 怎么写
  • 语法怎么记
  • 某个平台命令怎么配

但真正更重要的是:

  • 流水线是否稳定
  • 规则是否清晰
  • 权限是否安全
  • 构建是否可复现
  • 发布是否可追溯

你可以把 CI/CD 理解成团队工程能力的“自动化底盘”。

工具只是外壳,真正决定质量的是:

  • 流程设计
  • 风险控制
  • 模板沉淀
  • 团队纪律

只要你先从最小可用版本开始,把“自动检查、自动构建、按条件部署”这三件事做稳,再慢慢扩展到更复杂的流水线,就已经超过很多只会“复制 YAML 模板”但缺少工程判断的做法了。


参考资料


GitHub Actions / GitLab CI 从入门到实战:流水线设计、常见场景与配置示例
https://www.pcboy.com.cn/2026/06/27/GitHub-Actions-GitLab-CI-从入门到实战/
作者
chituer
发布于
2026年6月27日
许可协议