🥑

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。
但我知道,這就是我選擇成為軟體工程師的方式。

系列: 從 Senior 到 Staff(7/13)

我從 Senior 到 Staff 的旅程

//////