GitHub 官方的 Runner 路由可同時依照作業系統、處理器架構與自訂標籤三類條件選擇執行主機,這表示 GitHub Actions iOS 打包可以交給遠端 Mac 的 self-hosted runner;但註冊完成不等於具備生產發布資格。可靠做法是先固定 Xcode 工具鏈,再隔離簽名憑據,最後用真實專案逐層驗收 Archive、導出與 TestFlight 上傳。相關標籤規則可參考 GitHub 官方標籤路由說明。
這篇文章適合已經使用 GitHub 管理程式碼、希望自動建構與發布 iOS App 的獨立開發者,也適合沒有本地 Mac、想把遠端 macOS 環境改成常駐打包機的 Windows 或 Linux 開發者。需要控制 Xcode 版本、原生依賴與簽名材料的小型 App 團隊,也能用本文的驗收軸檢查現有環境。
先用五項指標判定 Runner 是否能進入生產
Runner 是否「在線」,只是最低限度的連線狀態。真正適合接收發布任務的遠端 Mac,至少要通過以下五個條件:
- 主機可用性:符合目前 Xcode 與目標 SDK 的 macOS 系統要求,具備穩定網路、足夠硬碟空間,並能在長時間運行後持續接收工作。
- 工具鏈一致性:活動開發者目錄、依賴鎖定檔、Build Scheme 和簽名設定可重複使用,不會因主機上存在多個 Xcode 而誤用版本。
- 憑據安全:程式碼簽名憑證與私鑰、Provisioning Profile、App Store Connect 上傳憑據各自管理,不在儲存庫中留下真實值。
- 任務完整性:依賴恢復、編譯、Archive、簽名導出、上傳和 App Store Connect 後台處理,均有獨立結果可以追查。
- 恢復能力:遠端 Mac 重啟、Runner 更新、快取失效或建構中斷後,能自動恢復或明確告警,而不是等待人工重新開啟終端機。
因此,註冊 Runner 只是起點。若其中一項未驗收,這台主機比較適合測試,不應直接承擔正式發布。
先確認遠端 Mac 能否穩定接單
核對 macOS、Xcode 與儲存空間
遠端 Mac 必須符合目前 Xcode 的系統條件,並與專案需要的 SDK 相容。Apple 會在 Xcode 系統要求與上傳條件頁面更新相容的 macOS、SDK 及提交要求;因此不要把某個版本的教學截圖當成永久規則。
驗收時可先記錄以下資訊:
sw_vers
xcode-select -p
xcodebuild -version
xcodebuild -showsdks
df -h
這些輸出應保存到工作流程日誌或受限的建構紀錄中。版本本身不是越新越好,重點是它要和專案的最低部署目標、原生套件及 App Store Connect 當前要求相容。
註冊 Runner 並驗證在線狀態
GitHub 支援把 self-hosted runner 註冊到儲存庫、組織或企業層級。對獨立開發者而言,儲存庫層級通常較容易控制範圍;小型團隊則可按專案權限決定是否使用組織層級。註冊指令應直接從 GitHub 目前的設定頁產生,絕對不要把下列敏感值提交到程式碼:
./config.sh \
--url https://github.com/PLACEHOLDER_OWNER/PLACEHOLDER_REPO \
--token PLACEHOLDER_RUNNER_TOKEN \
--name PLACEHOLDER_RUNNER_NAME \
--labels self-hosted,macOS,ARM64,ios-release
以上儲存庫、Token 和 Runner 名稱均為占位符。完成註冊後,在 GitHub 的設定頁確認 Runner 顯示為在線,並用一個不涉及簽名的最小工作流程測試它是否真的能接收工作。
把互動式啟動改成系統服務
直接在 SSH 或遠端桌面工作階段輸入 ./run.sh,只適合初步測試。關閉工作階段、主機重新啟動或使用者登出後,這個程序可能停止,GitHub 工作流程便會長時間排隊。
正式環境應依照 GitHub Runner 服務配置文件安裝系統服務。安裝後至少驗證:
- 主機重啟後,Runner 服務是否自動啟動。
- Runner 是否重新顯示在線並保留正確標籤。
- 網路尚未就緒時,服務是否能稍後恢復,而非永久失敗。
- 沒有圖形化登入時,Xcode 命令列工具與必要環境變數是否仍可用。
用標籤把發布任務送到正確主機
GitHub Actions 的 runs-on 會要求工作流程中的標籤與 Runner 標籤匹配。self-hosted、macOS、ARM64 可用來限制基本條件,自訂的 ios-release 則用來區分正式發布主機與一般測試主機。
jobs:
ios_release:
runs-on: [self-hosted, macOS, ARM64, ios-release]
steps:
- uses: actions/checkout@v4
- name: Show build environment
run: |
xcode-select -p
xcodebuild -version
這裡的 Action 版本只作為示意,實際工作流程應按專案的供應鏈政策固定並審查。若沒有任何 Runner 同時符合所有標籤,工作流程不會自動改派到其他系統,而會維持排隊狀態。這個現象需要納入監控:設定工作流程逾時、在排隊過久時通知維護者,並確認通知本身不會暴露 Token 或簽名資訊。
發布 Runner 不應與處理外部貢獻程式碼的 Runner 混用。GitHub 對 self-hosted runner 的風險與隔離方式已有 官方安全建議,公開儲存庫或會執行不受信任工作流程的專案,尤其不適合把常駐簽名材料放在同一台主機上。
固定 Xcode 基線,再驗證最小建構
讓工具鏈選擇可追蹤
如果遠端 Mac 同時安裝多個 Xcode,工作流程必須明確設定活動開發者目錄,而不是依賴登入使用者當前的選擇:
sudo xcode-select -s /Applications/Xcode_PLACEHOLDER.app/Contents/Developer
xcode-select -p
xcodebuild -version
實際路徑請替換為受控環境中的值;不要把私人電腦路徑、Team ID 或專案識別資料直接複製到公開範例。工作流程還應固定:
- 依賴管理工具使用的鎖定檔。
- 用於 Archive 的 Scheme,並確認它已標記為 Shared。
-destination、工作區或專案路徑。- 建構設定,例如 Release 設定與目標 Bundle Identifier。
先做不含簽名材料的建構
在處理憑據前,先確認原始碼可以被 Runner 還原並編譯。這一步能把「主機或依賴問題」和「簽名問題」分開:
xcodebuild \
-workspace PLACEHOLDER_WORKSPACE.xcworkspace \
-scheme PLACEHOLDER_SCHEME \
-configuration Release \
-destination 'generic/platform=iOS' \
-derivedDataPath "$RUNNER_TEMP/derived-data" \
CODE_SIGNING_ALLOWED=NO \
clean build
若這一步失敗,先檢查 Xcode 目錄、Swift Package 或其他依賴的鎖定狀態、原生套件版本與硬碟空間,不要急著重新產生憑證。最小建構成功後,才進入 Archive;這能讓日誌清楚分辨「程式碼無法編譯」與「簽名或發布設定錯誤」。
以隔離方式處理 iOS 簽名憑據
iOS 開發者證書與 Provisioning Profile 並不是一枚可以包辦所有工作的 API Key。Apple 對 證書與 Provisioning Profile 的用途有不同說明,發布工作流程必須按用途分開管理。
至少應區分以下內容:
- 用於程式碼簽名的憑證與私鑰。
- 與 Bundle ID、裝置或發布用途相符的 Provisioning Profile。
- 用於 App Store Connect 傳送建構版本的上傳憑據。
- GitHub Secrets 中的加密內容、解碼後檔案與工作期間產生的暫存資料。
可採用的安全邊界如下:
- 只允許受信任的私有儲存庫與發布分支觸發正式工作流程。
- 將憑據放在 GitHub Secrets,不寫入 YAML、
.env、設定檔或提交紀錄。 - 工作開始時建立臨時 Keychain,設定必要密碼與解鎖狀態。
- 將憑證與 Profile 匯入到該 Keychain,避免污染主機預設登入 Keychain。
- 工作完成、失敗或取消時,刪除臨時 Keychain、解碼檔案和輸出中的敏感環境變數。
- 定期撤銷不再使用的 Runner 與憑據,保留輪換及撤銷紀錄。
注意: 具備完整主機權限不代表所有工作流程都值得信任。只要發布 Runner 能接觸私鑰,任一可執行的不受信任指令都可能把簽名材料或建構產物帶離主機。
按產物狀態驗收 Archive 到 TestFlight
不要把一條 xcodebuild 命令回傳成功,直接寫成「已發布」。工作流程應讓每一層都有明確輸出:
1. 依賴恢復
先執行 checkout 與依賴恢復,記錄鎖定檔是否存在、依賴是否成功下載,以及快取命中或失效的結果。快取只能縮短恢復時間,不能取代鎖定檔;快取失效時仍應能從乾淨環境重新建立。
2. Archive
Archive 是將可發布建構整理成 Xcode 歸檔產物的階段。可以使用占位符路徑示意:
xcodebuild archive \
-workspace PLACEHOLDER_WORKSPACE.xcworkspace \
-scheme PLACEHOLDER_SCHEME \
-configuration Release \
-archivePath "$RUNNER_TEMP/PLACEHOLDER_APP.xcarchive" \
-destination 'generic/platform=iOS'
Archive 成功後,先檢查 .xcarchive 是否真的存在,再進行簽名導出。Apple 的 應用程式歸檔與分發說明可用來核對產物與上傳流程的關係。
3. 簽名導出
導出階段應使用受控的 Export Options 設定,並將實際 Profile 名稱、Team ID、憑證名稱改成工作流程中的 Secrets 或安全設定值。公開文章與儲存庫範例只能使用:
PLACEHOLDER_TEAM_ID
PLACEHOLDER_BUNDLE_ID
PLACEHOLDER_PROFILE_NAME
PLACEHOLDER_CERTIFICATE_NAME
導出的 IPA 不應直接長期留在共享工作目錄。只保留完成驗收所需的時間,並限制 Artifact 存取權限。
4. 上傳
上傳步驟要單獨記錄命令退出狀態、傳輸回應與產物識別資訊。Apple 的 上傳建構版本文件說明了提交後的處理關係;因此「上傳命令成功」和「TestFlight 已可測試」仍是兩個不同狀態。
5. 後台處理與通知
最後確認 App Store Connect 後台是否完成處理、版本是否出現警告,以及測試群組是否能取得建構版本。通知內容只需包含專案、提交識別、失敗階段和日誌位置,不要把簽名錯誤中的完整環境值直接傳到聊天工具。
用對照清單選擇部署方式
以下不是主機規格表,而是把「遠端 Mac 自托管 Runner」與「僅使用臨時託管 Runner」放在同一組決策條件中。獨立開發者可依每一點判斷,而不是只看註冊速度。
選擇遠端 Mac self-hosted runner,當:
- 專案需要固定的 Xcode、原生依賴或特殊建構腳本。
- 需要常駐的 macOS 環境來處理重複 Archive、簽名與發布。
- 團隊能限制私有儲存庫、發布分支和工作流程的觸發權限。
- 能接受自行監控重啟、磁碟增長、Runner 更新和憑據輪換。
- 需要在真正發布前保留可追查的日誌與產物。
先選擇臨時或託管環境,當:
- 專案仍在探索 Xcode、依賴或簽名設定,尚未形成穩定工作流程。
- 沒有能力保護常駐主機,或工作流程會執行外部貢獻者提供的程式碼。
- 建構頻率低,且不需要固定的本機工具或快取。
- 團隊只需要短期驗證,不希望承擔主機更新與故障排查。
若選擇遠端 Mac,建議先參考 RUVCLOUD 的遠端 Mac 方案,以短期環境跑通真實專案,再決定是否改為常駐 Runner;這比一開始便把正式簽名憑據放到長期主機更容易控制風險。
用檢查清單完成常駐化驗收
在正式啟用前,可逐項勾選:
- [ ] macOS、Xcode、SDK 和專案部署目標已按 Apple 當前文件核對。
- [ ] Runner 已註冊到正確的儲存庫或組織,且 Token 沒有出現在程式碼與日誌。
- [ ]
self-hosted、macOS、ARM64和發布用途標籤均已驗證。 - [ ] 沒有匹配 Runner 時,工作流程會排隊並觸發可觀察的逾時或告警。
- [ ] Xcode 活動目錄、Scheme 和依賴鎖定檔已固定。
- [ ] 不含簽名材料的最小建構可以在乾淨工作目錄完成。
- [ ] 臨時 Keychain 可建立、解鎖、匯入並在工作結束後刪除。
- [ ] Archive、簽名導出、上傳與後台處理各有獨立驗收結果。
- [ ] Runner 以系統服務啟動,主機重啟後能恢復在線。
- [ ] 已測試磁碟不足、快取失效、建構中斷與網路短暫中斷的處理方式。
- [ ] 已保留重新註冊、撤銷舊 Runner 和輪換憑據的操作紀錄。
- [ ] 公開儲存庫或外部貢獻工作流程不會接觸正式發布主機。
完成一次真實發布任務後,結論應只分為「通過」、「需要整改」或「不適合常駐運行」。若只是 Archive 成功、導出失敗,應標記為簽名階段未通過;若上傳成功但後台仍在處理,則不能提前通知測試者。
常見問題
遠端 Mac 適合所有 GitHub Actions iOS 打包工作嗎?
不一定。它適合需要固定 macOS、Xcode、原生依賴或簽名環境的發布流程,但也增加了主機安全、更新、磁碟和恢復責任。若專案仍在早期試驗階段,先用不含簽名的建構驗證工作流程,通常比立即配置正式發布主機更穩妥。
self-hosted runner 能否只靠標籤固定 Xcode?
不能。標籤只能協助 GitHub 選擇符合條件的作業系統、架構或用途主機,無法保證該主機當前使用哪個 Xcode。工作流程仍應設定活動開發者目錄,輸出 Xcode 與 SDK 資訊,並在建構前檢查 Scheme 和依賴鎖定狀態。
簽名憑據是否可以直接放在遠端 Mac 硬碟?
不建議把可長期使用的私鑰和 Profile 放在共享或預設 Keychain。較安全的做法是從受限 Secrets 暫時匯入專用 Keychain,完成導出後清理檔案與 Keychain;同時要限制能觸發發布工作流程的人員與分支,避免主機權限被不受信任程式碼利用。
Runner 重新啟動後在線,是否代表可以立即發布?
不代表。Runner 在線只證明服務能與 GitHub 通訊,還需要檢查 Xcode 路徑、憑據匯入、磁碟空間、依賴恢復和 Archive 流程。建議在重啟後先執行不含簽名的最小建構,再執行受控測試發布,並將兩者的結果分開記錄。
GitHub Actions 成功後,TestFlight 何時可供測試?
工作流程成功只能表示其中設定的命令完成,不能保證 App Store Connect 後台已處理完畢。上傳後仍應在後台確認建構版本、處理狀態與警告,再通知測試者;若出現錯誤,應回到傳輸或後台處理階段排查,而不是重新註冊 Runner。
對沒有本地 Mac 的開發者而言,Windows 或 Linux 加上臨時雲端環境可以啟動建構,但常見限制是 Xcode 工具鏈不固定、簽名材料難以隔離,以及主機重啟後需要人工恢復;自行購買 Mac 則要承擔一次性硬體支出、閒置成本和長期維護。若目標是先驗證真實專案的 GitHub Actions iOS 打包流程,或需要一台持續在線的 macOS 打包機,使用 RUVCLOUD 租用遠端 Mac 會比為單一發布用途添置專用硬體更具彈性;建議先完成 Archive、簽名和上傳,再把重啟恢復與失敗定位一併驗收,通過後才轉為常駐 Runner。若需要比較不同租期,可查看 RUVCLOUD 的方案與租用資訊。