macOS GitLab Runner 部署不能以「控制台顯示在線」作為完成標準。你應在本週先準備一台可長期登入的真實 Mac,使用專用普通帳戶與 Shell executor,依序驗證重啟恢復、Xcode 建置、簽名金鑰隔離及真實流水線;任何一項未通過,就不要把它當成正式 CI 節點。
正在把 iOS 專案從手動打包遷移到 GitLab CI 的開發者,應優先確認第一條可重現流水線。維護跨平台 CI 基礎設施的 DevOps 工程師,應特別檢查使用者會話、權限邊界與故障恢復。若團隊沒有可長期在線的 Mac,本文也能幫你判斷遠端 Mac 的配置、租期與交付要求。
01先用時間表判斷部署是否具備條件
動手前:先確認任務真的需要 macOS
macOS Runner 適合承接依賴 Xcode、Apple SDK、iOS 模擬器或程式碼簽名的工作。普通 Linux 建置、單元測試或一般後端編譯,不應為了「看起來統一」而搬到 Mac 上。
你可以先按下列條件分流:
- 只需要一般編譯與測試:留在 Linux Runner。
- 需要
xcodebuild、iOS SDK 或 Simulator:使用 macOS Runner。 - 需要封裝、歸檔或發佈:使用受保護的專用 macOS Runner。
- 來源包含不可信分支、外部貢獻或可修改 CI 腳本:不可與簽名憑據共用同一台 Runner。
GitLab 官方指出,Shell executor 的工作會在本機直接執行,隔離能力有限;工作可以取得 Runner 使用者的權限,甚至影響同一主機上的其他專案。它只適合可信程式碼與你信任的主機。參考 GitLab Shell executor 安全說明。
上線前決策清單
在你註冊 Runner 之前,先逐項勾選。只要前四項有一項不成立,就應先補齊條件;最後一項不成立,則不要接入發佈任務。
- [ ] 專案確實需要 Xcode、Apple SDK、Simulator 或程式碼簽名。
- [ ] Mac 能長期在線,且有明確的重啟與人工恢復安排。
- [ ] Runner 使用專用普通帳戶,不沿用個人開發帳戶。
- [ ] 可信分支與外部貢獻的執行範圍已分開。
- [ ] 已決定哪些工作只做建置測試,哪些工作可以讀取簽名憑據。
- [ ] 已準備真實專案作為驗收,不會只用空專案測試。
- [ ] 失敗後能清理工作目錄、臨時檔案與敏感產物。
完成後,你的部署方案可以按這個判定:
- 全部勾選:可以開始註冊與建立最小流水線。
- 只有工具鏈未完成:先安裝並驗證 Xcode,不要接入簽名。
- 使用者會話未解決:先測試重啟恢復,不要宣稱 Runner 可長期運作。
- 程式碼信任邊界未解決:只允許可信專案,暫停發佈任務。
- 沒有真實驗收專案:可以做技術驗證,但不能列為生產節點。
上線證據:不要只看 Runner 狀態
正式使用前,至少要留下以下證據:
- 一次真實專案的無簽名建置成功。
- 一次真實測試任務成功,並保留退出碼與測試結果。
- Mac 重啟後 Runner 能恢復接單。
- 簽名憑據不在 Git 儲存庫、建置日誌或公開產物中。
- 工作目錄能在失敗後清理,舊產物不會干擾下一次建置。
這些驗收項目比單純查看 GitLab 控制台的「在線」標記更可靠。控制台只能證明 Runner 曾經連上,不代表 Xcode、鑰匙串或實際專案能正常工作。
02第一小時:帳戶、架構與 Runner 註冊
使用專用普通帳戶,不要沿用個人開發帳戶
建議建立一個只承接 CI 的 macOS 使用者,例如 ci-runner。它不應是日常開發帳戶,也不應擁有不必要的管理員權限。
這樣做可以降低三類風險:
- 個人 SSH 金鑰、瀏覽器登入狀態和 CI 工作混在一起。
- CI 腳本意外讀取你的主目錄資料。
- 發佈憑據與日常開發活動共用同一個信任邊界。
Shell executor 不是容器。它會直接使用 Runner 帳戶的檔案、環境變數與工具鏈,所以不要讓不可信專案進入持有簽名資產的節點。
依 Apple Silicon 或 Intel 架構安裝
GitLab 官方 macOS 安裝文件同時提供 Apple Silicon 與 Intel x86-64 的 Runner 執行檔。你應先確認:
uname -m
再依架構選擇官方安裝方式,不要從不明來源下載二進位檔。安裝後確認:
gitlab-runner --version
官方文件目前將 macOS Runner 定義為使用者模式的 LaunchAgent,不是系統層級的 LaunchDaemon。服務配置會放在該使用者的家目錄中。參考 GitLab macOS 安裝文件。
註冊時把標籤當成路由規則
在 GitLab 控制台建立專案級或群組級 Runner,取得當時產生的認證資料。命令中的 URL、Token 與名稱只使用佔位符:
gitlab-runner register \
--url "https://gitlab.example.invalid/" \
--token "$RUNNER_TOKEN"
互動註冊時,請設定:
- 描述:例如
ios-macos-arm64-ci - 標籤:例如
macos、ios、xcode - 執行器:
shell - 維護備註:寫明用途、負責人與是否持有發佈憑據
GitLab 的註冊流程會把 Runner 與指定 GitLab 實例建立認證關係,配置會保存到 config.toml。註冊 Token 不要寫入 .gitlab-ci.yml,也不要貼到公開工單。參考 GitLab Runner 註冊文件。
macOS GitLab Runner 重啟後離線的真正原因
使用者會話比「服務已安裝」更重要
在 macOS 上,GitLab Runner 官方支援的服務模式是使用者層級 LaunchAgent。它在使用者登入時啟動,登出時停止,並能存取該使用者的鑰匙串與圖形會話。這正是 iOS Simulator 與程式碼簽名常需要的環境。
因此,以下做法不能直接照搬 Linux:
sudo systemctl enable gitlab-runner
這不是 macOS 的處理方式。系統層級的 LaunchDaemon 沒有相同的使用者會話與鑰匙串存取條件,不應把它寫成通用的 macOS Runner 部署方案。
安裝並啟動服務時,依官方方式執行:
cd ~
gitlab-runner install
gitlab-runner start
gitlab-runner status
然後檢查服務檔是否出現在:
~/Library/LaunchAgents/gitlab-runner.plist
GitLab 文件指出,Runner 會在目前已登入的使用者身分下執行。若整機重啟後沒有自動登入,Runner 可能維持離線;即使檔案已安裝,工作也不會自動接手。參考 GitLab macOS 服務模式文件。
自動登入、安全性與人工恢復要做取捨
若你的節點需要在無人值守狀態下跑 Simulator 或簽名任務,必須評估自動登入。它能改善重啟恢復,但也會降低主機在實體接觸或主控台遭入侵時的防護。
可按任務敏感度選擇:
- 只做無簽名測試:可考慮自動登入,並限制 SSH、網路與專案範圍。
- 需要發佈簽名:優先採用受保護分支、專用節點與人工恢復流程。
- 高敏感憑據:不要把「自動登入」當成唯一可用性方案,應保留人工登入、檢查與撤銷憑據的程序。
重啟驗證不能只執行一次。至少測試正常啟動、退出 SSH、短暫斷網與整機重啟。每次都記錄 Runner 是否重新出現、是否能接單,以及工作是否能存取鑰匙串。
04GitLab CI 呼叫 Xcode 的最小可行流水線
先固定活動開發者目錄
Apple 的 xcodebuild、simctl 和其他命令列工具由 Xcode 提供。執行前必須安裝 Xcode,並把正確版本設為活動開發者目錄。參考 Apple Xcode 命令列工具文件。
在 Runner 使用者下執行:
xcode-select -p
xcodebuild -version
xcodebuild -runFirstLaunch
若有多個 Xcode,明確指定路徑:
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
不要只在個人帳戶中完成首次啟動。Runner 使用者必須自己能讀取專案依賴、執行 Xcode 工具與安裝所需 Simulator 元件。
用四段式流水線排除問題
第一版 .gitlab-ci.yml 不要一開始就接入發佈。先分四段:
stages:
- checkout
- build
- test
- archive
variables:
LANG: "en_US.UTF-8"
checkout:
stage: checkout
tags:
- macos
script:
- whoami
- xcode-select -p
- git status
build:
stage: build
tags:
- macos
script:
- xcodebuild -workspace "App.xcworkspace" \
-scheme "App" \
-configuration Debug \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=YOUR_SIMULATOR' \
build
test:
stage: test
tags:
- macos
script:
- xcodebuild test \
-workspace "App.xcworkspace" \
-scheme "App" \
-destination 'platform=iOS Simulator,name=YOUR_SIMULATOR'
archive:
stage: archive
tags:
- macos
when: manual
script:
- xcodebuild archive \
-workspace "App.xcworkspace" \
-scheme "App" \
-archivePath "$CI_PROJECT_DIR/build/App.xcarchive"
artifacts:
paths:
- build/
xcodebuild 會依專案、Target、Scheme 與建置設定執行工作。Apple 建議在實體裝置上進行發佈前測試;Simulator 適合快速開發驗證,但不能完全代表實體裝置表現。參考 Apple 建置與執行 App 文件。
這一階段的退出條件是:
build能成功產生建置結果。test能回傳正確退出碼。- 日誌能辨識 Xcode 路徑、Scheme 和目的地。
archive尚未接入真實發佈憑據,也能驗證基本流程。
簽名憑據要和一般測試分開
先分清楚「測試」與「發佈」
無簽名 Simulator 建置不需要把憑證、描述檔或 App Store Connect 憑據放進 Runner。這類資產應等建置和測試穩定後,再接入受保護的發佈工作。
Apple 的建置設定中,CODE_SIGN_IDENTITY 會指向鑰匙串中的簽名憑證;缺少有效憑證時,建置會失敗。CODE_SIGN_STYLE 則決定簽名資產由自動或手動方式管理。參考 Apple Build Settings Reference。
專用鑰匙串與受保護變數
簽名階段至少要做到:
- 使用 CI 專用鑰匙串,不要直接使用個人預設鑰匙串。
- 憑證與私密金鑰只匯入 CI 帳戶。
- 密碼放在 GitLab 的受保護、遮罩變數中。
- 發佈工作只允許受保護分支或受保護標籤。
- 外部貢獻、分叉儲存庫與可修改 CI 腳本的工作,不得排程到發佈 Runner。
- 工作結束後刪除臨時描述檔、匯入檔與解密資料。
若採用 App Store Connect API Key,也要為它設定最低可用權限。不要把完整管理權限當成預設值,並應定期撤銷不再使用的金鑰。
06對照清單:自建 macOS Runner 還是遠端 Mac
你可以用這組條件作最後判斷:
選自有 Mac
- 需要實體 iPhone、iPad 或 USB 裝置。
- 需要長期保留本地快取與專用硬體。
- 團隊能負責系統更新、磁碟清理、憑據輪換與重啟恢復。
- 機器可放在受控機房,且有固定電力與網路。
選遠端 Mac
- 沒有可長期在線的 Mac。
- 需要按專案週期取得 Apple Silicon 環境。
- 需要從 Windows 或 Linux 透過 SSH、VNC 或網頁控制台維護節點。
- 想先驗證 Xcode 版本、建置流程和簽名策略,再決定是否購買硬體。
暫不接入 Mac Runner
- 專案尚未固定 Xcode、Scheme 和依賴版本。
- CI 腳本仍允許任意分支讀取發佈變數。
- 沒有人負責處理憑據、工作目錄與節點故障。
- 你的任務其實不需要 macOS 專屬工具鏈。
若你正在比較節點位置,可以先閱讀 遠端 Mac 構建節點配置選擇,再依團隊所在地和開發者連線需求查看 香港遠端 Mac 方案 或 新加坡遠端 Mac 方案。這些選擇不應只看地區名稱,還要一起評估 SSH 延遲、維護權限與長期可用性。
07上線首週:用真實任務驗收節點
不要用空專案跑分。第一週應觀察真實專案的以下狀態:
- 工作排隊是否符合團隊的提交時段。
- 建置失敗能否從日誌定位到工具鏈、依賴或簽名問題。
- 工作目錄和 Xcode 快取是否持續增長。
- 多個任務是否意外共用檔案或 Simulator 狀態。
- 重啟後是否能重新接單。
- 失敗後是否能刪除臨時憑據與產物。
- Archive 和
dSYM是否按專案規則保存。
Apple 建議保留與發佈建置對應的 Archive 與符號檔,否則日後分析崩潰報告可能缺少必要資訊。參考 Apple 建置除錯資訊文件。
你的驗收判定可以簡化成三個出口:
- 繼續使用:重啟恢復、真實建置、測試、簽名與清理都通過。
- 先清理優化:建置成功,但工作目錄、快取或鑰匙串管理不穩定。
- 增加節點或回退人工發佈:排隊衝突、恢復失敗,或外部程式碼仍可能接觸發佈憑據。
長期維護責任也要寫清楚。至少指定誰負責 Xcode 與 Runner 更新、硬碟回收、憑證輪換、Runner 版本複核,以及每次失敗的日誌留痕。沒有責任人,遠端 Mac 很快會變成「仍在線但沒人敢用」的節點。
如果你目前使用的是 Windows 或 Linux 主機,常見缺點是無法直接執行 Xcode 與 Apple SDK、需要額外維護跨平台工具鏈,而且發佈簽名不能靠普通 Linux 伺服器補足。相比之下,租用 VpsMesh 的真實 Mac,可以先取得一台可遠端管理、能獨立建立 CI 帳戶並長期保留 macOS 工具鏈的主機;這通常比先購買一台可能長時間閒置的 Mac 更適合短期遷移、版本驗證或按發佈週期擴展。若你的工作需要實體 USB 裝置,或屬於長期高負載且必須完全自主管理的任務,仍應優先評估自購 Mac。