2026年獨佔遠端 Mac iOS/macOS CI:SwiftPM 的 Package.resolved 到底該不該提交?
技術方案 2026-04-25

2026年獨佔遠端 Mac iOS/macOS CI:SwiftPM 的 Package.resolved 到底該不該提交?——可復現建置、快取預熱、CI 鎖版本漂移與 SSH 流水線決策矩陣 + FAQ

要把「依賴圖釘死」,還是讓解析器在 CI 上當場決定?本文以獨佔遠端 Mac 與 SSH 流水線的真實限制,拆解 Package.resolved、快取預熱與鎖漂移,並整理可寫進 Runbook 的決策矩陣與 FAQ。

1. 先把對象說清楚:你在鎖什麼?

Package.resolved 記錄的是 SwiftPM 解析後得到的精確版本與校驗資訊(含 Git revision 或 registry 版本等),用來復現同一張依賴圖。它與 Package.swift 裡寫的版本範圍不是同一件事:範圍是「允許解在哪一片」,resolved 是「這一次解在哪一點」。

在 Xcode 專案 + SPM 整合依賴的情境裡,常見路徑是專案目錄下的 xcworkspace/xcshareddata/swiftpm/Package.resolved(或等效位置);純 Swift Package 儲存庫則多在根目錄 Package.resolved。CI 腳本若只備份其一,會在「命令列能編過、Xcode 專案卻重新解依賴」這類問題上反覆踩坑。

2. 可復現建置:為什麼「應用類」儲存庫幾乎總是提交?

對可交付的 App/韌體/內部工具,業界共識是:提交 Package.resolved。如此 PR 與主幹、本機與 CI、本週與下週,都在同一張已解析的依賴圖上做 diff;出現「只發生在 CI」的迴歸時,你能先排除「解析器選了另一組相容版本」這一大類變因。

對對外發佈的 Swift Package 函式庫,常見做法是不提交 resolved(或僅把 resolved 當成本機/範例用途),以免把「函式庫的相容面」誤鎖成「某個消費端的一次解析結果」。若你維護的是函式庫,卻在獨佔 Runner 上跑「矩陣:多 Swift 工具鏈 × 多平台」,更應以 Package.swift 的語意與 CI 矩陣為主,而不是以單份 resolved 冒充相容承諾。

3. 快取預熱:提交 resolved 與「省下載」不是同義詞

獨佔遠端 Mac 的一大優勢是持久化磁碟:你可以在機器層級預熱 SourcePackages、Git 鏡像或自建 registry 代理。但快取命中依賴鍵(解析結果、工具鏈版本、registry 設定、甚至網路出口),而不是只靠「有沒有 resolved 檔」。

實務上:提交 resolved 減少的是解析不確定性;快取策略減少的是重複 fetch/checkout。兩者疊加最好——在 SSH 流水線上用固定的 -clonedSourcePackagesDirPath 或團隊約定的 DerivedData/SourcePackages 路徑,並在 Runbook 寫明何時允許清空快取(大版本 Xcode 升級、registry 遷移、資安事件)。若要一併收斂「git 拉取策略與 checkout 失敗分診」,可對照 獨佔遠端 Mac CI:Git blobless/淺克隆與 SSH checkout 的決策矩陣 + FAQ,把儲存庫端與依賴端放在同一套敘事裡。

4. CI「鎖版本漂移」:即使提交了也會動?

會。典型來源包括:Xcode/Swift 工具鏈升級、Package 使用版本範圍且上游打了新 tag(若你在 CI 上執行會改寫 resolved 的指令)、鏡像/registry 中繼資料變更,以及多根專案/多 workspace 下解析入口不一致。獨佔 Runner 若長期不升級工具鏈,會把問題延後成「一次性大爆炸」;託管機則相反,漂移更頻繁但更平均。

緩解策略:把工具鏈版本寫進驗收清單;對應用儲存庫在 CI 上校驗「resolved 是否被意外改寫」;對函式庫儲存庫用矩陣涵蓋解析邊界。並行多個 job 時,也要留意 DerivedData/Simulator 與解析目錄的爭用;可延伸閱讀 Xcode 測試計畫與並行測試在自託管 Runner 上的資源爭用與 SSH 無頭 flaky FAQ,把「鎖依賴」與「鎖執行緒/IO 預算」一起寫進 Runbook。

5. 決策矩陣(獨佔遠端 Mac + SSH 流水線)

情境 Package.resolved 理由摘要
iOS/macOS 應用主儲存庫 提交 強可復現;便於 PR 審查依賴變更
可複用 SwiftPM 函式庫(對外) 通常忽略 避免誤代表相容面;以矩陣驗證範圍
單倉多 App/多 workspace 每入口各一份並都提交 防止「CLI 與 Xcode 各解各的」
Fork/修補依賴 + 頻繁 rebase 提交 + 嚴格流程 衝突在 resolved 上可見;需約定合併策略
資安稽核要求「可釘死供應鏈」 提交 + 校驗 與 SBOM/allowlist 聯動;CI 防竄改

6. SSH 獨佔流水線上的硬建議

  • 顯式解析步驟:在 xcodebuild 前呼叫 -resolvePackageDependencies(或團隊封裝的等價物),失敗時日誌要落盤。
  • 非互動:SSH 工作階段無鑰匙圈彈窗;憑證走環境或預置鑰匙圈,避免首次解析卡住。
  • 併發 jobs:同一使用者下並行建置時,避免多個 job 爭用同一 DerivedData/SourcePackages 路徑——這是 flaky 好發區。
  • 升級日:Xcode 大版本切換後安排一次「冷啟動」建置驗收,再恢復快取。

若你仍在搭「從筆電 SSH 到第一台遠端 Mac」的最小路徑,請先在 Runbook 固定工作階段、工作目錄、非互動憑證三件事,再把同樣的紀律遷移到 CI(未必安裝同一套軟體,但原則一致)。

7. FAQ

CI 報錯「package resolution failed」優先看什麼?

工具鏈版本、網路/registry、Git 憑證,以及 Package.swift 與 resolved 是否指向同一解析入口(Xcode 專案 vs 套件根目錄)。

resolved 合併衝突怎麼解?

不要手改 JSON:在主幹合併後於本機或 Runner 上執行一次官方解析流程,產生新的 resolved 再提交;衝突本身代表依賴圖同時在變,應審查而不是「選一邊」。

不提交 resolved 會更快嗎?

偶爾省掉合併煩惱,但換來的是難以解釋的 CI 漂移;在獨佔長跑 Runner 上,這種漂移更難用「換一台乾淨機器」自證。

在 Mac mini 上把「鎖依賴」做成預設正確

依賴解析與編譯同樣是 CPU、磁碟與 I/O 的混合負載:Apple Silicon 的統一記憶體與頻寬,讓大型 SPM 圖在解析與增量編譯時較不容易掉速;macOS 作為官方工具鏈的一等公民,也少了跨平台模擬層帶來的額外變因。對需要長期無人值守的獨佔 CI 而言,macOS 的穩定性與極低當機率,意味著更少的「半夜 job 紅燈」。

若你希望把本文的快取策略、SSH 非互動解析與多 job 隔離真正跑穩,一台靜音、待機功耗低且能 7×24 放在機房的 Mac mini M4,往往比臨時拼湊的虛擬機池更省心——總持有成本也更容易算清。若你正在物色這樣一台「解析與建置都可靠」的主力節點,現在就是把它納入團隊基礎建設的好時機:前往 SSHMac 首頁瞭解方案。

遠端 Mac 建置方案

獨佔 Mac mini CI 友善

Apple Silicon 持久快取 SSH 原生
可復現建置從「鎖依賴 + 鎖環境」開始,硬體與系統堆疊同樣值得鎖。
立即獲取