GitHub Actions / GitLab CI 从入门到实战:流水线设计、常见场景与配置示例
当一个项目从“个人写着玩”进入“多人协作、频繁提交、需要稳定上线”的阶段,手工构建、手工测试、手工发布很快就会变成瓶颈。
这时候,GitHub Actions 和 GitLab CI 的价值就会真正显现出来。
它们解决的核心问题不是“会不会写 YAML”,而是:
- 每次提交后,怎么自动检查代码质量
- 每次合并后,怎么自动构建产物
- 每次发布前,怎么自动执行一套稳定流程
- 出问题时,怎么让发布和回滚更可控
这篇文章从入门概念开始,逐步讲到:
- CI/CD 到底是什么,和日常开发有什么关系
- GitHub Actions 与 GitLab CI 的核心概念怎么对应
- 最小可用流水线怎么写
- 前端、Node 项目、博客项目常见流水线怎么设计
- 真正进入团队后,流水线应该怎么做得更稳
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:什么时候触发
常见触发方式:
pushpull_requestmerge_requesttag- 定时任务
- 手工触发
也就是说,流水线不是“永远自动跑”,而是“在指定事件发生时运行”。
3.2 Job:一组任务
一个 Job 可以理解为“同一台执行环境里的一组步骤”。
例如:
- 安装依赖
- 执行测试
- 执行构建
这些步骤可以放在同一个 Job 里。
3.3 Step:具体动作
Step 是更细粒度的执行单元。
例如:
1 | |
3.4 Runner / Executor:谁来执行
流水线不是凭空运行的,它需要执行环境。
例如:
- GitHub-hosted runner
- GitLab runner
- 你自己维护的自托管执行机
这决定了:
- 能用什么系统
- 能装什么依赖
- 有多少权限
3.5 Artifact:流水线产物
例如:
- 构建生成的静态文件
- 打包好的压缩包
- 测试报告
- 覆盖率报告
产物常用于:
- 下载查看
- 交给下一个 Job 使用
- 后续发布部署
4) GitHub Actions 与 GitLab CI 概念对照
下面这张表很适合建立映射关系:
| 概念 | GitHub Actions | GitLab CI |
|---|---|---|
| 配置文件位置 | .github/workflows/*.yml | .gitlab-ci.yml |
| 触发器 | on | only / rules / pipeline source |
| 任务单元 | job | job |
| 任务步骤 | steps | script |
| 执行环境 | runs-on | runner / tags / executor |
| 复用单元 | action | include / template / reusable config |
| 构建产物 | artifacts | artifacts |
| 环境变量 / 密钥 | secrets / variables | CI/CD variables |
你会发现它们其实只是名字和组织方式不完全一样,思想基本相通。
5) 第一个最小可用示例
5.1 GitHub Actions 最小示例
下面是一个最小的 Node.js 工作流:
1 | |
这段配置表达的意思很简单:
- 当
main分支有 push,或者有人向main提 PR 时 - 启动一条 Job
- 拉代码
- 安装 Node
- 安装依赖
- 跑测试
5.2 GitLab CI 最小示例
对应的 GitLab CI 版本可以写成:
1 | |
思路一样,只是写法不同。
6) 什么时候该拆多个 Job
初学者常见问题是:所有步骤都写进一个 Job,行不行?
当然可以,但当项目变复杂后,拆 Job 会更清晰。
例如可以拆成:
linttestbuilddeploy
好处是:
- 职责更清楚
- 失败更容易定位
- 某些任务可以并行跑
GitHub Actions 示例:
1 | |
当你再进一步时,就可以让 deploy 依赖 build 完成之后再执行。
7) 缓存为什么重要
如果每次流水线都重新下载依赖,速度会很慢。
所以很多项目都会加缓存。
7.1 GitHub Actions 中的缓存思路
典型方式:
- 缓存
~/.npm - 或缓存包管理器目录
示例:
1 | |
7.2 GitLab CI 中的缓存思路
1 | |
注意:
- 缓存能提速
- 但缓存策略不当也会带来“脏依赖”问题
所以缓存不是越多越好,而是“缓存真正稳定且昂贵的部分”。
8) 密钥、环境变量、权限控制
这一节非常重要,因为很多流水线事故都不是出在 YAML 语法,而是出在权限和密钥管理。
8.1 不要把敏感信息写进仓库
例如:
- API Token
- SSH 私钥
- 云厂商密钥
- 数据库密码
正确做法是放到平台的密钥管理里:
- GitHub:
Secrets and variables - GitLab:
CI/CD Variables
8.2 权限要最小化
建议:
- 只给流水线需要的最小权限
- 区分测试环境和生产环境密钥
- 部署密钥和个人账号分离
8.3 不同环境分开管理
例如:
DEV_API_URLSTAGING_API_URLPROD_API_URL
不要让测试环境和生产环境共用一套变量。
9) 前端项目实战:构建与质量检查
对于 React、Vue、Next.js、Vite 这类项目,最常见的流水线需求通常是:
- 安装依赖
- 跑 lint
- 跑单测
- 执行构建
9.1 GitHub Actions 示例
1 | |
9.2 GitLab CI 示例
1 | |
如果你是纯静态前端项目,dist/ 往往就是后续部署的核心产物。
10) Hexo / 博客项目实战
像这个博客项目,最典型的流水线目标通常是:
- 安装依赖
- 执行
hexo clean && hexo generate - 检查静态生成是否成功
- 有需要的话自动部署
10.1 GitHub Actions 示例
1 | |
10.2 如果还要自动部署
你可以在构建成功后再增加部署步骤,例如:
- 发布到 GitHub Pages
- 部署到对象存储
- 同步到服务器
这时候建议把部署条件卡严一些,例如只在:
push到main- 打 tag
- 手工触发
时才执行部署。
不要让每个 PR 都直接触发正式发布。
11) 后端项目实战
后端服务的 CI 往往更关注:
- 单元测试
- 集成测试
- 镜像构建
- 制品上传
一个简化版思路:
- 拉代码
- 安装依赖
- 跑测试
- 构建产物
- 打 Docker 镜像
- 推送镜像仓库
- 部署到测试或生产环境
这里最容易踩坑的是:
- 测试依赖外部服务
- 构建环境与线上环境差异太大
- 镜像版本不可追溯
所以实践上建议:
- 镜像 Tag 带 commit sha 或版本号
- 区分测试镜像和正式镜像
- 关键部署步骤加审批或受保护分支限制
12) 什么时候该自动部署,什么时候不该
不是所有项目都适合一合并就自动发布。
12.1 适合自动部署的场景
- 文档站
- 个人博客
- 测试环境
- 演示环境
12.2 需要谨慎自动部署的场景
- 核心支付系统
- 涉及数据库迁移的后端服务
- 多服务联动的大型系统
- 高峰期不能随意变更的生产环境
一个很务实的建议是:
- CI 尽量自动化
- CD 按项目风险级别分层设计
也就是说:
- 检查、构建、测试尽量全自动
- 部署可以按环境决定是否需要人工确认
13) 常见优化点
当你的流水线已经能跑起来后,下一步通常不是“继续加步骤”,而是做优化。
13.1 降低重复执行
例如:
- 文档改动不跑完整后端测试
- 只改前端时不跑无关服务构建
13.2 提升可观测性
建议保留:
- 构建日志
- 测试报告
- 构建产物
- 失败截图或错误上下文
13.3 让失败更容易理解
不要让流水线失败信息只剩一句:
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 模板”但缺少工程判断的做法了。