Post

CI/CD 是什么|打造高效稳定开发团队的关键流程与工具选择

针对 iOS App 团队,解析无 CI/CD 流程的痛点,透过 GitHub Actions 与 self-hosted Runner 自动化测试与打包,减少人力浪费与错误,提升团队稳定性与开发效率,搭配 Google Apps Script Web App 实现跨职能便捷操作。

CI/CD 是什么|打造高效稳定开发团队的关键流程与工具选择

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](https://unsplash.com/@project2204?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash){:target="_blank"}

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 打包平台」希望这系列内容对你有所帮助。

最终成果

废话不多说,先上最终结果。

[Demo PR](https://github.com/ZhgChgLi/github-actions-ci-cd-demo/pull/11){:target="_blank"}

Demo PR

[Demo Web App](https://script.google.com/macros/s/AKfycbxk1nYhzfBzqny34rvBlxmcWMEQbWTL5a28mBmYId0NDaCZd0S-U3ytpBoTi2wZp0d6cg/exec){:target="_blank"}

Demo Web 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」这个词,先来回想一下一个初创什么工作流程都没有导入的开发团队,会是怎么工作的,大致简略为下图流程:

  1. 产品有一个 Bug,Developer T 从主分支开分支 fix/bug-c 分支进行修正,修正完后 Merge 回主分支。

  2. 紧接著 Developer Z 从主分支开分支 feature/a 做 需求 A,做到一半发现功能怪怪的, 查了一下才发现原来当前功能被改坏、测试也坏了 ,回头通知 Developer T 进行修正。

  3. 一切开发完毕后,Developer Z 使用他的电脑打包版本给 QA 测试,来来回回修正跟打包 ,最后没问题后将功能回到主分支。

  4. 很快地也到了 Sprint 尾声需要打包释出给使用者;Developer Z 先放下手上工作 ,协助从主分支打包给 QA 进行 Regression 测试,同样 来来回回修正问题跟重新打包 ,完成后打包送审 App。

  5. 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 人 一个月来计算

团队人数 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>{:target="_blank"}

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 工作 」:

[Demo Web App Form URL](https://script.google.com/macros/s/AKfycbw8SuK7lLLMdY86y3jxMJyzXqa5tdxJryRnteOnNi-lK--j6CmKYXj7UuU58DiS0NSVvA/exec){:target="_blank"}

Demo Web App Form URL

使用 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

本系列文章花费了大量的时间精力撰写,如果内容对您有帮助、对您的团队有实质提升工作效率与产品品质;欢迎请我喝杯咖啡,感谢支持!

[Buy me a coffee](https://www.buymeacoffee.com/zhgchgli){:target="_blank"}

Buy me a coffee

有任何问题及指教欢迎 与我联络


Buy me a beer

本文首次发表于 Medium (点击查看原始版本),由 ZMediumToMarkdown 提供自动转换与同步技术。

Improve this page on Github.

This post is licensed under CC BY 4.0 by the author.