CI 是軟體工程師的好朋友
- 發佈於
你記得自己第一次接觸 CI(Continuous Integration)是什麼時候嗎?
是從 onboarding 文件中讀到團隊採用 CI/CD 策略時?
還是在 local 起 server 的時候,卡在某個 pipeline error 才開始查 CI 的規則?
或是某次發 PR 被紅色的 ❌ 擋下,才發現原來這就是 CI check point 在發揮作用?
在運行得當的情況下來說,我想大部分的時候它都蠻安靜的,就像個恬靜的家庭成員。
不過相反的,如果跑得亂七八糟的時候,你可能會覺得他比高分貝的果汁機還吵。
第一個的地雷#
舉例來說,剛入職到這間公司後就發現主要專案的 formatter 設定是有問題的,這邊的「有問題」是指每個人的電腦生效後的結果是不一致的。
這有什麼重要的?你也許會這樣問。
照理來說 formatter 不會影響程式邏輯,不應該造成本質上的問題才對。
但實際上,同事們在這些檔案中改動的 PR 總是長出很難比照的 changed file,讓我在 review PR 時總要花力氣區分哪些是格式差異,哪些是真正要檢查的邏輯調整——這件事對我來說非常耗神。
Fast Agree on Our Disagreement#
我第一次還可以忍,但看得 PR 多了,這些額外的認知負擔讓我開始無法忽視。
所以我開始搜集同事意見,發現大家都覺得挺吵的。
技術上讓 formatter 設定一致並不難,難的是——為什麼會不一樣?
是因為機器設定不同?還是對寫作風格的偏好本就不同?
我在這次經驗中發現實用又有趣的合作策略是:
fast agree on our disagreement
不是所有人都喜歡一樣的排版風格,有人不在意 import 排序,有人堅持單引號、雙引號。這些小細節說大不大,卻是高頻噪音。
最低可接受的 baseline#
這種小事,能分配的討論時間不多。
與其追求共識後再行動,不如先行動,後共識。
所以我草擬了初步的 formatter 修訂計畫,針對幾個最容易導致 diff 混亂、卻能自動修復的規則列為優先,撰寫一份設定文件,並請大家在 local 設定完後截圖回傳確認一致性。
雖然這不是從零開始共同產出的共識,但它提供了具體的起點。
後續可以在這個版本之上逐步調整與迭代。
我將這個專案命名為:
最低可接受 formatter baseline
這也成為我開始對 CI 下刀的契機。
從 formatter 到 linter#
之後,我開始為團隊更新 coding guideline,補上過去逐漸形成的默契,也掃除已經過時的規範。一開始我並沒有發現 linter 有問題,只是覺得一些檢查太繁複,希望偷懶一點,讓機器幫我做事。直到開始檢查 linter 設定時才發現,有些已經不符合目前規範,甚至沒人知道來龍去脈。
我這才意識到:CI 工具是需要定期檢視與更新的。尤其當團隊已經形成共識的規則,更該交給工具自動執行,而不是讓 reviewer 靠肉眼逐條檢查。
所以我把能自動化的規則逐一實作進 linter 設定,讓 CI 來執行 enforcement,回到初衷:
正確的偷懶
讓錯誤更早暴露、提早修正,將 CI 當成 shift the problem to the left 的一環,而不是單純的打勾工具人。
新的挑戰#
事情進展到這裡,CI 已經大幅減少我的工作煩惱。
但複雜度永遠不會因為你處理完一次就停止。
後來我導入 monorepo 架構進行新服務的開發,模組之間互動變複雜了。
這代表我需要追蹤每次改動對哪些模組產生影響,但又不能讓開發者因此痛苦。
我找了:
- commit lint 作為語意檢查工具人
- 搭配 semantic-release 分析 commit message
- 自動對應 semantic version 並產生 CHANGELOG
這樣一來版本管理更清楚,也減少 manual release 的負擔。
這個專案成功後,讓 microservice 的價值被公司看見,也開始思考 platform engineering 的概念,真是可喜可賀。
讓 CI 成為守門員#
不過事情不會就此打住。
有幾次 product team 改動到底層邏輯,reviewer 沒有注意,導致出包。
老闆希望我提出解法。
我想到了 GitHub 的 CODEOWNERS 機制,可以為特定目錄或檔案指派專屬 reviewer。
當某段關鍵程式碼被改動,CI 就自動分派對應 reviewer,流程不再靠記憶或人情 tag,review check 更穩定。
分散責任#
但我也知道不能讓最懂的人變成最忙的人。
所以我將 CODEOWNER 指派到群組,例如 @platform-core、@design-system。
這樣可以:
- 彈性輪流審核
- 分散負擔
- 幫助新人融入、加快交接
- 減少單點風險
再搭配 GitHub 的保護規則,讓 PR 必須通過指定 reviewer 審核才能 merge。
這聽起來有點硬派,但這正是:
CI 作為守門員的角色重現
推動這套機制前,我其實有猶豫。
畢竟大家都忙,新流程綁太緊可能引起反感或卡住開發。
但我最後還是選擇:
一開始拉緊一點,之後再寬
因為從嚴到寬至少方向清楚;
從寬到嚴則常常卡在「為什麼現在要變?」
所以我在初期推動時附上一段備注
「如果有造成窒礙難行的部分,請回饋讓我知道,我好再做後續調整。」
這段經驗讓我理解:
流程設計不只是技術問題,而是結合人性、彈性與演進空間。
CI 的變更,雖然技術門檻不高,但背後的制度與文化轉換才是真正難的。
選擇改變的人,可以獲得讚美,但也得面對不同聲音,去理解它們背後的需求並解決它。
從這裡開始,我真正理解 CI 的價值:
不是只是自動化而已,而是把模糊地帶的事情釐清、具現化、可演進。
這一連串看似繁瑣的流程背後,核心只有一件事:
守護好人類有限的認知資源
把注意力放在需要判斷的地方,而不是可以自動化的瑣事上。
這個想法,帶我進入下一階段,開始有意識地看待軟體工程文化的設計。
最後的感想#
有被問過說,不會覺得這些事情很繁瑣嗎?
當然是蠻瑣碎的。
但如果我們不先排除這些低層的噪音,就沒辦法聚焦在真正重要的事。
而 CI 的價值,就是讓我們有空間把注意力放在值得的地方。
沒錯,我也還不知道這樣的想法轉換,會不會帶著我走向 Staff。
但我知道,這就是我選擇成為軟體工程師的方式。