CI/CD 實戰指南(一):CI/CD 是什麼?如何透過 CI/CD 打造穩定高效的開發團隊?工具選擇?
以 App (iOS) Team 為例,帶您從 0 認識 CI/CD 與導入後能帶來的實質價值。
ℹ️ℹ️ℹ️ Click here to view the English version of this article, translated by OpenAI.
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 實戰指南(一):CI/CD 是什麼?如何透過 CI/CD 打造穩定高效的開發團隊?工具選擇?
- CI/CD 實戰指南(二):GitHub Actions 與 self-hosted Runner 使用與建置大全
- CI/CD 實戰指南(三):使用 GitHub Actions 實作 App 專案的 CI 與 CD 工作流程
- CI/CD 實戰指南(四):使用 Google Apps Script Web App 串接 GitHub Actions 建置免費易用的打包工具平台
最終成果
廢話不多說,先上最終結果。
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 到最終完成前文的最終成果。
系列文章:
- CI/CD 實戰指南(一):CI/CD 是什麼?如何透過 CI/CD 打造穩定高效的開發團隊?工具選擇?
- CI/CD 實戰指南(二):GitHub Actions 與 self-hosted Runner 使用與建置大全
- CI/CD 實戰指南(三):使用 GitHub Actions 實作 App 專案的 CI 與 CD 工作流程
- CI/CD 實戰指南(四):使用 Google Apps Script Web App 串接 GitHub Actions 建置免費易用的打包工具平台
Buy me a coffee
本系列文章花費了大量的時間精力撰寫,如果內容對您有幫助、對您的團隊有實質提升工作效率與產品品質;歡迎請我喝杯咖啡,感謝支持!
有任何問題及指教歡迎 與我聯絡 。
本文首次發表於 Medium ➡️ 前往查看
由 ZMediumToMarkdown 與 Medium-to-jekyll-starter 提供自動轉換與同步技術。