Xcode Cloud sudo 不可用:2026 該遷移遠端 Mac 嗎?

Xcode Cloud sudo 不可用:2026 該遷移遠端 Mac 嗎?

Apple 官方文件已確認,Xcode Cloud 的自訂建置腳本不能透過 sudo 取得系統管理員權限。官方自訂建置腳本說明也沒有提供以互動式密碼繞過這項限制的方法。獲勝者取決於阻斷點:只需安裝 Homebrew 工具、讀取環境變數或執行一般使用者腳本,就先修正 Xcode Cloud;若依賴管理員權限、常駐服務、跨建置持久化檔案或深度系統設定,則遷移至遠端 Mac。標準測試留在 Xcode Cloud、複雜發布任務交給遠端 Mac,通常是風險較低的雙軌方案。

這篇文章適合三類讀者:在 ci_post_clone.sh 安裝依賴卻被 sudo 或權限錯誤阻斷的獨立開發者;需要背景服務、自訂工具鏈或持久化快取的小型 App 團隊;以及正在比較 Xcode Cloud 與可控遠端 Mac 建置環境的發布維護者。

先從錯誤類型判斷:sudo 不是唯一問題

先將失敗日誌脫敏。使用者名稱、路徑、Repository、Bundle ID、Team ID、密碼與 Token 都應替換成明顯佔位符:

#!/bin/bash
set -euo pipefail

sudo brew install <PACKAGE_NAME>
chmod +x <SCRIPT_PATH>
./<SCRIPT_PATH>

可能的輸出如下:

sudo: command not found
zsh: permission denied: ./<SCRIPT_PATH>
<TOOL_NAME>: command not found

這三行代表不同問題:

  • sudo: command not found:腳本嘗試使用不被託管環境提供的管理員升權方式。
  • permission denied:可能是檔案沒有執行權限、路徑錯誤,或腳本使用了不適合目前 Shell 的格式。
  • command not found:工具未安裝、PATH 未設定,或依賴恢復步驟沒有在正確階段執行。

因此,不應把所有錯誤都歸因於 Xcode Cloud。先移除 sudo,再檢查命令、執行權限與環境變數。Apple 的工作流程參考文件說明了腳本階段與建置流程之間的邊界;這也是判斷命令放錯階段的重要依據。

Xcode Cloud 自訂腳本可以使用 sudo 嗎?
不能把 sudo 當成取得管理員權限的方案。若腳本必須修改系統目錄、全域安裝工具或調整 macOS 系統設定,重複輸入密碼、改用互動式 Shell 或增加授權環境變數,都不能改變託管環境的權限邊界。

依賴安裝:可重構的工具不必急著遷移

第三方工具安裝失敗時,先將依賴分成「建置工具」與「專案依賴」。

建置工具可能是格式化工具、程式碼產生器或測試輔助程式。若它能透過 Xcode Cloud 已提供的 Homebrew、專案內固定版本的二進位檔,或一般使用者目錄安裝,就不一定需要管理員權限。Apple 的讓依賴可供 Xcode Cloud 使用的說明是設定這類流程的主要依據。

#!/bin/bash
set -euo pipefail

export TOOL_HOME="${HOME}/<TOOL_DIRECTORY>"
mkdir -p "${TOOL_HOME}"

brew install <PACKAGE_NAME>
export PATH="${TOOL_HOME}:${PATH}"

<PACKAGE_NAME> --version

輸出應類似:

<PACKAGE_NAME> <VERSION>

這裡的 <VERSION> 只是待驗證的版本佔位符,不應在文章或腳本中硬編未核實的版本號。重點是:工具是否能在一般使用者目錄完成安裝,並在後續階段再次被找到。

CocoaPods、Carthage 與 Swift Package Manager 也不能一概視為 sudo 問題。依賴解析失敗可能來自 lockfile 不一致、快取失效、來源無法連線,或建置階段沒有讀取正確目錄。只有當依賴明確要求修改系統層級目錄或安裝核心元件時,才應把管理員權限列為遷移條件。

需要管理員權限的建置依賴怎麼安裝?
先尋找專案級替代方式:鎖定依賴版本、把可攜式二進位檔放入 Repository、使用一般使用者目錄,或在建置前明確設定 PATH。若工具仍要求系統全域安裝、修改 /Library 或載入系統元件,便不應繼續繞過限制;這是遠端 Mac 比較適合的訊號。

留在 Xcode Cloud 的驗收條件是:

  1. 乾淨環境可完成依賴恢復。
  2. 所有工具都能由一般使用者啟動。
  3. 腳本不要求互動式密碼。
  4. 後續 Archive 不依賴上一輪建置留下的本機狀態。

臨時檔案與快取:跨建置狀態才是分水嶺

Xcode Cloud 的工作流程包含臨時建置環境。Apple 的首次設定 Xcode Cloud 工作流程文件環境變數參考可用來確認腳本階段、輸入值與建置資料如何交接,但不能把一次建置的本機目錄當成永久磁碟。

產生檔案時,先判斷它屬於哪一類:

  • 可重建的中間檔:每次建置重新產生,不必保留。
  • 應交付的資源:放入 Repository、ci_scripts 可用資源、建置產物或外部儲存。
  • 大型依賴快取:若失效後仍能重建,可接受每次恢復;若失效會使發布流程無法運作,就要評估持久化主機。
  • 現場狀態:例如手動修改過的工具設定、背景程序狀態或未提交的產生檔。這類狀態不適合依賴臨時建置環境。

Xcode Cloud 腳本產生的檔案為什麼不能持續保留?
因為工作流程的建置環境不是可由團隊長期控制的工作站。腳本在本次工作流程中產生的檔案,只有在被提交、列為建置產物、傳到外部儲存,或由後續明確支援的階段接收時,才具備可交接性。把檔案留在家目錄,不能等同於跨建置保存。

注意: 不要用「上一輪建置剛好成功」作為持久化證明。應建立全新工作流程,從依賴恢復開始驗證,否則快取或未預期的環境差異可能掩蓋腳本缺陷。

背景服務與系統設定:短命程序不等於常駐主機

可在單次建置內以一般使用者啟動的服務,與必須長時間運作的服務,決策完全不同。

例如,測試用的本機 HTTP 服務或模擬服務,若能由腳本啟動、在測試結束後關閉,且不需要修改 macOS 全域設定,仍可能留在 Xcode Cloud。腳本必須處理啟動順序、埠號、健康檢查與結束清理:

#!/bin/bash
set -euo pipefail

<LOCAL_SERVICE> --config <CONFIG_PATH> &
SERVICE_PID=$!

cleanup() {
  kill "${SERVICE_PID}" 2>/dev/null || true
}
trap cleanup EXIT

curl --fail http://127.0.0.1:<PORT>/health
xcodebuild -workspace <WORKSPACE>.xcworkspace \
  -scheme <SCHEME> \
  -destination '<DESTINATION>'

輸出應能看見健康檢查成功,並在建置結束後完成清理。若服務需要守護程序、系統擴充功能、全域設定、固定資料庫狀態,或必須在多次建置之間持續存在,Xcode Cloud 就不是合適的長期承載環境。

遠端圖形工作階段、背景程序與無人值守建置也不要混為一談。VNC 方便查看螢幕,SSH 適合執行命令;但能透過圖形介面連線,不代表建置程序會在斷線後自動恢復。真正需要的是可重啟、可記錄、可由腳本恢復的主機狀態。

簽署失敗:先分離 sudo、Keychain 與憑證問題

Archive 或上傳失敗時,遷移環境前應拆解四個層次:

  1. 秘密環境變數是否在正確的腳本階段可讀取。
  2. Keychain 是否允許非互動式建置程序存取。
  3. 憑證與私密金鑰是否成對存在。
  4. Provisioning Profile、Bundle ID 與團隊設定是否一致。

Apple 的團隊簽署憑證說明雲端管理憑證文件可用於核對憑證交付方式。這些問題不等於系統管理員權限。某個 Keychain 項目拒絕存取,不能直接推出需要 sudo;同樣地,私密金鑰遺失也不是換伺服器就會自動修好。

提醒: 任何修改 Keychain 存取控制、替換簽署資產或放寬秘密權限的操作,都應先記錄影響範圍,並保留可回退的憑證與 Profile。最小權限比把所有 Token 放進全域環境更容易維護。

建議把驗證拆成:

security find-identity -v -p codesigning
xcodebuild -workspace <WORKSPACE>.xcworkspace \
  -scheme <SCHEME> \
  -configuration Release \
  -archivePath <ARCHIVE_PATH> archive

若列出的身份不完整,先修正簽署資產。若身份完整但 Keychain 在無人值守流程中拒絕存取,再檢查存取控制與秘密注入方式。Apple 的工作流程環境變數文件可協助確認變數名稱與使用階段,避免把憑證錯誤誤判成 sudo 阻斷。

用條件分支決定修腳本、雙軌或遷移

以下決策卡應套用在實際失敗腳本,而不是只看一次 Build Succeeded

  • 所有依賴都能以一般使用者目錄或 Xcode Cloud 已提供工具安裝,則選擇修正 Xcode Cloud
  • 只有標準測試、Pull Request 建置與可重建的產生檔,則留在 Xcode Cloud
  • 測試可留在 Xcode Cloud,但 Archive、簽署、上傳需要固定工具鏈或較完整主機控制,則選擇雙軌流程
  • 依賴系統管理員權限、常駐背景服務、跨建置大型快取或深度 macOS 設定,則遷移至遠端 Mac
  • 失敗只出現在憑證、Keychain 或環境變數,則先修正憑據設計,不因 sudo 字樣直接遷移
  • 遠端 Mac 的流程只能靠手動點擊、VNC 連線不能中斷,則暫緩遷移,先補上 SSH、日誌、重啟與無人值守腳本

這套分支把「需要完整主機控制」與「只是腳本寫法不正確」分開。遠端 Mac 不是修復錯誤命令的捷徑;它的價值在於提供可持續管理的主機、檔案與系統設定。

三張表快速比較建置方案

阻斷問題 修正 Xcode Cloud 雙軌流程 遠端 Mac
Homebrew 或一般使用者工具 優先選擇 不必切換 通常過度配置
依賴系統全域安裝 不適合 發布任務移出 較適合
單次測試服務 可由腳本啟動 測試留在雲端 只有需要常駐時採用
跨建置持久化狀態 改存 Repository 或外部儲存 依任務分流 可由主機管理
Keychain 與簽署失敗 先修憑證設計 測試與發布分開 仍需正確設定憑證
系統級設定或守護程序 不適合 複雜任務移出 較適合
驗收項目 只留 Xcode Cloud 雙軌 遷移遠端 Mac
依賴恢復 乾淨環境成功 測試流程成功 主機重啟後仍可恢復
Archive 不依賴本機狀態 發布線獨立驗證 以固定腳本執行
簽署 非互動式可讀取 發布環境獨立保護 Keychain 存取可審計
上傳 工作流程可完成 僅發布線執行 SSH 或排程可執行
失敗復現 重新建立環境 分別記錄兩條線 保留主機日誌與設定
任務特性 停止遷移、回到修腳本 進入雙軌驗證 遷移必要條件
sudo 只用於安裝可攜式工具
測試需短時間啟動本機服務 可選
Archive 依賴固定系統設定
快取遺失只增加恢復時間 可選
快取遺失會使發布中斷
需要長期背景服務

同一個 App 最終應完成依賴恢復、Archive、簽署、上傳,以及主機或工作流程重建後的恢復測試。只驗證一次成功建置,無法證明環境可維護。

從 Xcode Cloud 轉移前的五步操作

  1. 保留原始失敗日誌:替換敏感值,但不要刪除錯誤類型、腳本階段與命令順序。
  2. 建立最小建置分支:只留下依賴安裝、測試與 Archive,暫時移除無關的部署命令。
  3. 移除升權假設:刪除 sudo,改測試一般使用者目錄、明確 PATH 與專案內工具。
  4. 標記狀態來源:把每個產生檔案分類為可重建資源、建置產物、外部資料或必須持久化的主機狀態。
  5. 分離簽署驗證:先確認環境變數、Keychain、憑證私密金鑰與 Profile,再測試 Archive。
  6. 測試背景服務生命週期:確認服務能啟動、健康檢查、在建置結束時清理,或明確標記為常駐需求。
  7. 執行方案驗收:若普通建置能穩定完成而發布需要主機控制,採用雙軌;若全部需求都可重建,繼續留在 Xcode Cloud。

若只是想查看遠端環境的連線方式,可先參考 SFTPMAC 的遠端 Mac 服務入口;若已確定需要短期主機進行 Archive,則應先核對 Mac 租用方案與計費資訊,再以實際專案做驗收,而不是只比較硬體名稱。

對多數獨立開發者而言,Xcode Cloud 目前的限制不是單純缺少一個命令,而是託管環境與主機控制權的差異。只要依賴能以一般使用者腳本完成,修正流程通常比遷移更直接;但若現有方案包含全域安裝、常駐服務、不可重建快取與深度系統設定,繼續強行改腳本只會增加發布風險。此時讓標準測試留在 Xcode Cloud,把複雜發布交給 SFTPMAC 的遠端 Mac,並以短週期的依賴恢復、Archive、簽署、上傳與重啟恢復測試作為進入條件,會比僅因一行 sudo 報錯就全面更換環境更穩妥。