CI/CD 是什么|打造高效稳定开发团队的关键流程与工具选择
针对 iOS App 团队,解析无 CI/CD 流程的痛点,透过 GitHub Actions 与 self-hosted Runner 自动化测试与打包,减少人力浪费与错误,提升团队稳定性与开发效率,搭配 Google Apps Script Web App 实现跨职能便捷操作。
Click here to view the English version of this article.
點擊這裡查看本文章正體中文版本。
基于 SEO 考量,本文标题与描述经 AI 调整,原始版本请参考内文。
CI/CD 实战指南(一):CI/CD 是什么?如何透过 CI/CD 打造稳定高效的开发团队?工具选择?
以 App (iOS) Team 为例,带您从 0 认识 CI/CD 与导入后能带来的实质价值。
Photo by Leif Christoph Gottwald
前言
历经了两次在不同开发团队建置 App CI/CD 的经验,最近终于有时间整理这段从「为什么要做」到「该怎么做」的心路历程;不敢保证是最标准的 CI/CD 工作流程,但绝对是一个值得参考的起点,帮助您的团队开始导入、提升产品稳定性与整体开发效率。
章节
本系列文章会从「CI/CD 是什么、能带来哪些价值」开始讲起,接著开始手把手实作「如何用 GitHub Actions + self-hosted Runner 搭建 CI/CD 环境」并「以 App 开发为例,实际导入 CI 和 CD」,最后还会介绍如何「使用Google Apps Script Web App 结合 GitHub Actions,打造一个方便跨团队使用的 App 打包平台」希望这系列内容对你有所帮助。
最终成果
废话不多说,先上最终结果。
CI/CD — 全部都使用 GitHub Actions 开发,好维护、好扩充。
CI:
发 PR 自动触发单元测试
依照改动档案范围执行对应测试
测试通过 (passed) 后才能 Merge PR
CD:
Google Apps Script Web App (CD 打包介面) 工程师、QA、PM 都可以透过这个网站在电脑或手机上打包 App
GitHub Actions Self-hosted Runner 使用自己的机器跑 CI/CD 用量吃到饱
串接 Firebase App Distribution API 直接取得打包的测试版下载连结
Automation :
发 PR 自动 Assign self
发 PR 自动随机指定 Reviewer
标记 PR Size Label
Demo Web App/Project
Sign in Edit description script.google.com
CI/CD 是什么?
故事 — 无 CI/CD 的开发流程
在谈 CI/CD 究竟是什么之前我们先抛开「CI/CD」这个词,先来回想一下一个初创什么工作流程都没有导入的开发团队,会是怎么工作的,大致简略为下图流程:
产品有一个 Bug,Developer T 从主分支开分支 fix/bug-c 分支进行修正,修正完后 Merge 回主分支。
紧接著 Developer Z 从主分支开分支 feature/a 做 需求 A,做到一半发现功能怪怪的, 查了一下才发现原来当前功能被改坏、测试也坏了 ,回头通知 Developer T 进行修正。
一切开发完毕后,Developer Z 使用他的电脑打包版本给 QA 测试,来来回回修正跟打包 ,最后没问题后将功能回到主分支。
很快地也到了 Sprint 尾声需要打包释出给使用者;Developer Z 先放下手上工作 ,协助从主分支打包给 QA 进行 Regression 测试,同样 来来回回修正问题跟重新打包 ,完成后打包送审 App。
Apple/Google 审核完毕后发布给使用者使用。
问题
在以上故事中我们可以归纳出两个大问题。
Question 1: 对当前正确的功能异动无任何统一检查机制。
不符合 Coding Style 的程式码也能 Merge
就算 Build 不起来我也能 Merge
异动后基本的 Unit Tests、重要检查项目都没过也能 Merge
我的环境功能正确但其他人不一定正确
影响到其他正在开发的人
Question 2: 耗费大量人力时间在打包工作上。
打包要透过工程师人力打包,中断当前开发工作
来回在打包与开发之间,心流切换成本极高
打包等待时间无法进行其他开发工作
工程师的时间成本就是金钱
人工操作可能出错
QA 要请工程师打包 (来回沟通)
CI — Continuous Integration 持续整合
对应 Question 1「持续整合」旨在确保所有变动都能自动执行统一环境的 Build & Test 确保进入生产环境之前的改动都通过所有测试案例及符合团队规范 — 「持续地自动确保正确的程式码整合到生产环境」。
另外也可以增加 Nightly Build、更多的自动化测试环节,确保稳定性。
CD — Continuous Delivery / Deployment 持续交付/部署
对应 Question 2「持续部署」旨在确保程式码在 CI 环节无异常之后,将改动结果自动完成打包部署繁琐流程给内部测试(QA, Debug, Staging, Beta…)或外部上线(Production, Release…)。
Continuous Deployment: 全自动直接部署到 Production 环境
Continuous Delivery: 只自动部署到 Staging/Debug 环境可,需手动验证确认没问题之后才会再部署到 Production 环境
依照 App 开发的场景,比较偏向是 Continuous Delivery 持续交付 ,我们希望 App 最终上线之前是由人工把关确认完全无问题后才发布,确保释出时间与功能正确性。
故事 — 透过 CI/CD 打造稳定高效的开发团队
回头看我们的故事,导入 CI/CD 后:
CI 所有人的调整都需要经过 自动化测试验证通过后才能进入主分支、增加 Nightly Build 定时自动化测试环节提升稳定性。
CD 统一都使用 CD 打包,Developer T 和 Developer Z 可以完全专注在业务开发上、减少人工沟通与操作错误。
团队工作效率与产品稳定性 🚀🚀🚀🚀🚀
CI/CD 的价值
结合敏捷开发的核心理念「小步快跑,快速迭代」CI/CD 为其提供了「频繁持续迭代功能」时的稳定性与工作效率的基石。
自动统一验证迭代结果
- 确保所有调整都符合正确的预期结果、不影响其他功能、不影响其他成员
自动执行繁琐的部署流程
- 让团队成员可以专注在主要业务开发、减少人工操作错误
CI/CD 的成效
回顾 2021 年在 Pinkoi 的演讲「 2021 Pinkoi Tech Career Talk — 高效率工程团队大解密 」其实说来说去都是差不多的内容,不外乎就是「自动化、减少人跟人的依赖、专注在主要业务上」导入 CI/CD 也完全符合上述三个方向,借此我们也可以用同样的方法来估算成效。
另外有一点需要再次 Highlight 的是 心流切换成本 :
当我们持续投入工作一段时间后就会进入「心流」状态,此时的思绪、生产力都达到巅峰,能提供做好最有效的产出;但如果被打断,要重新回到心流,又会再需要一段时间,这边以 30 分钟为例。
在无 CI/CD 的场景中可能是: 花很多时间才发现是被改坏再回头沟通调整(CI)、QA/PM 来请工程师帮忙打包测试版 App (CD)。
CI/CD 成效估算
团队人数 6 人 / 一个月来计算
这边我们以每个月为基准,假设在无 CI/CD 流程时,每个月会发生 4 次意外改坏主分支的问题,造成后续修正、沟通的成本,约花费 720 分钟;加上每个月打包测试版、正式版及因人工操作造成错误的可能,总和约 1,010 分钟;以工程师月薪 8 万计算,每个月就造成约 1 万 3 的成本浪费。
CI/CD 建置成本
人力成本: 照本系列文章建置,粗估需投入人力 1 人花费 10 天 = 4,800 分钟 能完成。(~= NT$36,384 )
设备与执行成本: 使用 GitHub Actions self-hosted Runner 只需在前期采购 1–2 台 Mac-Mini 或直接使用现有汰换的 MacBook Pro 就能当成 CI/CD Runner 提供服务使用。 以 6 人团队采购一台全新的 Mac Mini 为例:32G RAM M4 Mini (= NT$40,900 )
总花费成本约 NT$80,000 元就能完成建置,约半年后开始享受效益。
声明: 这里只是提出一种效益计算的方式,不一定是最准确的;只是给大家一个概念去延伸, 让管理决策层能看到 CI/CD 的效益 进而授权推动完成整个工作流程。
CI/CD 的工具选择
云服务 Bitrise / XCode Cloud
Bitrise: 最早期主打提供 App CI/CD 的云服务,第一次接触 CI/CD 也是使用 Bitrise,它提供友善直觉的步骤编辑工具,可以很快的设定好 App CI/CD 流程。 缺点: 最早期是 $99 镁吃到饱,Apple M 系列处理器刚出来的时候一度改成用量计费( 养套杀 ),那时候估团队用量每个月至少要花 $500 镁,索性就迁移至 GitHub Actions 了。 但最近看官网,现在有提供 1 App / 1 Concurrent / 吃到饱 / $89 镁 / 月。
XCode Cloud: 100 小时 / 1 个月 / $50 镁,优点是与 XCode、App 开发高度整合;但缺点同样是,无法提供 Android 使用、要客制化一些步骤会有些困难;但如果是纯 iOS 的小型 App 我会再次考虑直接使用。
实在很怕 云服务又养套杀 、希望可控性在自己手上,所以改考虑地端服务。
地端服务 Jenkins / GitHub Actions / Gitlab CI/CD
Gitlab CI/CD: 比 GitHub Actions 推出的时间更早、功能更完整,但是我们的专案是托管在 GitHub 上所以就不考虑用 Gitlab CI/CD 了;但是两边功能类似,本系列文章会以使用 GitHub Actions 为例。
GitHub Actions GitHub 2018 年才推出的 CI/CD 服务,跟 GitHub 专案直接绑定,在这几年持续更新完善功能,有很多封装好的步骤 ( Marketplace ) 可以直接使用;支援 self-hosted runner 可以使用自己的机器无限使用。(等于混合云了)
Jenkins: 一个专门处理 CI/CD 的开源免费工具、古老但是功能强大;从应用层任务设计、权限管理到底层服务派发执行,Jenkins 全包;同样有 Plugins 可以直接搭配使用,是早期 DevOps CI/CD 的必备工具。
Jenkins v.s. GitHub Actions
TL;DR
在没有专门做 DevOps 的 App Team,要 App 开发者从 0 到 1 架设维护 Jenkins 环境门槛太高、会的人也不多还会衍生出网路安全问题;选择直接用 GitHub Actions,App 开发者只需专注在 CI/CD 流程设计,大概扫一下官方文件怎么撰写跟启动 Runner,就能快速搭建出免费稳定又安全的 CI/CD 服务。
以下仅以 App CI/CD 架设为出发点做比较,并不适用所有技术场景。
架设与维护难易度 Jenkins >>> GitHub Actions
这边先用一张不是很专业的结构分层图来说明两者的差异,Jenkins 如前述是从上到下功能全包,所以在自架上会复杂许多;而 GitHub Actions,GitHub Actions 本身只需要在 GitHub 上撰写 YAML 工作流程,本地机器只需要注册好 GitHub self-hosted Runner (5 个指令就完成),GitHub 就会自动派发任务给本地机器执行了,其他包涵 Github Actions/Runner 版本升级或是任务派发问题都是 GitHub 负责维护,我们无需处理。
还有另一个比较麻烦的点是 Jenkins 是独立于 Git 的服务,之间要透过 API (e.g. GitHub API/WebHook) 进行沟通,设定又更复杂了。
之前也从身边能接触到的 iOS 开发者(约 30 位)做过调查,懂 Jenkins 的屈指可数( 2 位) 而有在使用 GitHub Actions 的则超过 (10 位) 毕竟就是写一写 YAML 就能完成 CI/CD 任务。
学习难易度 Jenkins »> GitHub Actions
同上只需参考官方文件学习 GitHub Actions 可用 YAML 指令跟如何在本地起自己的 Runner 即可。
稳定性 GitHub Actions > Jenkins
这点我觉得 GitHub Actions 略胜 Jenkins。
Jeknins 有机会因为系统升级或装到有冲突的 Plugin 导致服务崩溃 (不过如果跑得好好的不去动它基本上没有问题)。
GitHub Actions 受限于 GitHub 服务状态 (如果 GitHub 挂也会跟著挂),但是发生频率不高,平均在线率都能维持在 99.9%;真出问题也不用处理,坐等修复。
安全性 GitHub Actions > Jenkins
考量到 GitHub Actions/Runner 服务本身是 GitHub 在维护跟自动更新这点可能会比 Jenkins 需要手动更新来的更安全。
另外 Jenkins 跟 GitHub 沟通之间需要开 API/WebHook 口相对比较危险,GitHub 与 GitHub Actions 之间是无痛整合、GitHub Actions 与 self-hosted Runner 之间是观察者模式,self-hosted Runner 会去跟 GitHub 要任务回来做,所以 Runner 本身不需开对外接口。
但如果是全封闭网路环境,Jenkins 会比 GitHub Actions 安全。
权限控管 Jenkins »> GitHub Actions
这点需要特别挑出来比较,Jenkins 可以另外设定帐号登入权限进行控管;GitHub Actions 则直接与 GitHub Repo 进行绑定,要有 Repo 权限的人才能使用。
*因此后面的文章才会又用 GAS Web App 搭建跨团队的操作平台。
使用广度 Jenkins »> GitHub Actions
在有完整 DevOps Team 的团队无庸置疑的应该还是会选择 Jenkins,毕竟在其他领域 (例如 Web, 后端, Java…) 还是 Jenkins 运行最久、Plugin 做多最好用,并且可以统一建置一套 CI/CD 服务所有团队使用方便控管,或是后端部署完前端自动部署这种复杂的 CI/CD 场景。
*GitHub Actions 后来也支援跨 Repo Actions/Runner 了。
第三方套件丰富度 Jenkins > GitHub Actions
就数量上 GitHub Actions 大于 Jenkins,但是 Jenkins 理的 CI/CD 功能比较有深度跟强大,GitHub Actions 很多只是自动化的功能。
功能深度 Jenkins »> GitHub Actions
这点没法比,Jenkins 已做了快 20 年,GitHub Actions 还有很多功能需要再补上;例如:权限管理、Secret 管理(目前只限纯文字,密钥档案的话要先转成纯文字)、Cache/Artifact 目前只支援 Cloud…等等
扩展上,GitHub Self-hosted Runner 也支援 Docker or k8s 。
客制化深度 Jenkins »> GitHub Actions
Jenkins 从头到尾都掌控在自己手上,客制化的权限比较大,可以影响到整个系统,GitHub Actions 只能在应用层客制化不同步骤而已。
例如目前 GitHub Actions 内建的 Artifacts 不支援 self-hosted,那也只能在步骤中改成 sh copy 到其他目录,无法自行客制化实现 Artifacts。
*App CI/CD 场景也用不到太深度的功能。
易用性 GitHub Actions »> Jenkins
介面上 GitHub Actions 是新的工具在介面使用上比 Jenkins 更容易使用; 脚本设定上 Jenkins 是 Pipeline Script 储存在 Jenkins 上、GitHub Actions 是 YAML 档跟著专案 Git 管理,也比 Jenkins 容易设定。
费用风险 Jenkins > GitHub Actions
Jenkins 全开源免费权掌握在手,GitHub Actions 部分开源但任务派发与执行是 GitHub 封闭的 SAAS 服务;目前政策是 GitHub Actions 完全免费,使用 GitHub Runner 才要钱(Private Repo),使用 self-hosted runner 则不用。
Google Apps Script Web App 的用途与为何选择
另一个工具选择是 Google Apps Script Web App,会需要多一个这个的原因是 GitHub Actions 自带的表单功能过于阳春(介面太工程、只能静态)并且执行权限跟 GitHub Repo 绑定在一起,如果我们需要提供给其他职能伙伴使用会非常的麻烦。
如下:
CD 打包会希望让操作人填写一些资讯,例如 Release Notes。
因此我们需要一个「介面」工具提供给其他伙伴使用或甚至是自己工程师更方便的使用。
所需情境:
在这个比较好用的「介面」上填写需要的资讯,串接专案管理工具(e.g. Jira, Asana) 取得 Task 或是 GitHub 直接取得 PR 列表,直接下拉选单选择后送出,再透过 GitHub API 触发 GitHub Actions 进行打包。
Slack
第一次导入 CI/CD 的时候我们选择串接 Slack API 达成类似如下效果:
https://slack.com/intl/zh-tw/blog/productivity/workflow-builder-tools-automation-examples
- 伙伴可以直接在 Slack 中使用表单填写资讯、并触发 CD 打包、收到 Slack 通知
使用操作起来很顺畅并且统一在日常的办公工具上(SSOT) 不需重新学习;但是他背后的问题是 开发跟维护成本非常的高 ,其中有一个原因是 Slack Outgoing-Webhook API 对响应要求非常高 (需要在 3 秒内),因此基本上可以直接排除使用 FAAS 服务简单串接了 (e.g. Cloud Functions, GAS, Lambda…)。
之前的做法是有一位对自动化跟后端很有兴趣的伙伴自己用 Kotlin+ktor 开发了一整套后端服务,然后再 GCP 起伺服器供 Slack 串接使用。
开发与维护成本非常非常高而且很难交接。
Google Apps Script — Web App
之前有分享过「 使用 Google Apps Script Web App 表单串接 Github Action CI/CD 工作 」:
使用 Google Apps Script — Web App 的优势是:
网站 Web
同 Google Workspace 企业帐号权限管理,可设定只有组织内的 Google 帐号才能存取
完全免费
Function as a Service 不需自行架设维护伺服器
较容易维护与交接
手机上可以操作
AI Can Help! 不管是 ChatGPT 或其他 AI 工具对 GAS 都非常熟悉,可以直接动口请他帮我们制作打包表单与串接 GitHub API
一样能串接 Jira,Asana,Slack 通知 API
第二推广我就改用 GAS Web App 给伙伴使用,同样得到很好的反响,跟 Slack 差别就只在要多记一个网址到书签,需要打包的时候打开网址从网页表单操作打包。
App CI/CD 完整工具流程
这边先附上完整的工作流程,下篇开始会逐步介绍每个工具如何使用与串接。
工具角色:
GitHub Actions : CI/CD 逻辑脚本程式码
GitHub Actions — Self-hosted Runner : CI/CD 实际执行的地方,使用自己架设的 Runner 执行,只需要负担机器购买成本,就能无限制使用量的执行任务。
Google Apps Script Web App : 因打包不一定是工程师负责,需要有一个平台给跨职能伙伴可以使用; GAS Web App 能快速打造一个 Web 工具分享网址给其他人操作使用。
Asana/Jira : 专案管理工具,可与 GAS Web App 串接让 QA/PM 可以直接选择想把包的 Task 进行打包。
Slack : 负责接收执行结果通知
场景:
End-User (QA/PM/PD/Developer): 使用 GAS Web App 送出打包表单 (捞取 Jira or Asana 任务单对应的 Branch) -> GAS 打 GitHub API -> 触发 CD 打包 Github Actions <- GitHub self-hosted runner 监听到任务拉回机器执行 -> 执行完毕 Slack 通知、更新 GAS Web App 打包状态。
End-User (Developer): 开 PR、Push new commit 到 PR -> 触发 CI 测试流程 <- GitHub self-hosted runner 监听到任务拉回机器执行 -> 执行完毕 Comment 测试结果、更新 Checks。
总结
本篇主要是带大家初步了解 CI/CD 是什么跟带来的效益,下一篇开始会进入技术环节,手把手带您了解、实作 GitHub Actions CI/CD 到最终完成前文的最终成果。
系列文章:
Buy me a coffee
本系列文章花费了大量的时间精力撰写,如果内容对您有帮助、对您的团队有实质提升工作效率与产品品质;欢迎请我喝杯咖啡,感谢支持!
有任何问题及指教欢迎 与我联络 。
本文首次发表于 Medium (点击查看原始版本),由 ZMediumToMarkdown 提供自动转换与同步技术。