2026 Swift Strict Concurrency 遷移:在 Mac 雲 CI 上怎麼做對門禁——Sendable、CI-only flaky 與五步 Runbook

如果你是移動團隊技術負責人,2026 年很可能正在把工程推進到 Swift 6/Strict Concurrency 完整模式;卻頻頻遇到僅在 CI 上爆紅、本地卻很難復現這類「幽靈告警」。本文為讀者拆解三大根因、給出門禁決策矩陣與五步可抄 Runbook,並串聯站內 三種算力來源對照Simulator 並行 PR 流水線 兩篇長文的可讀順序。

2026 年團隊在 Mac 雲 CI 上對 Swift Strict Concurrency 做門禁討論的示意圖

本文要點

1. 痛點拆解:CI-only 告警為什麼偏偏找上你

在進入 Swift Strict Concurrency(嚴格並發檢查)深水區之後,很多問題不再「一眼能修」,而是表現為:同事筆記本上靜默通過,流水線卻穩定失敗。這類現象的根往往不在業務邏輯,而在環境與任務形態差異

  1. 工具鏈與時間片差異:CI Job 通常為 headless、`xcodebuild` 在無 UI Session 的條件下執行分析與索引;Swift 前端對並行調度極為敏感——當機器的節能核/性能核與本地開發機比例不同,@MainActor isolation 推導會出現「只差一條警告就失敗」的差異。
  2. 緩存熱度的冰火兩重天:DerivedData/模塊緩存若在本地常駐溫熱,Swift 對部分跨模塊Sendable 約束會走快速路徑;而 CI「冷起跑」或未命中緩存時,會觸發更激進的診斷路徑,從而在門禁門檻上出現「本地不報、遠端報」。這不是編譯器玄學,是可度量的輸入差異。
  3. 任務分叉:Smoke / Simulator / Archive 混在同一個標籤裡:當你在 PR Checks 上用輕量 Smoke,卻把 Archive 延後到夜間任務,兩者對並發模型的驗證深度不同;若未顯式分叉,就會把「歸檔才暴露的問題」誤判為 flaky。更多矩陣拆分思路請對照 Simulator 並行與 destination 文中的表格。

2. 決策矩陣:哪個模塊先門禁、何時允許暫緩

Strict Concurrency 遷移不是「一口開關打開」;工程上更健康的姿勢是按模塊劃片 + 可審計 PR。下表把常見策略壓縮成可貼進評審模板的語言(你可以直接複製列頭到工單系統)。若團隊還在評估「算力從何而來」,可先讀另一篇站內決策長文:GitHub Runner、Xcode Cloud 與專用 Mac 雲三者對照

策略維度先門禁的業務信號可先觀察窗的原因門禁外的配套動作
跨團隊協作的數據模型多處 UI/網絡層共享可變狀態純內部工具、低風險流量為該模塊拆分單獨 scheme 與-warnings-as-errors 開關
Actor 邊界清晰度已經出現野指針式「偶發卡住」日誌僅佔少量代碼路徑的邊緣特性為該路徑補最小可復現實驗與集成測試優先級
依賴庫升級節奏上遊已標明 Swift 6 兼容第三方尚未完成 Sendable 標註用 Package 覆蓋或二進位隔離層擋在邊界外
運行時成本歸檔/Test 任務耗時應進入預算表僅開發期一次性腳本在 CI 上對「並發檢查等級」分兩檔:PR 檔位與 nightly 檔位

矩陣的目的:把「感受」轉成可審計工單條件。

3. 五步 Runbook:從釘死工具鏈到壓平 flaky

  1. 釘死 Xcode 與 DEVELOPER_DIR:在專有 Mac Runner 上使用顯式sudo xcode-select -s或由基礎設施注入統一路徑;在任何 PR 模版中要求開發者粘貼xcodebuild -version輸出,門禁腳本再比對 semver。這樣能消掉九成「我本地預覽版你沒說」之爭。
  2. 分拆 Job:Smoke / Simulator / Archive 三條泳道:給每條泳道單獨的超時、重試與緩存鍵;避免把「重 Archive」綁在「輕 smoke」後拖垮開發者耐心。泳道參數語言與並發上限可直接復用 PR 並行文的清單。
  3. 對 DerivedData 設「軟預算 + 硬清理」:為磁碟水位設兩級閾值:軟閾觸發降級並發,硬閾觸發rm -rf 與冷啟動;把每次清理寫進指標,避免「為什麼忽然全員排隊」這種神秘事件。
  4. 對並發錯誤設「可診斷日誌包」:當-warn-concurrency 或完整模式失敗時,自動打包swiftc 依賴圖片段、關鍵模塊接口文本與 Runner 資源視圖;要求修復 PR 必須附該包,減少來回三次都找不對模塊的尷尬。
  5. 把「允許的不完美」寫進 ADR:若必須暫時保留nonisolated(unsafe) 或與第三方類型共存,記錄在架構決策表裡:負責人、復盤日期、風險半徑。半年後機器人自動開 issue——這比口頭承諾更接近工程真實。

你可以在 CI YAML 中用類似片段強調工具鏈對齊(節選示意,佔位符請改成團隊 scheme):

export DEVELOPER_DIR=/Applications/Xcode_26.app xcodebuild -scheme S clean test OTHER_SWIFT_FLAGS=-strict-concurrency=complete

4. 硬核參數:閾值、時間與磁碟水位

可把下面四條直接抄進 Grafana/值班手冊 KPI
  • 冷啟動首開牆鍾時間:在專有 M4/統一內存節點上,100k LOC 量級主工程的首次swift build 建議壓到不大於 420 秒(若長期飄高,多半是並發任務搶同一 NVMe——應回到 Job 分拆表)。該數字為經驗閾值,請以你團隊 backlog 校準。
  • Archive Job 獨享窗口:為歸檔任務獨佔 1–2 P-core 等量算力配額,避免與它共享機器的 UI Smoke 爭搶同一溫控預算;這比盲目加並行度更能降低 flaky。
  • DerivedData 軟閾:單節點 DerivedData不大於 240 GB(或磁碟的 70%)觸發自愈清理腳本;寫入 launchd plist 或由 Runner 鉤子觸發。
  • 門禁復跑策略:對確認為資源爭用所致的失敗,只允許同一代碼哈希下復跑最多 1 次,防止「無限重骰」掩蓋真正的數據競爭。

若同時使用 Xcode Cloud 與專有 Runner,請參閱對照文「接縫」:強定製腳本、長期緩存或對磁碟布局苛求的歸檔,通常落到可 SSH 的專用 Mac。

5. 站內交叉索引與延伸閱讀

在閱讀順序上可先讀:三種算力來源 定 SLA,再對照 Simulator 並行;最後再用本文門禁拆模塊——避免隊列與歸檔搶同一條流水線。

6. 選型收束:為什麼 Mac 獨佔雲勝過混雜池

一些團隊把 Job 投進共享溫控與盤的「泛 Mac 池」,短期帳單好看,但一旦並發診斷與 flaky 歸檔攪在一起,排障時間會上升:拿不到獨佔 NVMe/穩定隊列/可預期溫控,就難以分清告警來自代碼還是鄰機噪聲。專門為 Apple 工具鏈調校的 Mac 雲更接近辦公室自建 Runner:**獨佔算力 + 漂移少 + SSH 習慣可沿用**;在混雜池上與鄰機搶 IO,只會累積不可測的技術債。