你可能在找的答案
- GitHub Actions macOS runner 很慢/卡在
Queued - iOS CI 建置失敗或一直 retry
- Xcode build 在 CI 逾時,本機卻正常
- Cloud Mac 跟 GitHub Actions 怎麼選
- CI pipeline 結果不穩、難以重現
若你維護 GitHub Actions 或 macOS 自架 Runner,2026 年最常聽到的抱怨其實很具體:排隊變長、Xcode 編譯時間飄、同一支 PR 反覆 retry、CI 時綠時紅。本文用四層展開——先對齊這些工程症狀,再說明 Agent 如何把 CI「循環化」,最後釐清 Cloud Mac 在其中的位置。標題裡的「CI 死了」留到文末 FAQ 再談;正文從你能直接對號入座的故障現象寫起。
1 · 第一層:2026 年 GitHub Actions 為什麼「變慢、變飄、變 flaky」
近半年我們接觸的 iOS/Flutter/macOS 團隊,回饋高度重疊——不是「CI 概念過時」,而是下面四類問題同時變多。
1.1 macOS runner 排隊(Queue)
在託管 macos-latest 上,Queued 時間經常大於真正 build 的時間。打開 job 時間軸:等 40 分鐘、跑 12 分鐘——團隊卻還在調 xcodebuild 參數。診斷公式仍是 wait time >> run time,詳見 macOS runner 排隊 Runbook。2026 年 queue 變長,一部分是 macOS 併發上限沒跟上 repo 裡的 job 數量;另一部分是 Archive/重任務佔槽,把 PR 快回饋一起拖進佇列。
1.2 Xcode build 時間波動
同一個 commit 重跑,CI 裡 Xcode 編譯有時 18 分鐘、有時 31 分鐘,本機 Mac 卻穩在 15 分鐘左右。常見因素疊加:runner 冷啟動、DerivedData 沒命中、CocoaPods 重新 resolve、映像檔裡 Xcode patch 跟本機不一致。單看像「快取沒設好」;但當 每次 retry 都是 cold 環境 時,波動會被放大成「CI 不可信」。
1.3 Retry 次數失控
除了 workflow 裡明寫的 retry-on-failure,愈來愈多團隊還有 隱式 retry:Agent 或 bot 讀 log → 改 patch → push → 再觸發 Actions。一支 PR 從「人 push 2 次」變成「機器 push 8 次」,minutes 帳單跟 queue 壓力同步上漲。你以為是 flaky test;其實是 同一支 PR 在 CI 裡被跑了多輪不同程式碼。
1.4 Flaky CI:時綠時紅,難以重現
經典 flaky:測試偶發逾時、模擬器啟動失敗、簽章鑰匙圈偶發鎖死。2026 年多了一層:Agent 每輪提交的 diff 不同,你很難回答「到底是測試 flaky,還是 Agent 改壞了別的東西」。Release 工程師最痛的一句:「昨晚 CI 綠了,今早同樣的 tag 又紅了。」
| 你看到的 | 常誤以為是 | 值得先查 |
|---|---|---|
| Job 長期 Queued | GitHub 掛了 | macOS 併發、Archive 是否進 PR |
| Xcode 時間飄 | 專案變大 | 快取、映像 Xcode 版本、cold start |
| 同一 PR 多次 run | 開發者亂 push | Agent/bot retry、concurrency 未設 |
| 時綠時紅 | 測試寫得差 | 每輪 commit 是否一致、環境是否漂移 |
2 · 第二層:原因不是「CI 變差」,而是 CI 被循環化了
上面四類問題,單獨修 queue、修快取、修測試,往往只能緩解一輪。把它們放在一起看,會出現一條共同線索:CI 不再是一次性驗證,而變成「失敗 → 修復 → 再跑」的循環。Agent 普及之前,這個循環主要在工程師腦裡(改程式、再 push);現在循環被寫進基礎設施——模型讀 log、出 patch、自動觸發 workflow。
典型鏈路已經很常見:
- PR 開啟 → CI 紅(測試/編譯)
- Agent 讀 Actions log → 產生 fix commit
- push → 新 workflow → 可能再紅 → 再 fix
- 直到綠了,或直到人叫停/token 用盡
名義上仍叫 GitHub Actions/CI;行為上已是 Agent retry loop。這時你面對的不再是「某次 build 失敗」,而是 多輪嘗試疊加後的機率結果——於是出現第一層那些症狀:queue 被多輪 job 塞滿、Xcode 時間因每輪 cold start 而飄、flaky 因為每輪程式碼跟環境組合都在變。
這裡才涉及一個稍抽象、但可操作的說法:經典 CI 假設流程是 確定性(deterministic) 的——同 commit、同環境,結果應可重現。Agent 循環之後,路徑變成 機率性(probabilistic) 的——第幾次嘗試才綠、中間改過幾版程式、是否誤觸 Archive,都帶隨機性。不是要你一定換平台,而是解釋為什麼「只加快取」解決不了全部問題。
| 維度 | 傳統 CI(單次驗證) | 循環化 CI(Agent retry loop) |
|---|---|---|
| 觸發次數 | 人 push 驅動,次數少 | 失敗自動再跑,次數 ×N |
| 程式碼版本 | PR 頭固定 | 循環中 commit 連續變化 |
| 失敗意義 | 目前程式有問題 | 可能是「還沒試夠」 |
| 成本 | minutes × 單價 | minutes + token + 環境 cold start |
GitHub 仍在優化 workflow、runner、快取——服務的是 單次確定性 job。當 repo 裡已經預設跑 Agent loop,這些優化有用,但擋不住「job 數量 × retry 輪次」的乘法效應。這也是標題說「GitHub 還沒意識到」的所指:產品敘事還在 CI/CD,用法已向 自動修復循環器 漂移。
3 · 第三層:結構變了——從 CI 流水線到 retry loop + 執行底座
把第一層症狀跟第二層原因對齊,結構變化可以概括成一句話:CI 從線性流水線,變成帶回饋環的執行系統。
圖 1 · 循環化 CI:Agent 決策 + Runner 執行 + 回饋環
舊模型:Code → Build → Test → Result,一步失敗整條線停。新模型:Code → Agent → Modify → Execute → Retry → … → Result,失敗是環的一部分而不是終點。GitHub 上的綠勾仍讓人安心,但語義變了——可能是第 4 次嘗試才綠,且中間 commit 已變。
這裡出現一個新詞,但含義很工程:execution substrate(執行底座)——Agent 可以隨便改程式,但編譯、簽章、上傳必須落在 一塊穩定、可重現的 macOS 執行面 上。Serverless job 太短,狀態帶不走;本機 Mac 會 sleep、會升級 Xcode;託管 runner 排隊且規格漂移。Cloud Mac 填的正是這層:持續在線、工具鏈可 pin、環境可快照——不是「遠端桌面」,而是 retry loop 裡 唯一應盡量保持 deterministic 的那一層。
執行權也在轉移:過去人寫 workflow,機器照做;現在人寫邊界(什麼能進 PR、什麼能 Archive、最多 retry 幾輪),Agent 在邊界內試路徑,人驗收最終結果。macOS/iOS 團隊對此最敏感——簽章與 Archive 不應在 retry 環裡無限重複,否則綠了不代表可發版。
4 · 第四層:用 Cloud Mac 穩住執行面(可立刻做的)
不必等 GitHub 改敘事,也不必推翻 Actions。針對循環化 CI,我們在 VPSSpark 端最常被驗證有效的,是下面四件事——也是 Cloud Mac 相對託管 runner 的差異化所在。
4.1 分池:限制 retry 的破壞半徑
PR 只跑 L0/L1(analyze、單測、模擬器建置),禁止 Archive 進 PR;發版、IPA、公證只在 main/tag 的隔離池跑。Agent 循環再瘋,也不會用 35 分鐘的 Archive 佔滿快池,導致全員 Queued。硬規則與案例見 CI Hard Rules;Flutter 雙池拓撲見 2 台 Cloud Mac 分 fast/archive。
4.2 Warm environment:別讓每輪 retry 都 cold start
持久化 PUB_CACHE、DerivedData、Pods 下載快取;Runner 開機自啟、7×24 在線。Agent 第 2 次 retry 不應重新 pod install 15 分鐘——否則 Xcode 時間波動會被誤讀成「專案變慢」。Cloud Mac 買的是 環境保持成本,而不只是單次 CPU 分鐘。
4.3 macOS execution substrate:固定工具鏈版本
用映像或 fvm pin Flutter/Xcode 大版本;Archive 機與快池 實體隔離,不共用 DerivedData。retry 每一輪應在 同一把 Distribution 憑證、同一套 CLT 上跑——這是 iOS CI 可稽核的前提。自架邊界參考 GitHub 官方說明。
4.4 Retry isolation:給 loop 設上限
workflow 層用 concurrency 取消同一 PR 的舊 run;為 Agent 觸發單獨設 timeout 與最大 push 次數;簽章機只允許 release 池存取。語法細節見 workflow 文件。目標不是消滅 Agent,而是 讓 loop 在可控邊界內轉。
macos-fast 快池,託管 runner 暫留 Archive;觀察 3 天 P95 queue 與 Xcode wall time 方差。快池穩定後再補第二台 Archive 機——與「2 台起步」系列一致,動機從排隊擴展為 Agent retry。
5 · FAQ
「CI 死了」是不是危言聳聽?
標題確實誇張,但指向的現象是真的:你的 pipeline 可能照常綠、PR 也在合,只是 「同一份程式、同一套檢查,每次跑出來的路徑跟結果不再穩定可預期」。我們說的「CI 死了」,不是說 GitHub Actions 不能用,而是經典 CI 那條假設——建置與驗證是 確定性流程——在 Agent 反覆改程式、反覆觸發 workflow 的情境裡已經站不住。更貼切的說法是:CI 還在,語義變了,從「持續整合」滑向「持續嘗試」。
GitHub 會因此改產品嗎?
會改,但節奏可能跟不上用法漂移。近期你仍會看到 workflow 優化、runner 擴容、快取改進——這些都服務 傳統 CI。Agent 相關能力(sandbox、呼叫稽核、按 token 計費)更可能逐步補進平台,而不是一夜之間重寫敘事。對團隊來說,不必等官方定義清楚再動手:在現有 Actions 上先把 PR/Archive 分池、限制 retry、鎖死簽章機,就是 Agent 時代最低成本的護欄。
Cloud Mac 跟託管 macOS runner 有什麼差別?
一句話:託管 runner 租的是「一次 job 的執行時間」;Cloud Mac 買的是「一塊長期穩定的環境」。偶爾發版、能接受排隊、job 短——託管 macos-latest 往往夠用。Agent loop 或高頻 iOS CI 則不同:需要 Xcode/憑證/快取 常駐、快池與 Archive 實體隔離、環境不被 sleep 或靜默升級打斷。Cloud Mac 的價值在後者——尤其涉及簽章、Archive、公證時,retry 每一輪都應在 同一把鑰匙、同一套工具鏈 上跑,而不是每次 cold start 碰運氣。
跟 OpenClaw/本機 Agent 是什麼關係?
不衝突,分層不同。OpenClaw、Cursor Agent、本機 Copilot 等負責「想改什麼、怎麼編排任務」——偏 Gateway 與排程。Runner/Cloud Mac 負責「在哪跑、用什麼環境跑」——編譯、測試、簽章、上傳。Agent 可以在本機改 patch,也可以在 CI 裡循環;但無論入口在哪,macOS 建置最終要落到一個可重現的執行面。把編排層跟執行層分開設計,才不會出現「Agent 很聰明,但每次 CI 都在陌生環境裡從頭來」的錯位。
第四層的下一步:用一台 Cloud Mac 固定執行面
前三層如果對你有共鳴——queue、Xcode 飄、retry 失控、flaky——第四層不需要一次到位。最常見路徑是:先 1 台 Cloud Mac 做 warm 快池,把 Agent retry 最傷人的 cold start 跟工具鏈漂移壓住;Archive 與簽章仍可按需隔離。Apple Silicon 低功耗適合長期在線;對 iOS/macOS 團隊,這比再加 GitHub minutes 包更直接對準「循環化 CI」的帳單結構。
若你正在對照本文做 PoC,VPSSpark Cloud Mac mini 可作為 macOS execution substrate 的起點——了解方案,先穩住環境,再讓 Agent 跑第 N 輪。