症狀:遠端 Mac 上的 fastlane 無法取得上傳授權;最快解法:先按實際 action 選擇適用的 API Key,把 .p8 私鑰放在受控位置,再載入並做低風險驗證。API Key 不會取代程式碼簽名憑證與 Provisioning Profile。
適用對象:首次在遠端 Mac 設定 fastlane 自動上傳的獨立 iOS 開發者。
也適合把發布流程從本機搬到遠端環境的小團隊,以及想收緊私鑰存取範圍的開發者。
先確認憑證各自負責的工作
App Store Connect API Key 用來授權受支援的 App Store Connect API 操作;fastlane 會使用相關設定取得授權。它不負責替 App 簽名,也不會自動建立簽名憑證或描述檔。Apple 說明 API 採用 JWT 授權;建立與管理金鑰時,應以Apple 的 API Key 建立與管理說明核對目前選項。
開始之前,把工作分成兩類:
- 上傳或管理 App Store Connect 資源:確認目標 fastlane action 是否支援 API Key,以及所需的角色權限。
- 建置與簽名 App:另行確認簽名憑證、App ID 與 Provisioning Profile。Apple 的開發描述檔說明列出描述檔相關設定;API Key 不能替代這些簽名材料。
這個區分能快速縮小故障範圍:授權錯誤先查 Key ID、Issuer ID 與角色;簽名錯誤則查憑證、描述檔和建置設定。不要因為上傳工具讀取了 API Key,就假設建置和簽名也已準備妥當。
準備適合 fastlane 任務的金鑰
如何判斷個人金鑰或團隊金鑰適用?
選擇依據不是「哪一種比較好」,而是執行任務的身分與權限。個人金鑰和團隊金鑰的關聯對象不同,應核對金鑰建立位置、可用角色及團隊存取政策。Apple 的角色權限表可用來檢查指定角色的權限;具體到 fastlane,仍須對照該 action 的文件,不能把 API Key 當成適用所有操作的通用憑證。
如果流程包含 provisioning 相關操作,先看 fastlane 對該操作的支援說明,再決定金鑰類型與權限。fastlane 的App Store Connect API 文件整理了 API Key 設定及相關 action 支援情況。版本或 action 的支援狀況可能變動,請以實際使用版本的文件為準。
建立金鑰時,記下識別所需的 Key ID;若採用的金鑰類型需要 Issuer ID,也一併保存。私鑰檔案下載後立即放入受控的憑證保管位置。Apple 提醒私鑰僅能下載一次;若沒有妥善保存,應依目前金鑰管理指引處理,而不是預期稍後能重新下載。Apple 的 API Key 說明可供建立前後核對。
把私鑰安全交付到遠端 Mac
App Store Connect API Key 的 .p8 檔案應放在哪裡?
放在遠端 Mac 上只有發布工作需要存取的受控位置,並避免放進 Git 工作目錄。實際位置應配合團隊的憑證管理方式與遠端環境政策;不要假設每個遠端 Mac 都提供相同的秘密管理工具,也不要把未確認的供應商功能當成既有保障。
交付時核對以下事項:
.p8只由需要執行發布工作的帳號或流程取得。- 私鑰不提交到 Git,也不寫入 App 原始碼、Fastfile 或客戶端程式。
- 不把私鑰內容貼到終端機輸出、建置紀錄、聊天訊息或除錯日誌。
- 執行工作目錄與私鑰存放位置分開,並確認發布完成後如何保留或移除存取。
- 遠端 Mac 的管理者清楚知道憑證由誰保管、由哪個工作流程使用。
若遠端環境沒有可核實的安全交付方式,先暫停發布流程,向環境管理者確認可用機制。不要為了趕上架而把私鑰塞進版本庫,再寄望事後清除紀錄。
注意: 私鑰被提交後,即使之後刪除檔案,也不能據此認定所有副本和歷史紀錄都已消失。若懷疑外洩,應按 Apple 的撤銷指引處理並重新配置,不要只更改遠端檔案路徑。
在 fastlane 載入金鑰並確認設定
遠端 Mac 上如何讓 fastlane 使用 App Store Connect API Key?
先讓執行 fastlane 的程序能讀到私鑰檔案,再在 Fastfile 或該版本支援的設定方式中提供 Key ID、適用時的 Issuer ID,以及私鑰路徑。以下是結構示例,不含真實憑證:
api_key = app_store_connect_api_key(
key_id: ENV["ASC_KEY_ID"],
issuer_id: ENV["ASC_ISSUER_ID"],
key_filepath: ENV["ASC_KEY_PATH"]
)
lane :upload do
upload_to_testflight(api_key: api_key)
end
環境變數只放識別資訊與檔案路徑,不要把 .p8 內容直接貼進設定檔。若使用的金鑰類型不需要 Issuer ID,依 fastlane 文件確認該參數如何處理,不要填入猜測值。
upload_to_testflight 有自己的參數與使用說明,應對照fastlane 的 TestFlight 上傳 action 文件檢查目前版本。其他 action 不一定接受相同參數;呼叫方式也不能只因為某個 lane 能載入金鑰,就推定所有 API 操作都已獲授權。
可先檢查程序看得到路徑和識別資訊,不要輸出私鑰內容:
test -r "$ASC_KEY_PATH" && echo "API Key file is readable"
預期結果:
API Key file is readable
這只能確認檔案可讀,不能證明 API 權限有效,也不能證明 TestFlight 已收到建置。
先做低風險授權驗證,再執行上傳
fastlane 上傳 TestFlight 前如何驗證授權?
先使用目標工作流程中受支援、影響範圍較小的授權操作,確認金鑰能完成預期範圍內的 API 存取。若所選 action 沒有適合的低風險驗證方式,不要自行假設別的 action 能代表上傳權限;直接按該 action 的文件與團隊測試流程確認。
排查時把錯誤分層記錄:
- 檔案讀取失敗:檢查遠端執行帳號、路徑與檔案存取權。
- API 授權失敗:核對 Key ID、適用時的 Issuer ID、金鑰是否有效,以及角色是否有目標操作權限。
- 建置或簽名失敗:檢查 Xcode 工具鏈、簽名憑證、描述檔與專案設定,不要只重建 API Key。
- 命令成功但建置未確認:回到 App Store Connect 檢查交付結果;命令回傳成功不是完整的發布驗收。
確認授權後,再執行 fastlane 建置與上傳。把使用的 action、執行版本、必要的錯誤訊息摘要及 App Store Connect 中的驗收結果記入發布紀錄;不得把私鑰或包含敏感資訊的完整環境輸出放進紀錄。
維護金鑰與發布紀錄
人員離隊、金鑰遺失或疑似外洩時,先確認受影響的金鑰與發布流程,再按 Apple 的API Key 撤銷說明撤銷並重新配置。撤銷後不要預期能恢復原金鑰;應以新金鑰更新遠端環境中的識別資訊和私鑰檔案,再重新驗證授權。
每次發布至少核對這些項目:
- 執行 fastlane 的遠端帳號仍能讀取受控位置中的金鑰檔案。
- 使用的 action 仍支援目前設定方式,且金鑰角色符合該操作。
- 簽名材料獨立管理,沒有混入 API Key 設定。
- 上傳結果已在 App Store Connect 檢查,而不是只依賴終端機訊息。
- 發布紀錄不含私鑰內容,且團隊知道遇到疑似外洩時的撤銷與替換流程。
完成設定後,可勾選以下項目作為上線前檢查:
- [ ] 已按目標 fastlane action 確認 API Key 支援與權限。
- [ ]
.p8已安全交付到遠端 Mac 的受控位置,且不在 Git 工作目錄內。 - [ ] Fastfile 使用的是環境提供的識別資訊與檔案路徑,沒有寫入真實私鑰。
- [ ] 已分別驗證檔案讀取、API 授權與簽名建置。
- [ ] TestFlight 上傳後已到 App Store Connect 核對交付結果。
- [ ] 團隊已記錄金鑰撤銷、替換與發布驗收的負責流程。
發布方案與環境驗收
| 方案 | 適合情況 | 發布前要留意 |
|---|---|---|
| 本機 Mac | 經常需要本機操作或連接實體裝置 | 本機需維持可用;工具鏈與私鑰管理由團隊自行安排 |
| 遠端 Mac | 需要遠端執行 Xcode、fastlane 或維持發布環境 | 先驗證遠端憑證交付方式、執行帳號與上傳鏈路 |
| 託管 CI 流程 | 已有明確自動化工作流程,且所需 action 受支援 | 確認環境可調整範圍、憑證注入方式與失敗紀錄可見性 |
無論採用哪種方案,都要把 API 授權和簽名材料分開驗收。若正把工作流程搬到遠端環境,可先看遠端 Mac 入門指南,再按發布項目核對支援與環境問題的處理方式。
如果目前依賴本機 Mac,發布機可能受本機可用狀態影響,工具鏈與私鑰也容易分散在個人環境;若使用託管 CI,則要確認 action 支援範圍與環境控制能力是否符合實際流程。需要持續運行 Xcode 和 fastlane、又不想為單一發布工作購買並維護另一台實機時,可以比較 NUMACS 的 Mac 租用方案。若工作需要實體介面或長期固定硬體,先評估自購是否更合適;若只是需要遠端發布環境,則應先依自己的憑證政策驗收連線、工具鏈和上傳流程。
NUMACS 雲端 Mac
讓發布流程在專屬雲端 Mac 穩定執行
透過 NUMACS 獨享實體 Mac mini,將建置與發布工作安排在專屬的遠端 macOS 環境中。
