團隊已在使用 GitLab(SaaS 或自管),但 iOS/macOS 建置仍卡在託管 macOS runner 排隊、筆電兼差,或另起 Jenkins。若以 VPS 維運 思維看待平台,本指南提供「像租節點一樣租 Mac」的路徑:七份檢核表凸顯 專用遠端 Mac 上 GitLab Runner 的真實摩擦,再以三方對照表比較 Jenkins SSH agent 與 GitHub Actions 自架 runner,接著是含註冊、標籤、快取目錄、併發與 .gitlab-ci.yml 草圖的六步交付 runbook,並交叉連結 runner、Jenkins、SwiftPM/Pods 磁碟治理 文章。
GitLab 文件讓 gitlab-runner register 看起來順暢,上線後時間卻常耗在 Apple 工具鏈狀態機 與併行磁碟互踩。用下列七項把「加一台 runner」變成可簽核的風險表。
把遠端 Mac 當 Linux runner:忽略 TCC、鑰匙圈與偶發 GUI 需求,首跑簽章會炸掉;請與 SSH 對 VNC 檢核表 一併審查。
以個人 macOS 帳戶註冊:睡眠、更新提示與桌面工作階段會破壞真正的無人值守流程;請用對齊 可重現建置 的專用 CI 使用者。
只依 CPU 核心規劃併發:Xcode 記憶體尖峰與 NVMe 寫入放大通常先咬人;若未分桶 DerivedData,兩個 job 可能互鎖 — 契約同 SwiftPM/Pods 磁碟治理。
忽視 runner 權杖與註冊衛生:把 config.toml 備份當明文散佈,輪替日佇列變紅時只剩錯覺式的安心。
複製貼上快取政策:糟糕的 cache: 金鑰會跨分支污染或永遠 miss;請依分支與鎖檔維度設計金鑰。
只把產物留在 runner 磁碟:沒有 GitLab 產物或物件儲存,磁碟與合規都會痛;保存週期應綁安全審查。
沒有「第一次需要人在場」的窗口:初始簽章設定檔在回到 headless 前,可能仍需一次性 VNC 或桌面確認;見 Fastlane + CI。
共同根因是把「遠端 Mac」當純算力,而非具 Xcode 指紋與鑰匙圈邊界 的主機。請像維護資料庫副本一樣維護映像指紋、工具鏈版本、清理水位與 runner 標籤契約。搭配 企業建置資源池:多專案共用主機時,GitLab tags 必須比「任一 Mac」更細,否則 resource_group 無法表達真隔離。
與 GitHub Actions 的差異不在「能不能編譯」,而在管線定義與事件來源:.gitlab-ci.yml 原生綁 MR 生命週期;Actions 綁 PR,但遷出 GitHub 成本高。若全押 GitLab,macOS 作 shell runner 通常比為 iOS 再養一套 Jenkins 方言一致;但內部編排審查仍可能由 Jenkins 勝出。下表鎖定權衡。
註冊前請讀 runner 指南 的快取與標籤段落:多數目錄契約可直接對應 GitLab cache 與 CI_PROJECT_DIR;僅觸發從 workflow 換成 pipeline。
沒有銀彈 — 您選的是編排心智模型與憑證邊界。請在審查中寫入三項 SLA:佇列延遲、可解釋的失敗、金鑰輪替成本。
| 維度 | GitLab Runner(macOS shell) | GitHub Actions 自架 | Jenkins SSH agent |
|---|---|---|---|
| 管線定義 | .gitlab-ci.yml 對專案/MR 原生;範本與 include 成熟 | 儲庫內 YAML 與 PR/Issue 事件強耦合 | Job DSL/Pipeline Groovy — 跨儲庫編排彈性高但風格漂移大 |
| 註冊模型 | 專案/群組權杖;config.toml 集中執行器與標籤 | 組織/儲庫 runner 權杖,設定相對標準化 | 控制器集中持有 SSH 憑證 — 需強化控制平面 |
| 併發與節流 | resource_group、parallel、runner 併發上限 | YAML 內矩陣與 concurrency | 標籤 + 節流外掛 — 彈性高但設定重 |
| 快取與產物 | 原生 cache/artifacts;壞金鑰會污染快取 | actions/cache 與產物生態豐富 | 常需 DIY 接物件儲存 |
| 最適合 | 以 GitLab 為中心、要 MR 管線與統一 runner 池的組織 | 以 GitHub 為中心、PR 驅動交付 | 多產品線、內部產物庫、簽核、混用 Git 託管 |
用 GitLab 的說法「像 VPS 一樣」租 Mac,等於買一個可註冊的 runner 設定檔:固定 SSH、可預期的磁碟層級,以及把 Xcode 指紋打進標籤的能力。
若 GitLab Runner 勝出,請把 tags 當一等公民:Xcode 次版本、是否允許沉重 pod install、是否跑 UI 測試,皆須明示。搭配 快照對長壽節點:長壽 runner 仰賴增量清理;金映像仰賴預熱映像與回滾冒煙測試。
若同時運作多套 CI,請統一 DerivedData 分桶,避免 GitLab job 在同一台遠端 Mac 踩到 Jenkins 或 Actions job — 分開 Unix 使用者或根目錄,別指望「排程錯開就好」。
順序很重要:先身分與目錄,再註冊與標籤,最後併發 — 請與 可重現建置 的指紋腳本對齊,讓 GitLab 驗證的是穩定簽章,而非僅「git clone 成功」。
建立專用使用者與工作根目錄:例如 /Users/ci/gitlab-runner,勿與個人 ~/Desktop 混用;SSH 僅限金鑰。
安裝 gitlab-runner:官方 macOS 套件或 Homebrew;二進位在 PATH 且可在服務帳戶(launchd)下執行。
執行 register:選 shell 執行器,提供 GitLab URL 與註冊權杖;以互動或非互動旗標固定 tag_list(例如 ios,shell,m4)。
第一個健康檢查 job:輸出 xcode-select -p、xcodebuild -version、swift --version 與磁碟快照;日誌作為 runner 驗收佐證。
在 .gitlab-ci.yml 明確指定 DerivedData:契約同 SwiftPM/Pods 磁碟治理 — 依專案分桶,避免預設共用路徑。
定義逾時、產物與清理:timeout、失敗保留,以及磁碟偏低時停線(監控 + 暫停 runner 的 API)。
stages: [build]
variables:
DERIVED_DATA: "$CI_PROJECT_DIR/.derivedData/$CI_PIPELINE_ID"
build_ios:
stage: build
tags: [ios, shell, m4]
timeout: 45m
script:
- xcode-select -p
- xcodebuild -version
- df -h
- xcodebuild -scheme "App" -configuration Release -destination "generic/platform=iOS" -derivedDataPath "$DERIVED_DATA" build
artifacts:
when: on_failure
paths:
- "**/*.xcresult"
expire_in: 3 days
提示:若管線亦上架商店,請讀 Fastlane + CI,並將建置使用者、鑰匙圈分割與 App Store Connect API 金鑰對齊 GitLab CI/CD 變數(遮罩 + 保護機密)。
GitLab 或 runner 升級時,以同一提交跑升級前後的 iOS 金絲雀 job,比較指紋輸出與建置時間分佈。對照 runner 快取:過鬆的 GitLab 快取金鑰會讓分支 A 污染分支 B 的 Pods 快取;過嚴則意味無止境的冷啟動 — 平台與產品須約定保留層級。
若供應商給固定 SSH 埠與非 root 使用者,請把連線參數集中在內部 runbook,而非散落的變數說明 — 輪替單點化。搭配 Jenkins + 遠端 Mac:SSH 基線(金鑰、防火牆、稽核)應跨 CI 堆疊單一來源,勿變成三套方言。
resource_group 與沉重相依安裝的節流常見錯誤是依「能塞幾個 xcodebuild 行程」定併發。pod install/SPM 解析與編譯尖峰常在不同階段 — 請在 .gitlab-ci.yml 以 resource_group 表達互斥資源或拆分 job。搭配 SwiftPM/Pods 治理:另限流沉重解析 job,別搶頻繁綠燈建置的槽位。
測試是另一隱藏維度:模擬器 UI 測試需要與純編譯管線不同的併發模型 — 請讀 XCTest 與模擬器 分片,並在 GitLab 以專用標籤或 runner 池隔離。
警告:磁碟低於安全水位時勿再塞佇列 — 先暫停排程並清理,否則半寫入的 Xcode/git 狀態比短暫排隊更貴。
若 runner 跨區域,請把區域編入名稱與標籤,並標示產物路徑,避免大型跨區傳輸被誤判為建置失敗。搭配 買斷對租用 TCO:延遲與出站流量一開始就應納入成本模型。
以下條目供內部對齊;請依儲庫規模與平行度調整閾值。
gitlab-runner --version、xcodebuild -version、使用 CocoaPods 時的 Ruby/Bundler、磁碟型號;變更後觸發金絲雀管線。僅供辦公室的 Mac 易受睡眠、網路抖動與工具鏈漂移所苦;Linux 無法承載 Apple 官方 iOS 工具鏈。在熟悉的 Web/MR 流程保留 GitLab,同時把 macOS 執行移到專用、常駐、可 SSH 連線的遠端節點,「管線真實單一來源」才從口號變契約。相較臨時自有硬體或脆弱的虛擬化 Xcode 堆疊,NodeMini Mac Mini 雲端租用往往較強,因為 SSH 端點、磁碟層級與可重現 runner 設定更清楚;規格與價格請見 雲端租價,上手收尾請用 說明中心。
請把本 runbook 綁到內部工具鏈變更層級:Xcode 修補/次版/主版對應不同簽核、金絲雀範圍與快取失效政策。
多數原生 iOS/macOS 團隊會為了與 Xcode、鑰匙圈、模擬器摩擦最低而先採 shell。Docker 適合容器化堆疊或更強隔離,但在 Apple 工具鏈上成本較高。硬體層級請先比較 雲端租價。
不要只看 CPU 核心:先量單一 job 尖峰 RAM 與 NVMe 寫入放大,再提高併發並看 P95;DerivedData 與相依快取分桶,沉重 pod install 另限流。上手問題請見 說明中心。
GitLab 將專案/群組 runner 權杖與 .gitlab-ci.yml 綁定;Jenkins 倚重企業編排與外掛;Actions 與 PR 緊密結合。請文件化事件來源、機密邊界與佇列 SLA,而非商標。延伸閱讀 Jenkins + 遠端 Mac 與 GitHub Actions runner。