技術文章
在 Ianvs 打造範例驗證 CI/CD:技術與協作筆記
分享 Ianvs 範例驗證系統的設計過程,包括分層檢查、回歸報告,以及如何提供更清楚的 CI 回饋。
透過 LFX Mentorship 專案,讓我有機會接觸 Ianvs 開源社群,並參與範例驗證 CI/CD 專案,負責替專案中的範例建立自動驗證流程。實作之後我才發現,這不只是一項 CI 工作,也包含許多溝通、取捨與協作。
這篇文章會介紹系統的設計方式,也整理我在開發與社群協作過程中學到的事。
先確認問題,再設計 CI
專案最初的問題很直接:範例是否能正常使用,往往只能靠貢獻者自行測試,或在會議中由維護者人工確認。當核心程式、相依套件或外部資源更新後,原本可執行的範例可能失效,但問題不一定會立刻被發現。
一開始我直覺認為,只要在 GitHub Actions 中把範例全部跑一遍即可。但討論後才發現,許多範例需要大型模型、資料集、GPU、token,甚至依賴外部服務。若每個 Pull Request 都完整執行所有範例,CI 很可能變慢、不穩定,而且成本過高。
最後,我們把驗證設計成由淺至深的分層流程:
這種設計讓流程能在速度與可靠性間取得平衡。若以 表示檢查成本、 表示可偵測風險,目標是在 CI 預算 內選出有效的檢查集合 :
好的設計不必承諾解決所有問題,而是要清楚知道自己能解決什麼、不能解決什麼,並先穩定地解決最重要的問題。
CI 的重點是找出新問題
在長期維護的開源專案中,部分既有範例可能早已因環境或外部依賴而失敗。如果 CI 只回傳一份大量紅色錯誤,貢獻者很難判斷:哪些問題是原本就存在的,哪些才是自己這次改動造成的。
因此,我們加入 Regression Summary,比較基準分支與 Pull Request 分支的測試結果。報告會分別標示新增錯誤、既有錯誤與已修復的問題。
| 結果 | 意義 | 後續行動 |
|---|---|---|
| 新增失敗 | 由本次改動引入 | 合併前調查 |
| 既有失敗 | 基準分支已存在 | 獨立追蹤 |
| 已修復 | 基準失敗、PR 成功 | 呈現改善成果 |
我們也持續調整報告內容。除了 Pass/Fail 與錯誤數量,報告也會提供容易理解的錯誤訊息、相關檔案、詳細結果與 log。貢獻者不會只看到紅色叉號,而能直接知道下一步該查看哪裡。
def classify(base: bool, pull_request: bool) -> str:
if base and not pull_request:
return "new-failure"
if not base and pull_request:
return "fixed"
return "unchanged"
錯誤訊息也是使用體驗的一部分
以前我把測試報告視為程式輸出;這次才真正體會到,它同時也是使用者介面的一部分。
對熟悉系統的人來說,簡短的錯誤代碼可能已經足夠;但對第一次提交 Pull Request 的人而言,這些詞並不能告訴他問題是什麼。當我們把訊息改得更接近使用情境,並提供後續追查的路徑,CI 才真正降低了溝通成本。
這也提醒我,檢查流程是寫給電腦執行的,但結果必須讓人看得懂。特別是在開源社群裡,清楚的回饋能大幅降低貢獻者與維護者之間的溝通成本。
讓程式架構與文件保持一致
實作途中,我們不只調整程式,也重新整理模組邊界、目錄結構與命名方式。例如,將觸發條件、驗證器與共用工具分開,讓 GitHub Actions workflow 與實際驗證邏輯各自放在適合的位置。
這些整理不只是為了讓目錄更好看。當架構圖、提案文件與程式碼使用相同的概念和名稱,新加入的貢獻者會更容易找到入口,也能更快理解每個模組的用途。demo 與使用說明也很重要,因為它們能讓維護者從使用者角度確認整套流程是否合理。
理解回饋背後的原因
每週會議中,許多回饋看起來很細:名稱是否清楚、報告要不要多一句解釋、流程圖如何畫得更直觀、資料夾應該放在哪裡。起初我會把它們當成待辦清單;後來才理解,這些意見背後都在回答同一個問題:未來的人能不能理解並維護這套系統?
當我開始理解每項修改背後的使用情境,而不是只完成表面的改動,設計決策就變得更有方向。我也更願意在討論中主動提出問題,而不是只等待別人給答案。
預先考慮無法控制的失敗
模型與資料集下載、cache 策略、runner 環境,以及外部服務的穩定性,都會影響驗證結果。有些失敗與貢獻者的程式碼無關,卻仍可能出現在 CI 中。
我們無法排除所有外部因素,但可以讓問題來源更容易判斷。分層檢查負責處理可控制的部分,比較不同分支的結果可以辨識新增問題,log 與 artifacts 則保留後續調查需要的資訊。暫時無法解決的限制也應該清楚記錄,而不是隱藏起來。
先交付一個實用的版本
開源專案不會等到所有條件都完美才開始。外部服務可能中斷、規格可能調整、需求也可能隨社群討論改變。這次經驗讓我學會把「尚未完成」與「沒有價值」分開看待。
只要系統已經能提供可靠且有用的回饋,就值得先讓貢獻者開始使用,再根據實際情況逐步改善。比起追求一次到位,一個容易驗證、能清楚說明的第一版更有價值。
這次學到的事
這個專案最後交付的不只是一套自動驗證機制。貢獻者能在 Pull Request 中理解改動造成的影響,維護者也能把注意力放在本次變更新增的問題上。
技術上,我學到如何設計分層驗證、比較不同分支的結果,以及撰寫更容易理解的 CI 報告。更重要的是,我再次體會到工程不只關於程式碼,也需要考慮溝通方式、共同理解,以及下一位維護者是否能順利接手。
如果想進一步了解專案、範例與後續開發,可以前往 Ianvs GitHub repository。