Claude Code GitHub Actions 要跑遠端 Mac,最快且較安全的做法是採用雙 Job 分層:Agent Job 負責讀取 Issue 或 Pull Request、修改程式碼並提交變更;Mac 驗證 Job 只接收固定 Commit SHA,執行受控的 Xcode 建置與測試。不要讓外部 PR 的 Agent 直接接觸共用簽名憑證;正式發佈則使用獨立節點、最小權限和人工核准。
這篇適合三類人:需要讓 Claude Code 自動處理 GitHub Issue 或 PR,並驗證 iOS、macOS 專案的開發者;維護 GitHub Actions 自託管 Mac Runner、工作路由與節點恢復的 DevOps 工程師;以及需要限制 Agent 存取原始碼、網路、鑰匙圈和發佈憑據的安全或平台負責人。
先記住一個停止條件: Runner 顯示在線,不代表 Xcode 建置成功;模擬器能啟動,也不代表 UI 測試已經可以無人值守。每個場景都要保存可核對的建置狀態、測試結果包和工作來源。
最後更新於 2026 年 9 月 7 日;工作流權限、Runner 路由與 Xcode 命令列行為已按 Claude Code Action 官方文件、GitHub Actions 安全使用文件 及 Apple 文件交叉核對。
先分開兩個 Job:改碼和 Apple 驗證不要混在一起
Claude Code Action、Claude Code CLI、GitHub Actions Runner 和 Xcode 是四個不同層次:
- Claude Code Action:由工作流觸發 Agent,理解 Issue 或 PR,讀取相關程式碼,產生修改並回傳差異或提交。
- Claude Code CLI:真正執行 Agent 指令的工具。它不等於 GitHub Runner,也不會自動提供 macOS 或 Xcode。
- GitHub Actions Runner:接收工作流並執行指令的代理程式。Runner 可以是一般 Linux 節點,也可以是自託管 Mac。
- Xcode 執行環境:提供
xcodebuild、Simulator、Scheme 和 Apple SDK。只有需要 Apple 工具鏈的 Job 才應路由到 Mac。
因此,普通的程式碼檢查、差異整理和文件修改,不必佔用遠端 Mac。Agent Job 完成後,應輸出明確的 Commit SHA;Mac Job 再以該 SHA checkout,避免 Agent 修改的是一個版本,而建置測試拿到另一個版本。
工作流可以保留以下占位欄位,正式環境再換成實際值:
jobs:
agent:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Run Claude Code Action
uses: anthropics/claude-code-action@<PINNED_REF>
mac-verify:
needs: agent
runs-on: [self-hosted, macos, <APPLE_PROJECT_LABEL>]
steps:
- name: Checkout fixed revision
uses: actions/checkout@<PINNED_REF>
with:
ref: ${{ needs.agent.outputs.commit_sha }}
- name: Build and test
run: ./ci/<BUILD_SCRIPT>
實際輸入和輸出欄位要以目前官方 Action 範例核對,不要自行假設某個輸出名稱一定存在。對 Action 使用固定參照、縮小工作流權限,並檢查 Claude Code Action 的安全說明。
第一個場景:Issue 或 PR 改碼後,怎麼觸發 Xcode 建置驗證?
當 Claude Code 修改 Apple 專案後,觸發方式不應是「只要 PR 有更新就把所有任務送到 Mac」。更穩妥的路由是先判斷檔案範圍,再由標籤或受控條件決定是否執行 Mac Job。
例如:
- 只改文件、腳本說明或與 Apple 專案無關的目錄:回到一般 Runner。
- 修改 Swift、Objective-C、Xcode 專案檔或
Package.swift:進入 Mac 驗證。 - 需要 Simulator、歸檔或發佈:進入更嚴格的 Runner Group,不與一般測試節點混用。
GitHub 的 Runner 標籤可用來選擇符合條件的自託管節點,Runner Group 則可限制哪些儲存庫能使用某組 Runner。請分別檢查 Runner 標籤路由文件 和 Runner Group 存取控制文件。
外部 PR 是風險分界。 來自 Fork 的程式碼可能修改工作流檔案或加入惡意腳本。不要因為它能通過一般審查,就把它送入持有簽名資產的遠端 Mac。預設可以只執行無簽名建置,或先由受信任分支重新產生待驗證 Commit;涉及寫入權限、秘密資料或人工觸發的流程,必須先讀過 GitHub Actions 安全使用規範。
第二個場景:在遠端 Mac 上驗收 Xcode,而不是只看 Runner 在線
「Claude Code 修改完成」和「Apple 專案可建置」是兩個結果。Mac 驗證 Job 至少要核對以下內容:
- 活動 Xcode 與 SDK:在 Job 開始時記錄
xcodebuild -version、xcode-select -p及實際 SDK 路徑。 - 專案入口:明確指定
<WORKSPACE_OR_PROJECT>、<SCHEME>、<DESTINATION>,不要依賴節點目前所在目錄。 - 依賴解析:固定 Swift Package 或其他依賴的解析結果,保存解析紀錄,避免節點快取讓結果漂移。
- 建置狀態:使用
xcodebuild執行建置或測試,將標準輸出、錯誤輸出和結果包作為工作流產物。Apple 的 Xcode 命令列工具參考 是欄位和指令行為的核對依據。 - 失敗處理:把結構化日誌回傳到 PR 審查流程。不要讓 Agent 自動清除所有快取、改動節點設定,或無限重試同一個失敗命令。
你可以將驗證腳本固定成:
set -o pipefail
xcodebuild \
-workspace "<WORKSPACE>" \
-scheme "<SCHEME>" \
-destination "<DESTINATION>" \
test \
-resultBundlePath "<RESULT_BUNDLE_PATH>" \
2>&1 | tee "<LOG_PATH>"
這裡的重點不是某個命令範本,而是讓「使用哪個 Commit、哪個 Scheme、哪個目的地、產生哪個結果包」都能被追溯。若只看到 Runner 顯示 online,沒有 xcodebuild 的退出狀態和結果包,就只能判定節點可接單,不能判定驗證通過。
需要先準備節點的開發者,可參考 遠端 Mac 的 Xcode 建置節點驗收方向,把工作目錄、SDK、依賴快取和日誌出口先固定下來。
第三個場景:純命令列、Simulator 和圖形測試要分級
三種工作不能用同一個「Mac 可用」標籤概括:
- 純命令列建置:通常只要求 SSH 或 Runner 服務可用、工作目錄乾淨,以及 Xcode 命令列工具可執行。
- Simulator 測試:需要確認指定模擬裝置能建立、啟動,測試結果包能在工作流結束前保存。
- 圖形化 UI 測試:除了上述條件,還可能需要圖形登入會話、螢幕解鎖狀態或特定輔助功能權限。這不是單靠 SSH 成功就能推導出來的結果。
Apple 對 Xcode 測試自動化的說明可參考官方測試自動化文件。驗收時應留下模擬器識別資料、啟動結果、測試結果包和斷線後的工作狀態。
模擬器能啟動,只能證明該模擬環境在當次工作中可用。它不能替代真機測試,也不能推論所有需要圖形會話的 UI 自動化都能在無人值守下完成。遇到遠端連線中斷時,還要確認 Runner 工作是繼續、失敗,還是被重新排隊;不能只看 VNC 視窗是否仍然存在。
第四個場景:把簽名和發佈資產隔離
預設流程應是無簽名建置或測試。Agent 修改程式碼時,不應同時取得簽名憑證、鑰匙圈、描述檔、Team ID 或發佈令牌。這些資料應從 Agent Job 的環境、工作目錄和秘密範圍中移除。
確實需要歸檔時,採用以下邊界:
- 只允許受保護分支進入歸檔 Job。
- 使用獨立 Runner 或專用 Runner Group,不與一般 PR 驗證共用。
- 把環境核准放在簽名和上傳步驟之前。
- 將憑證匯入、鑰匙圈解鎖和歸檔操作限制在短生命週期的工作目錄。
- 外部 PR、能修改工作流檔案的分支,以及未審查腳本,不得進入持有生產簽名資產的節點。
Apple 的簽名程式碼與歸檔文件可用來核對歸檔和簽名步驟。這裡的安全邊界不是「Agent 很聰明就能自動判斷」,而是由分支、Runner、環境和人工核准共同限制。
第五個場景:多個儲存庫共用一台 Mac 時,先阻止交叉污染
共享遠端 Mac 的隱性成本,通常不在 CPU,而在殘留狀態:
- 上一個儲存庫留下的原始碼、建置產物或依賴快取可能被下一個工作讀到。
- 不同專案使用相同 macOS 帳戶時,鑰匙圈、SSH 設定和工具設定容易越界。
- 長期 Runner 不像容器化臨時 Runner,可以在每個任務後自然消失。
- Agent 失敗後若自行清理節點,可能把其他工作需要的診斷資料一併刪除。
按儲存庫信任級別分配 Runner Group 和標籤。至少區分一般開發、團隊共享測試和生產發佈。工作開始時記錄任務來源、Commit SHA、Runner 名稱、工作目錄;結束時記錄清理結果、產物位置和失敗原因。
如果專案之間不能共用帳戶或快取,就不要用標籤把它們硬塞進同一節點。此時,專用節點或每次任務重建工作目錄,通常比追查交叉污染更省時間。自託管 Runner 的更新、工作目錄清理和長期運作方式,應依你目前採用的 GitHub Runner 管理版本逐項核對,不要把容器化臨時 Runner 的隔離假設直接套用到 macOS 節點。
第六個場景:Runner 重啟後,Agent 工作流如何恢復?
自託管 Mac Runner 重啟後,是否能恢復 Agent 工作流,不能只測試「服務有沒有自動啟動」。你需要驗證整條無人值守鏈路:
- 重啟 Mac,確認 Runner 程式和必要的背景服務按預期恢復。
- 從 GitHub 發出一個不含簽名資產的測試工作。
- 確認標籤和 Runner Group 仍然正確,沒有誤接到其他儲存庫。
- 讓測試工作產生可辨識的日誌與結果檔案。
- 人為中斷連線,觀察工作是失敗、繼續執行還是重新排隊。
- 檢查重啟前後是否殘留工作目錄、憑證、模擬器狀態或未上傳的日誌。
Runner 的更新與管理方式要按目前採用的 Runner 版本和組織政策核對。對長期運行節點而言,日志外送、磁碟清理、工作重試和人工停機入口同樣重要;否則一次重啟可能只恢復「在線狀態」,卻沒有恢復可交付的 Agent 驗證流程。
用條件分支決定是否上線
- 若 Agent 能輸出固定 Commit、Mac Job 能以該 SHA 建置,且結果包和日誌都能回傳,則可進入開發試用。
- 若一般測試通過,但外部 PR、工作流修改或共享快取仍未隔離,則限制為受信任分支和無簽名建置。
- 若簽名資產、人工核准、獨立 Runner 和清理證據都已通過,則才考慮生產發佈。
- 否則回退到一般 Runner 加遠端 Mac 手動驗證,不要讓 Agent 直接觸碰發佈節點。
如果你目前用的是普通 Linux Runner 或共用雲端工作節點,它們的缺點很明確:無法直接提供完整 Xcode 工具鏈、Simulator 圖形會話和 Apple 專案所需的 macOS 狀態;自行維護 Mac mini 又要承擔硬體採購、重啟、遠端管理和閒置成本。完成權限分層後,租用一台具備完整管理權限、可隔離並能做重啟驗證的遠端 Mac,較適合作為非生產試跑節點。你可以先查看 MACCOME 的遠端 Mac 方案,用真實專案確認建置、日誌回傳和權限邊界,再決定租用週期及是否增加獨立發佈節點。