xcodebuild 導出 IPA 失敗:2026 遠端 Mac 怎麼修?

xcodebuild 導出 IPA 失敗:2026 遠端 Mac 怎麼修?

症狀:Archive 顯示成功,但導出目錄沒有 IPA。
最快解法:先固定同一份 xcarchive,再對照圖形介面與 xcodebuild -exportArchive 的結果;不要反覆重新編譯,先驗收導出方式、簽名鏈、Provisioning Profile、Entitlements 與遠端權限。

這篇適合以下讀者:

  • 透過 SSH 或持續整合腳本執行 xcodebuild,Archive 成功卻找不到 IPA 的獨立開發者。
  • 使用遠端 Mac 作為常駐 iOS 打包機,遇到本地可以導出、遠端任務卻失敗的維護者。
  • 需要把 Build、Archive、Export、Upload 分開判斷,以縮短發版排障時間的小團隊。

四個階段的邊界

Apple 的分發流程把建置、歸檔、導出與發佈視為不同處理環節。xcodebuild 導出時會使用 Archive 路徑、導出設定檔與輸出路徑;這些參數可以在 Apple 的 Xcode App 分發說明 中核對。

你應先把任務記錄成以下四段,而不是只看最後一行退出碼:

  • Build:原始碼是否成功編譯,產生的 App 是否符合預期 Scheme 與 Configuration。
  • Archive:是否產生可供分發的 .xcarchive,其中是否包含主 App、擴充功能與必要的嵌套程式碼。
  • Export:是否能依據 ExportOptions.plist 將 Archive 轉成 IPA 或其他分發產物。
  • Upload:產物是否能被送往 App Store Connect,之後再觀察 Apple 的處理狀態。

因此,Archive 成功後沒有 IPA,通常不代表前面的編譯必然有問題。真正要問的是:這份 Archive 是否具備目標分發方式所需的簽名與授權條件。

為什麼 Archive 成功後仍然沒有 IPA?
因為 Archive 只是保存建置結果,Export 會重新檢查分發方式、簽名身份、Provisioning Profile、Entitlements,以及目前輸出目錄是否可寫。你應保留原始 Archive,直接重跑導出,先確認失敗發生在輸入、設定、簽名,還是遠端會話。

xcarchive 與導出輸入

先在同一個工作目錄執行導出,不要同時更換 Xcode、Scheme 或 Archive。命令中的專案名稱、Bundle ID、Team ID、使用者名稱與路徑應全部脫敏保存:

xcodebuild -exportArchive \
  -archivePath "/path/to/App.xcarchive" \
  -exportOptionsPlist "/path/to/ExportOptions.plist" \
  -exportPath "/path/to/export"

這裡有三個必須逐一驗收的輸入:

  1. archivePath 是否指向你剛剛檢查過的同一份 .xcarchive,而不是工作區清理後重新產生的檔案。
  2. exportOptionsPlist 是否真的被腳本讀取,路徑是否正確,內容是否符合目標分發方式。
  3. exportPath 是否已存在、可寫,且導出失敗後仍保留完整日誌與中間檔案。

對 Archive 本身,請在 Xcode Organizer 中檢查:

  • 預期的主 App 是否存在,版本與建置編號是否符合這次發版。
  • App Extension、App Clip 或其他 Target 是否一併收錄。
  • Archive 內的 Info.plist、簽名資訊與 Entitlements 是否存在。
  • Scheme、Configuration 與通用裝置目標是否正確,而不是針對模擬器產生的結果。

若 Organizer 的 Validate 或 Distribute App 也無法處理這份 Archive,優先修正 Archive 或簽名輸入;若圖形介面可以導出,命令列失敗,才把焦點移到 Plist 與遠端會話。

提醒: 不要先刪除 Archive、Profile 或憑證來「重新開始」。刪除前先保存原始檔、錯誤日誌與目前的簽名對照,否則你可能同時失去回退依據,讓真正的錯誤更難重現。

ExportOptions.plist 與分發方式

ExportOptions.plist 不是可以永久套用的通用模板。測試裝置分發、App Store Connect 發佈與其他分發方式,所需的 method、簽名管理方式、Team 與 Profile 映射可能不同。你應以目標 Mac 上執行的 xcodebuild -help 及當前 Apple 文件為準,不能直接沿用網路上的舊鍵值。

ExportOptions.plist 的分發方式與簽名設定如何核對?
先從一次成功的 Xcode 圖形介面導出取得可比較的設定,再逐項對照腳本中的 Plist。重點不是複製整份檔案,而是確認以下關係:

  • method 是否與這次要交付的對象一致。
  • Team 設定是否指向正確的開發者團隊。
  • 自動簽名或手動簽名是否與專案目前的設定相符。
  • 每個 Target,尤其是 Extension,是否都有對應的 Bundle ID 與 Profile。
  • 輸出路徑是否與 CI 工作目錄的權限和清理策略相容。

一旦出現 xcodebuild exportArchiveexit code 70,不要把它當成單一原因的錯誤碼。先從導出日誌中找第一個具體錯誤,再判斷是 Profile 不匹配、Entitlements 不符、分發方式不合,還是檔案權限問題。論壇中的個案只能用來理解錯誤表現,不能代替你目前 Xcode 版本的驗證。

簽名鏈與 Entitlements

導出階段至少要把下列資產分開檢查:

  • Apple Distribution 或其他目標分發所需的憑證。
  • 與憑證配對的私鑰。
  • 對應 App ID 的 Provisioning Profile。
  • Archive 內實際保存的 Entitlements。
  • 主 App、Extension 與第三方嵌套程式碼的簽名關係。

Apple 對憑證類型與用途有明確說明,可參考 Apple Developer Account 的憑證總覽。只匯入 .cer.p12 並不等於目前登入的 Keychain 能完成簽名;若私鑰不在同一個可用 Keychain,導出仍可能失敗。

Profile 也不要只以檔名判斷。從 Apple 帳戶重新編輯、下載或刪除 Profile 前,先確認影響範圍與回退方式;相關操作限制可查閱 Apple 的 Profile 管理說明

驗收時,將 Archive 內的 Entitlements 與 Profile 所授權的能力逐項比較:

  • Push Notifications、Associated Domains、App Groups 等能力是否一致。
  • Extension 的 App ID 是否與主 App 的嵌套關係吻合。
  • 手動簽名時,Plist 的 Profile 映射是否覆蓋所有 Target。
  • 自動簽名時,執行帳號是否能存取開發者帳戶及所需資產。

不要把「撤銷全部憑證、刪除全部 Profile」當作第一步。這種操作可能影響其他產品、CI 任務與已上線版本;只有在備份現有資產並確認沒有可用回退路徑後,才應評估重建。

本地匯出與 SSH 會話

本地可以導出 IPA,SSH 遠端執行為什麼失敗?
最常見的差異不是專案突然改壞,而是兩種會話沒有使用相同的使用者、Keychain、開發者目錄、工作路徑或暫存目錄。圖形登入可以解鎖的私鑰,不代表無人值守的 SSH 工作也能讀取。

請用同一個 macOS 使用者做對照:

  • 在互動式終端執行導出,保存完整標準輸出與錯誤輸出。
  • 在 SSH 或 CI 任務中執行完全相同的 Archive 導出命令。
  • 比較 whoami、工作目錄、DEVELOPER_DIRHOME 與輸出目錄的擁有者。
  • 確認目前 Keychain 是否可用,私鑰是否需要互動式解鎖或額外授權。
  • 確認任務結束後,Archive、Distribution 日誌與導出目錄沒有被清理。

你可以把每項指標標成「不通過」「可重試」或「通過」。若互動式終端通過、SSH 不通過,先修遠端會話;若兩者都不通過,回到 Archive、Plist 或簽名資產,不要繼續調整 SSH。

若團隊還沒有固定的遠端打包基線,可先參考 MacDate 的遠端 Mac 使用入口,再把使用者、Keychain、Xcode 版本與輸出保留策略寫入自己的驗收文件。

遠端 IPA 驗收清單

要判斷一台遠端 Mac 能否作為無人值守 IPA 打包環境,至少完成以下五步:

1. 固定可追溯輸入

保存脫敏後的 Archive 路徑、Xcode 版本、Scheme、Configuration、導出 Plist 與完整終端輸出。每次重試只改一項,否則無法知道是哪個變更造成結果不同。

2. 驗證 Archive 內容

用 Organizer 檢查主 App、Extension、Info.plist、簽名資訊與 Entitlements。若 Archive 內容不完整,先修正 Archive;不要用新的 Plist 掩蓋輸入缺失。

3. 對照圖形介面與命令列

使用同一份 .xcarchive,先在圖形介面導出,再以 xcodebuild -exportArchive 導出。兩次使用相同的目標分發方式,並保留兩組 Distribution 日誌。

4. 驗證遠端權限

切換到實際 CI 或 SSH 使用者,確認私鑰、Profile、工作目錄、輸出目錄與暫存目錄都可存取。需要帳戶角色時,也要依照 App Store Connect 角色權限文件 核對,而不是只在本地管理員帳號下測試。

5. 驗證重啟恢復

完成一次導出後,重啟遠端任務,再用相同 Archive 重做導出。檢查重啟、斷線或工作區清理後,錯誤日誌與中間檔案是否仍能保留。若每次都要手動開啟 Xcode、解鎖視窗或重新選擇帳戶,這台 Mac 還不算合格的無人值守打包機。

最後,若導出後還要上傳,請把 Upload 另外驗收。App Store Connect 的建置處理狀態與 IPA 本身是否成功產生,是兩件不同的事;可參考 Apple 的建置上傳狀態說明

決策對照:繼續修復還是更換環境

驗收結果 目前問題位置 下一步動作 評分
圖形介面與 SSH 都無法導出 Archive、Plist 或簽名輸入 固定 Archive,逐項修正導出設定與資產 不通過
圖形介面成功,SSH 失敗 使用者、Keychain、權限或工作目錄 以實際無人值守帳號重建會話驗收 可重試
同一 Archive 可重複導出,重啟後仍成功 遠端環境具備可重現性 才考慮接入 CI 或常駐打包流程 通過
只有更換全新 Archive 才能成功 輸入或清理流程不穩定 暫停自動化,先修 Archive 保留與版本固定 不通過
導出成功但上傳失敗 Upload 或 App Store Connect 權限 另行檢查帳戶角色與上傳狀態 可重試

這個對照不取代真實測試,而是避免把「偶爾成功」誤判成穩定環境。若你要把流程交給 fastlane,應先完成命令列導出,再參考 MacDate 的遠端 Mac 方案 評估是否需要一台可長時間保留工作狀態的獨立 Mac。長期高頻打包、必須使用實體介面或需要完全自行維護硬體的人,直接購買並管理本地 Mac 可能更合適;臨時發版、遷移驗收或需要隔離測試環境時,租用遠端 Mac 通常更容易先驗證流程,而不必立即承擔硬體採購、維護與閒置成本。

當你已確認同一份 Archive 在圖形會話中能導出,問題只出在原有機器的 SSH、Keychain 或重啟恢復,最穩妥的做法不是繼續重編譯,而是用驗收清單測試一台獨立遠端 Mac。先讓同一份 Archive 通過重複導出與任務重啟,再決定它是否值得成為常駐 iOS 打包機。

延伸閱讀