沒有 Mac 時,iOS 流水線會在哪一步斷掉
很多團隊先用 Linux 跑單元測試和靜態分析,以為「CI 已經搭好了」——直到要出 TestFlight 包才發現: xcodebuild、codesign、notarytool 和 App Store Connect API 全部要求執行在 Apple 簽過名的 macOS 上。這不是裝個 Docker 映象能繞開的事: Archive 證書鏈、Swift 編譯器對 Apple Silicon 的最佳化路徑,都假定你腳下是一台真實 Mac。
因此每個有 iOS 產品的團隊,遲早要面對「誰來長期提供這台 Mac」。 常見選項有三條:GitHub 代管 macOS Runner、辦公室自購 Mac mini、雲端獨享實體機。 它們沒有絕對優劣,差別在於你對排隊時間的容忍度、月建置頻率,以及是否有人專職維護系統與證書。 本文聚焦第三條路的技術落地,但會先幫你判斷另外兩條路的適用邊界。
硬體:Mac mini M4 · 10 核 CPU · 16 GB 統一記憶體 · 256 GB NVMe · 1 Gbps 獨享頻寬(PixVPS 日本節點)。
系統:macOS 15 Sequoia,Xcode 16.4。樣例工程:SwiftUI 中型 App(約 11.8 萬行、含 3 個 Extension target)。
CI:GitHub Actions self-hosted runner 2.323.0;Jenkins 2.479 LTS + macOS agent。
簽名:Apple Distribution 證書 + App Store Connect API Key(Issuer ID + Key ID + .p8)。
託管 Runner、自建機房與雲端獨享:怎麼選
把一次完整 iOS 建置拆成三段——等機器、編譯連結、簽名上傳—— 你會發現不同方案的瓶頸完全不同。我們在同一 commit 上對比了 GitHub 代管 macos-14 Runner 與 PixVPS M4 獨享節點:託管 Runner 在 UTC 13:00–17:00 高峰平均排隊 22 分鐘才開始執行 job, 實際 xcodebuild archive 耗時 5 分 38 秒;獨享 M4 無排隊,Archive 全量建置 3 分 52 秒, 16 GB 統一記憶體在 clean build 時未觸發 swap。
| 建置路徑 | 典型月成本 | 排隊 / 併發 | 更合適的場景 |
|---|---|---|---|
| GitHub 代管 macOS Runner | 按分鐘計費(約 $0.08/min 起) | 共享池,高峰明顯排隊 | 月建置 < 500 分鐘、可接受等待 |
| 自購 Mac mini 放機房 | 硬體一次性 + 電費維運 | 獨佔,需自行維護系統升級 | 有固定辦公場所、全年高頻建置 |
| 雲端獨享 Mac(按天租用) | PixVPS $21.1/天起,無合同 | 實體機獨占,付款後即時可用 | 中小團隊、發版周集中建置、遠端協作 |
若你的痛點是「push 之後半小時才知道編譯有沒有過」,瓶頸往往在排隊而非 Xcode 本身。 把 Runner 固定到一台隨時線上的獨享 Mac,是讓反饋迴路縮短的最直接手段。
遠端 Mac 節點環境初始化四步清單
PixVPS 交付的 Mac mini 已預裝完整 macOS 並授予管理員權限。開通後透過 SSH 或瀏覽器 VNC 登入, 建議按固定目錄規範存放證書與描述檔案,避免不同 Runner 指令碼各自找路徑。 以下四步是我們每次新節點初始化時的標準清單。
- 01 安裝 Xcode 並接受許可
從 App Store 安裝 Xcode 16.x,執行
sudo xcodebuild -license accept與xcodebuild -runFirstLaunch。驗證:xcodebuild -version輸出預期版本號。 - 02 匯入 Distribution 證書與描述檔案
將 .p12 放到
~/certs/,用security import寫入專用鑰匙串~/Library/Keychains/ci.keychain-db;.mobileprovision 放入~/Library/MobileDevice/Provisioning Profiles/。 - 03 配置 App Store Connect API Key
在 Apple Developer 後台建立 API Key,將
AuthKey_XXXXXX.p8存至~/private_keys/,上傳 TestFlight 時用altool或 Fastlanepilot upload,繞開互動式雙因素認證。 - 04 首次全量 Archive 並保留 DerivedData
克隆倉庫後本地跑通一次 Release Archive,確認簽名鏈路無報錯。保留 DerivedData 可使後續增量建置節省約 30–45% 時間。
在 ~/.zprofile 或 Runner 啟動腳本里統一匯出 KEYCHAIN_PATH、P8_KEY_PATH、DEVELOPER_DIR, 讓 GitHub Actions 與 Jenkins 共用同一套引用,減少「本地能編、CI 找不到證書」的來回排查。
GitHub Actions 自架 Runner:從註冊到 workflow
自架 Runner 註冊完成後,workflow 透過 label 把 job 精確派發到這台雲端 Mac。 操作路徑:倉庫 Settings → Actions → Runners → New self-hosted runner, 選擇 macOS ARM64,按頁面提示下載 actions-runner 包後執行:
./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO --token RUNNER_TOKEN --labels macos-m4,pixvps,ios-build --unattended
註冊成功後安裝為系統服務:sudo ./svc.sh install → sudo ./svc.sh start。 workflow YAML 中指定 runs-on: [self-hosted, macos-m4]。 典型 iOS job 步驟鏈:檢出程式碼 → 解鎖 CI 鑰匙串 → xcodebuild archive → xcodebuild -exportArchive → Fastlane upload_to_testflight。 我們在 M4 節點上從 push 觸發到 TestFlight 處理完成平均 約 10 分鐘,本地建置與上傳僅佔 5–6 分鐘。
Runner 能訪問倉庫原始碼與簽名金鑰,務必限制 collaborator 權限、定期輪換 registration token, 避免在 fork 來的 PR 上自動觸發帶金鑰的 workflow。 多專案共用一台節點時,可為不同倉庫註冊不同 Runner,或配合 OpenClaw 沙箱限制 Agent 的檔案系統訪問範圍。
Jenkins macOS Agent 彈性連線
若團隊已有 Jenkins 控制器(可執行在 Linux 上),macOS 建置能力透過 Agent 節點接入。 在雲端 Mac 上安裝 JDK 17,下載 agent.jar,以 LaunchDaemon 方式常駐, 控制器透過 SSH 或 JNLP 下發建置任務。
Jenkins 的優勢在於視覺化流水線與外掛生態:Credentials Binding 注入鑰匙串密碼、 AnsiColor 日誌著色、建置產物歸檔到 Artifactory 等。 典型 Pipeline 在 stage('Archive') 呼叫 sh 'xcodebuild ...', 在 stage('Upload') 呼叫 Fastlane。 與 GitHub Actions 相比,Jenkins 更適合多分支、多環境、需要人工審批閘門的企業內部流程。
雲端 Mac 按天租用可當作「彈性 Agent」:發版周開通節點掛載 Jenkins,淡季釋放, 不必為全年 365 天維運一台機房 Mac。固定 DEVELOPER_DIR 避免多版本 Xcode 切換混亂, 是 Jenkins 環境最容易被忽視的穩定性細節。
Archive、Export、TestFlight 全命令列管線
無論 GitHub Actions 還是 Jenkins,最終產物鏈路一致:Archive 生成 .xcarchive → Export 生成 .ipa → 上傳 App Store Connect。 命令列方式是 CI 的標準做法,不依賴 Xcode GUI。
Archive 示例(Release、指定 scheme):
xcodebuild archive -workspace MyApp.xcworkspace -scheme MyApp -configuration Release -archivePath build/MyApp.xcarchive CODE_SIGN_STYLE=Manual PROVISIONING_PROFILE_SPECIFIER="MyApp AppStore"
Export 需配套 ExportOptions.plist(method 設為 app-store):
xcodebuild -exportArchive -archivePath build/MyApp.xcarchive -exportPath build/export -exportOptionsPlist ExportOptions.plist
上傳 TestFlight(API Key 方式,適合無人值守):
xcrun altool --upload-app -f build/export/MyApp.ipa -t ios --apiKey KEY_ID --apiIssuer ISSUER_ID
M4 的 10 核 CPU 使 Swift 併發編譯明顯快於舊款 Intel CI 機; 若工程含大量 Swift Package 依賴,建議在 workflow 裡快取 ~/Library/Developer/Xcode/DerivedData 與 SourcePackages 目錄, 第二次建置起耗時可再降三分之一左右。
無人值守簽名:鑰匙串故障排除手冊
SSH 或無頭 Runner 上 codesign 失敗,絕大多數情況與鑰匙串有關,而非證書本身過期。 建置指令碼開頭建議固定執行解鎖與授權:
security unlock-keychain -p "$KEYCHAIN_PASSWORD" ~/Library/Keychains/ci.keychain-db
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" ~/Library/Keychains/ci.keychain-db
密碼透過 GitHub Secrets 或 Jenkins Credentials 注入,切勿明文寫入倉庫。 若報錯 errSecInternalComponent,先檢查鑰匙串是否設為預設、codesign 是否被加入信任列表。 若 altool 上傳卡在認證,核對 API Key 的 Issuer ID 與 .p8 檔名是否匹配。
另一個常見坑是 Provisioning Profile 與 Bundle ID 不一致——Archive 階段不報錯, Export 階段才失敗。建議在 CI 里加一步 security cms -D -i profile.mobileprovision 列印 UUID, 與工程裡的 PROVISIONING_PROFILE_SPECIFIER 交叉核對。
按發版節奏租用雲端建置機
獨立開發者和小團隊常陷入兩難:需要 macOS 建置,卻不想為了一台 CI 機租辦公室、拉專線、處理斷電與系統升級。 公有云 Linux 虛擬機器無法滿足(沒有完整 macOS 與 Apple 簽名鏈); 把 Mac mini 放家裡又面臨上行頻寬不穩、IP 變動、誤關機等風險。
PixVPS 提供獨享實體 Mac mini M4:不做虛擬化、不超售, 每台機器 16 GB 記憶體與 1 Gbps 獨享頻寬,付款後 1–5 分鐘自動開通。 五地節點——新加坡、日本、韓國、中國香港、美國東部——可按使用者分佈選擇; 面向日本市場的 App 可選東京節點,縮短上傳 TestFlight 時的跨境延遲。
計費按天 $21.1、按周 $57.1、按月 $105.7,無長期合同。 發版密集的一週開通節點掛載 Runner,日常維護期釋放,往往比全年自購機器加電費更划算。 需要多機並行 Archive 時,可選購 Thunderbolt 5 並聯服務組成 80 Gbps 叢集,適合大型 monorepo 或多 App 矩陣。
- 01 在 PixVPS 選擇節點並開通
登入控制台選區域與租期,付款後 SSH 憑據與 VNC 入口自動下發。連線教學見幫助中心。
- 02 按第三節完成 Xcode 與簽名基線
把鑰匙串路徑、API Key 路徑寫入環境變數,供 GitHub Actions / Jenkins 統一讀取。
- 03 註冊 Runner 並跑通首次 pipeline
先 Debug 建置驗證編譯,再切 Release Archive + TestFlight,把 Fastlane lane 固化進倉庫。
| 團隊形態 | 建議做法 | 雲端 Mac 角色 |
|---|---|---|
| 獨立開發者,月發版 1–2 次 | 發版日按天租用 + 手動 Archive | 臨時建置機,用完即釋 |
| 5–15 人,每天多次 push | 常駐 self-hosted Runner | 按月租用,獨佔不排隊 |
| 已有 Jenkins,缺 macOS Agent | 雲端 Mac 作彈性 Agent | 峰值擴容,避免新購硬體 |
| 多 App 矩陣 + 夜間批次建置 | TB5 叢集並聯 | 多台 M4 並行 Archive |
iOS CI/CD 的門檻不在 Xcode 選單欄,而在穩定可預期的 macOS 算力 + 單一可信的簽名環境。 公共 Runner 適合低頻建置;自建機房適合有維運能力的成熟團隊; 雲端獨享 Mac 填補了「不想排隊、又不想買機器」的中間地帶。 把編譯搬到雲上之後,本地 MacBook 可以專心寫程式碼,而不是在深夜被 CI 任務搶走風扇與記憶體。
給你的 iOS 流水線一台不排隊的 macOS 建置機
PixVPS Mac mini M4 獨享節點:完整 macOS 與 Xcode、16 GB 統一記憶體、 SSH / VNC 連線,可掛載 GitHub Actions 與 Jenkins Runner,按天 $21.1 起。