為什麼最後不用 Reusable Workflows: GitHub Actions 可讀性、維護性與操作面取捨
我原本以為把 shared logic 抽成 reusable workflows 會比較乾淨。
結果實際做完之後, 我最後把它們又收回到入口 workflows, 只保留 composite actions。不是因為 reusable workflows 不能用, 而是因為它在這個 case 裡, 沒有帶來我真正想要的「乾淨」。
這篇把我最後的取捨整理下來。
一開始為什麼會想用 reusable workflows
理由其實很合理。
如果 deploy-dev 和 deploy-prod 都有這些步驟:
- test
- build
- migrate
- terraform deploy
- health check
那直覺上就會想抽出兩條 reusable workflows:
|
|
然後入口 workflows 變成很薄的協調層。
這種設計看起來有幾個明顯優點:
- less YAML duplication
- one shared implementation path
- easier to update one common pipeline
在紙面上很漂亮。
問題不是功能, 是操作者體驗
真正讓我改主意的不是功能失敗, 而是操作面和可讀性。
GitHub Actions UI 會把 reusable workflows 也顯示成獨立 runs。這件事帶來兩個實際問題:
- 操作者會看到太多 workflows
- 責任歸屬會變得沒那麼清楚
我真正想要的 UI 是:
|
|
但用了 reusable workflows 之後, Actions 頁面會多出內部 workflow 項目。技術上它們沒有壞, 但對平常操作的人來說會變得很雜亂。
可讀性不是只有 UI, 也包括原始碼
除了 UI, source code 的追蹤成本也變高。
當 deploy 出錯時, 你常常要來回跳:
- 入口 workflow
- reusable workflow
- composite action
- Terraform root
這條追查路徑不是不能走, 但會比直接在入口 workflow 讀完整 pipeline 還慢。
尤其當 workflow 又牽涉到:
- branch guard
- environment-scoped vars
- job-level permissions
- OIDC auth
- concurrency
如果這些東西拆在不同 workflow file, review 的認知負擔會變高。
我後來怎麼分辨什麼該抽, 什麼不該抽
我最後用一個很簡單的判準。
適合保留成 composite action 的情況
如果它只是 step group, 適合抽成 composite action。
例如:
- install uv and sync dependencies
- install Cloud SQL Proxy
這種東西抽出來很合理, 因為:
- no job graph
- no permissions model
- no environment decision
- no workflow identity ambiguity
適合留在入口 workflow 的情況
如果它本身就是 deploy pipeline 的主體, 我現在更傾向留在 入口 workflow。
例如:
- build and push image
- run migration
- terraform plan and apply
- health checks
這些步驟跟 branch、environment、permissions、identity 都強相關。留在入口 workflow 比較容易審查和除錯。
這是一個 DRY vs clarity 的取捨
本質上這不是技術對錯, 是取捨。
| Option | Advantage | Cost |
|---|---|---|
| Reusable workflows | less duplication | worse UI and more indirection |
| Flat 入口 workflows | more explicit | some duplication |
| Composite actions | reuse step groups cleanly | cannot model full workflow graphs |
在我這次的 case 裡, 真正要優先的是:
- readable
- maintainable
- 乾淨的操作者入口面
所以我最後選的是:
- flat 入口 workflows
- composite actions for setup steps
- accept some duplication
什麼樣的 duplication 是可以接受的
不是所有重複都該消滅。
如果 deploy-dev 和 deploy-prod 都各自有一份:
- build step
- migrate step
- terraform apply step
這在某些 case 其實是可以接受的。
因為它換來的是:
- 每條 workflow 都能自成一體
- 每個環境路徑都很清楚
- 權限審查比較直觀
- 操作者不需要理解 workflow 的內部接線
對中小型 repo 來說, 這種重複常常比高度抽象更好維護。
什麼時候 reusable workflow 仍然值得用
我不會說 reusable workflow 不該用。
它在這些情況還是有價值:
- many repositories share the same workflow
- the workflow graph itself is the reusable asset
- UI clutter is acceptable
- 操作者根本不會直接碰 Actions 頁面
但如果你的要求是:
- Actions page must stay clean
- 面向操作者的 workflows 必須一眼看懂
- permissions must be easy to audit
那 reusable workflow 就不一定是最好的共用方式。
我最後的 workflow shape
我最後比較滿意的是這樣:
|
|
這個 shape 的好處是, 面向操作者的 workflows 很清楚, shared setup steps 也沒有變成大量 copy-paste。
結論
我這次最大的體會是:
less YAML is not always less complexity.
reusable workflows 可以減少重複, 但不一定會讓整個系統更容易理解。
如果你真正在乎的是:
- operator clarity
- reviewability
- permission visibility
- GitHub Actions UI 的整潔度
那 flat 入口 workflows + composite actions 很可能比 reusable workflows 更適合。