工程筆記

Xcode 託管建置與自管雲端 Mac 如何選

Xcode 託管建置與自管雲端 Mac 如何選

Xcode 託管建置與自管雲端 Mac 如何選

團隊已經有一條可正常運作的 iOS 流水線,但每次新增相依套件、切換 Xcode 或調整簽章設定後,都會再次爭論同一個問題:應該繼續使用託管建置,還是將工作放到自管雲端 Mac 上執行。不要先比較單次建置快了多少秒。真正影響長期成本的,是環境能否重現、快取是否可控、失敗現場能否保留,以及工程師需要承擔多少維運工作。

先將工作負載分成三類

先統計最近兩週的工作,而不是憑印象選擇平台。建議依合併檢查、封存發布與臨時診斷三類記錄。合併檢查通常生命週期短、輸入明確,失敗後可以重新執行;封存發布涉及簽章資料、產物保留與嚴格的版本固定;臨時診斷則要求工程師進入相同環境重現問題。

至少記錄以下資料:

項目 需要記錄的內容 判斷目的
工具鏈 macOS、Xcode、Ruby、套件管理器版本 判斷固定環境的難度
輸入 提交編號、鎖定檔、建置參數 判斷工作能否重現
狀態 佇列、執行、上傳、清理耗時 找出真正的瓶頸
現場 日誌、result bundle、封存產物 判斷故障鑑識能力
快取 路徑、大小、命中條件、失效方式 判斷長期效益

單次成功不代表流程穩定。至少以同一個提交連續執行三次,再使用一個只修改業務原始碼、不變更相依套件的提交,重新測試快取行為。

建立統一的環境指紋

兩種方式都應使用同一份環境檢查指令碼。不要只輸出 xcodebuild -version,還要記錄系統版本、目前的開發者目錄、SDK、Ruby 與套件管理器狀態。環境指紋檔應作為每次工作的普通產物保存;發生失敗時,先比較該檔案,再檢查業務程式碼。

#!/bin/zsh
set -euo pipefail

mkdir -p artifacts
{
  sw_vers
  uname -m
  xcodebuild -version
  xcode-select -p
  xcrun --sdk iphoneos --show-sdk-version
  ruby --version
  git --version
} > artifacts/environment.txt

export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
xcodebuild \
  -workspace App.xcworkspace \
  -scheme App \
  -configuration Release \
  -derivedDataPath "$PWD/.build/DerivedData" \
  -resultBundlePath "$PWD/artifacts/App.xcresult" \
  build

DEVELOPER_DIR 不應指向尚未核對的路徑。自管環境可以保留多個 Xcode 版本,但流水線必須明確選擇;託管環境則應在工作開始時驗證實際版本,不相符就儘早結束。如此可避免工作一直執行到封存階段,才暴露 SDK 差異。

分別驗證快取、簽章與並行執行

不要搬移整個目錄作為快取

快取鍵至少應包含 Xcode 主要版本、架構與相依套件鎖定檔摘要。SwiftPM、CocoaPods 與建置中間目錄應分開管理,因為它們的失效條件不同。不要封裝並還原整個使用者目錄,否則舊權限、暫存檔與不可見的設定也會一併進入新工作。

自管雲端 Mac 適合需要長期保留大型相依套件快取的流水線,但必須為每個儲存庫配置獨立工作目錄,並定期驗證刪除快取後仍可完成完整建置。託管建置的快取生命週期通常由平台控制;在工程設計上,應將快取視為最佳化手段,而不是成功執行的必要條件。

簽章資料只在工作期間可見

簽章資料應在工作開始時由受控儲存空間注入,完成後立即移除暫存副本。日誌不得輸出密碼、金鑰內容或完整檔案路徑。無論採用哪種方式,都必須驗證失敗分支同樣會執行清理,而不只是成功分支。

並行測試應從兩個工作開始,觀察它們是否共用 DerivedData、模擬器、Keychain 或固定連接埠。只要存在共用的可寫入狀態,提高並行數就可能放大偶發故障。

透過故障演練測試可復原性

不要等到真正的發布失敗後,才驗證復原流程。可以設計四種非破壞性演練:刻意指定不存在的 scheme、刪除一個相依套件快取、讓測試案例回傳失敗,以及在封存前終止工作。每次都要檢查結束代碼、日誌末尾、result bundle、臨時簽章資料與工作目錄狀態。

託管建置應著重確認日誌是否足以說明失敗原因、環境是否仍可重現,以及重新執行時輸入是否完全一致。自管雲端 Mac 還要確認殘留程序、掛載目錄與連接埠不會汙染下一個工作。建議每個工作使用唯一目錄,並透過退出掛鉤回收子程序。

workdir="$(mktemp -d "$PWD/.job.XXXXXX")"
cleanup() {
  jobs -p | xargs -r kill 2>/dev/null || true
  rm -rf "$workdir"
}
trap cleanup EXIT INT TERM

清理指令碼必須先在測試目錄中驗證,避免過於寬泛的萬用字元影響其他工作。需要保留的日誌與建置產物應先複製到獨立的 artifacts 目錄,再執行回收。

依控制權而非口號做決定

如果專案使用一般相依套件、工作時間短、失敗後允許直接重新執行,而且團隊不希望維護機器狀態,託管建置通常更合適。如果需要固定多個 Xcode 版本、長期重複使用快取、執行特殊工具、進入現場診斷,或讓長時間工作持續執行,自管雲端 Mac 更容易建立清楚的邊界。

兩者也可以拆分使用:合併請求執行輕量測試,穩定分支則在自管環境中完成封存與深度診斷。重點是兩邊共用同一套環境指紋、鎖定檔、建置進入點與產物命名,避免形成兩條互不相容的流水線。

最終驗收不應只看最快的一次,而要檢視多次執行的成功率、環境差異數量、刪除快取後的可復原性、失敗證據的完整程度,以及需要人工介入的步驟。將這些結果寫入儲存庫中的決策記錄,並約定在 Xcode 主要版本、相依套件體系或工作規模發生變化後重新評估,選型才不會變成永久不變的假設。

常見問題

託管建置一定比自管雲端 Mac 省事嗎?

不一定。標準化專案通常較省維護;若要固定 Xcode、保留長期快取或深入調查失敗現場,自管環境通常更直接。

團隊能同時使用兩種建置方式嗎?

可以。可由託管建置執行合併檢查,再將需要穩定快取、複雜簽署或完整日誌的封存任務交給自管雲端 Mac。

選型前最重要的驗證是什麼?

用相同提交、鎖定檔與建置命令重複執行,比較成功率、環境差異、快取命中、日誌完整度及失敗後的復原時間。

VMDebug 雲端 Mac

需要一台由單一訂單獨享的實體 Mac mini?

核對 M4 與 M4 Pro 兩種配置、四種租用週期及 5 個可選節點,再依工作流程選擇裝置。

選擇配置並訂購