CI/CD 发展史
从手动部署到自动化流水线
2000 年代初期,软件发布是极其痛苦的过程:开发团队工作数月,在"发布日"将所有代码合并,然后花数天时间手动测试、修复冲突、部署到服务器。这种"大爆炸式发布"导致了无数的夜间故障、加班噩梦和线上事故。
2006 年,Martin Fowler 系统化地提出了持续集成(Continuous Integration)实践,主张开发者每天多次将代码合并到主干,并通过自动化测试即时验证。这一理念逐渐演进为今天的 CI/CD 体系。
三个概念的精确区分
持续集成(CI)
开发者频繁(每天多次)将代码变更合并到共享主干,每次合并都触发自动化构建和测试。目标:尽早发现集成问题,保持代码库的健康状态。关键实践:自动化测试覆盖率 >80%、构建时间 <10 分钟、绿色主干不破窗。
持续交付(CD - Delivery)
在 CI 基础上,将软件自动部署到类生产环境(Staging),使其随时处于可部署状态。部署到生产环境需要人工批准。目标:减少发布的风险和复杂度,实现可重复的发布流程。
持续部署(CD - Deployment)
比持续交付更进一步:通过所有测试的变更自动部署到生产环境,无需人工干预。需要极高的自动化测试可信度和成熟的监控告警体系。代表公司:Netflix、Facebook、Amazon(每天部署数千次)。
代码提交
↓
[ 持续集成 ] ─── 自动构建 + 自动测试 ─── 失败则通知
↓(成功)
[ 持续交付 ] ─── 自动部署到 Staging ─── 人工审批
↓(批准)
[ 持续部署 ] ─── 自动部署到 Production(无需人工)
GitHub Actions 核心架构
五个核心概念
Workflow(工作流)
一个自动化流程,存储为 .github/workflows/ 目录下的 YAML 文件。一个仓库可以有多个 Workflow(如:CI 测试工作流、发布工作流、定时清理工作流)。
Event(事件)
触发 Workflow 运行的条件,如:push 代码、创建 PR、发布 Release、定时触发(cron)、手动触发(workflow_dispatch)等。
Job(作业)
Workflow 中的一个执行单元,在独立的 Runner 上运行。同一 Workflow 的多个 Job 默认并行执行,可通过 needs 声明依赖关系实现顺序执行。
Step(步骤)
Job 中的单个操作,按顺序执行。每个 Step 可以是:运行 Shell 命令(run)或调用已发布的 Action(uses)。
Runner(运行器)
执行 Job 的虚拟机或容器。GitHub 提供托管的 Runner(ubuntu-latest、windows-latest、macos-latest),也可以使用自托管 Runner(Self-hosted Runner)连接到私有网络中的机器。
架构图解
Repository(代码仓库)
└── .github/workflows/
├── ci.yml ← Workflow 1
└── deploy.yml ← Workflow 2
Workflow: ci.yml
├── on: [push, pull_request] ← Event(触发条件)
├── jobs:
│ ├── test ← Job 1(在独立 Runner 上运行)
│ │ ├── runs-on: ubuntu-latest
│ │ ├── steps:
│ │ │ ├── uses: actions/checkout@v4 ← Action
│ │ │ ├── run: npm install ← Shell 命令
│ │ │ └── run: npm test
│ └── build ← Job 2(依赖 test job)
│ ├── needs: test
│ └── steps: [...]
Runner(GitHub 托管虚拟机)
├── ubuntu-latest (Linux)
├── windows-latest
└── macos-latest
与其他 CI/CD 工具对比
| 特性 | GitHub Actions | Jenkins | CircleCI | GitLab CI |
|---|---|---|---|---|
| 托管方式 | 托管/自托管 | 自托管(必须) | 托管/自托管 | 托管/自托管 |
| 配置文件 | YAML | Groovy(Jenkinsfile) | YAML | YAML |
| 与 GitHub 集成 | 原生无缝 | 需要插件 | 良好 | 需要迁移 |
| 免费额度 | 公开仓库免费,私有每月 2000 分钟 | 完全免费(自托管) | 6000 分钟/月 | 400 分钟/月 |
| 学习曲线 | 平缓 | 陡峭 | 平缓 | 平缓 |
| Action 市场 | GitHub Marketplace(20000+) | 插件中心 | Orb Registry | CI/CD 组件 |
为什么选择 GitHub Actions?
对于已经在 GitHub 上托管代码的项目,GitHub Actions 是最自然的选择:零配置集成(代码和 CI 在同一平台)、庞大的 Action 生态(几乎任何工具都有现成的 Action)、慷慨的免费额度(公开仓库完全免费)。
第一个 Workflow:Hello GitHub Actions
# .github/workflows/hello.yml
name: Hello GitHub Actions
on:
push:
branches: [ "main" ]
jobs:
say-hello:
runs-on: ubuntu-latest
steps:
- name: Checkout 代码
uses: actions/checkout@v4
- name: 打印 Hello
run: echo "Hello from GitHub Actions! 🚀"
- name: 显示系统信息
run: |
echo "操作系统: $(uname -a)"
echo "当前目录: $(pwd)"
echo "文件列表:"
ls -la
- name: 显示提交信息
run: |
echo "触发事件: ${{ github.event_name }}"
echo "分支: ${{ github.ref_name }}"
echo "提交 SHA: ${{ github.sha }}"
echo "触发者: ${{ github.actor }}"
查看 Workflow 运行结果
将此文件推送到仓库后,进入 GitHub 仓库页面 → Actions 标签 → 选择对应 Workflow → 查看运行日志。每个 Step 的输出都可以展开查看,失败的 Step 会以红色标注。
Runner 详解:托管 vs 自托管
GitHub 托管 Runner(推荐起点)
GitHub 自动管理的虚拟机,每次 Job 都是全新环境。ubuntu-latest(2核/7GB内存)、windows-latest(4核/16GB内存)、macos-latest(3核M1/14GB内存)。公开仓库完全免费,私有仓库每月 2000 分钟(ubuntu)/ 200分钟(macOS 10倍计费)。
自托管 Runner(Self-hosted)
在自己的服务器或 K8s 集群上运行的 Runner。适用场景:需要访问私有网络(内网数据库/部署目标)、需要特殊硬件(GPU/大内存)、需要持久化数据/工具缓存、超出 GitHub 免费额度的大型项目。
Actions Runner Controller(ARC)
在 Kubernetes 上动态管理 Runner 的控制器,根据排队作业数量自动扩缩容。适合有大量并发 CI 需求的企业。Runner 以 Pod 形式运行,Job 完成后自动销毁(保证环境隔离)。
本章小结
本章核心要点
- CI/CD 三阶段:CI(自动构建+测试)→ 持续交付(自动到 Staging,人工审批到 Production)→ 持续部署(全自动到 Production);大多数团队处于"持续交付"阶段。
- GitHub Actions 五要素:Workflow(.github/workflows/*.yml)→ Event(触发条件)→ Job(在 Runner 上运行的独立单元)→ Step(命令或 Action)→ Runner(执行环境虚拟机)。
- 与 Jenkins 的核心区别:GitHub Actions 无需维护服务器,与 GitHub 原生集成,YAML 配置更简洁;Jenkins 更灵活但运维成本高,适合复杂的企业场景。
- 免费额度:公开仓库完全免费(无限制);私有仓库每月 2000 分钟(ubuntu),macOS 按 10 倍计费,需要合理规划矩阵构建避免超支。
- 起步实践:创建 .github/workflows/ 目录,推送 YAML 文件即可触发;Actions 标签页实时查看日志;利用 GitHub Marketplace 的 20000+ 现成 Action 加速开发。