保留流程,更換執行機器

這些流程,都能在雲端 Mac 上順利執行

將必須依賴 macOS 的建置與測試工作移至獨享實體 Mac mini。原生 iOS、Flutter、Unity 與 MLX 各有不同的資源瓶頸:先查看指令與前置條件,再依記憶體、快取及工作並行需求選擇方案。這裡提供可實際採用的工作流程,而非耗時基準測試。

獨享實體機,非虛擬機。按日租用,最低 $20.5/天;可用狀態以控制台即時回傳為準。

依工作負載選擇

共 5 種場景,全部展開。選擇分類可醒目標示並定位相關場景,不會隱藏其他內容。

從觸發條件到驗收產物

找到適合你的執行工作。

以下指令皆在節點上執行。請先安裝專案依賴,再設定對應的環境變數;路徑請指向你自己的專案與設定檔。複製只會複製指令,不會執行工作。

原生 iOS · 夜間建置

讓 Git 推送觸發封存,並交由 fastlane 上傳。

將雲端 Mac 註冊為 GitHub Actions self-hosted runner、GitLab Runner 或 Jenkins agent。推送至發布分支後,先簽出固定提交,再產生 Release 封存檔與 IPA。TestFlight 上傳是獨立步驟,方便將建置失敗與上傳失敗分開重試。

請先準備以下三項

  • 設定 WORKSPACE、SCHEME 和 EXPORT_OPTIONS,分別指向工作區、共用 scheme 與匯出設定。
  • 請在目前的建置使用者帳戶中設定簽署憑證與描述檔;可使用 fastlane match 管理,並透過 CI 密鑰注入解密所需的憑證。
  • 設定 ASC_API_KEY_JSON,指向 fastlane 使用的 App Store Connect API 金鑰 JSON 檔。請勿將金鑰放入程式碼儲存庫。

驗收時要檢查什麼

封存檔 build/App.xcarchive、匯出的 IPA、提交識別碼與 Xcode 版本。請確認 TestFlight 已收到對應版本;建置指令成功結束,不代表上傳已完成。

機型建議:Host M4 Plus 的 24GB 統一記憶體適合日常多 target 建置。先以序列方式確認流程順利,再依記憶體壓力與 DerivedData 用量,決定是否提高並行數。

封存 → 匯出 → 上傳
set -euo pipefail
: "${WORKSPACE:?Set WORKSPACE}"
: "${SCHEME:?Set SCHEME}"
: "${EXPORT_OPTIONS:?Set EXPORT_OPTIONS}"
: "${ASC_API_KEY_JSON:?Set ASC_API_KEY_JSON}"

mkdir -p build
xcodebuild -version
xcodebuild \
  -workspace "$WORKSPACE" -scheme "$SCHEME" \
  -configuration Release \
  -destination 'generic/platform=iOS' \
  -archivePath build/App.xcarchive archive

xcodebuild -exportArchive \
  -archivePath build/App.xcarchive \
  -exportPath build/export \
  -exportOptionsPlist "$EXPORT_OPTIONS"

IPA_PATH="$(find build/export -type f -name '*.ipa' -print -quit)"
test -n "$IPA_PATH"
bundle exec fastlane pilot upload \
  --ipa "$IPA_PATH" \
  --api_key_path "$ASC_API_KEY_JSON"
方案:Host M4 Plus · M4 / 24GB / 512GB 建議節點:日本(東京)
租用 Host M4 Plus

跨平台 · Flutter

Android 繼續在 Linux 執行,只遷移 iOS 工作。

不必搬遷整條雙平台流程。Linux runner 保留 Android 工作,雲端 Mac 負責 CocoaPods、Xcode 編譯與 IPA 匯出。兩端使用相同的提交識別碼,最後再彙整產物;其中一端失敗時,只需重跑該端工作。

設定快取失效條件

  • 固定 Flutter、Ruby、CocoaPods 與 Xcode 版本,並保留 pubspec.lock、Podfile.lock 和 Gemfile.lock。
  • 快取 Pub 與 CocoaPods 的下載目錄;快取鍵至少須包含工具鏈版本與依賴鎖定檔摘要。
  • 請勿讓多個並行工作寫入同一個專案目錄。依工作隔離 DerivedData 與輸出目錄,避免快取互相污染。

驗收時要檢查什麼

保存 build/ios/ipa 中的簽署 IPA、建置記錄與依賴鎖定檔。先透過裝置安裝或後續測試工作驗證產物,再將建置結果標記為可發布。

機型建議:Host M4 Lite 適合從單一工作開始。若同時開啟模擬器、執行測試並打包,請先測量記憶體峰值,再考慮升級至 Host M4 Plus,而不是直接增加並行數。

Flutter · iOS 工作
set -euo pipefail
: "${EXPORT_OPTIONS:?Set EXPORT_OPTIONS}"

flutter --version
xcodebuild -version
flutter doctor -v
bundle check || bundle install
flutter pub get

(
  cd ios
  bundle exec pod install --deployment
)

flutter build ipa \
  --release \
  --export-options-plist="$EXPORT_OPTIONS"

find build/ios/ipa -type f -name '*.ipa' -print
方案:Host M4 Lite · M4 / 16GB / 256GB 建議節點:新加坡
租用 Host M4 Lite

遊戲 · iOS 封裝

接手 Unity 匯出的專案,再進行簽署、封裝與容量檢查。

Unity 資源處理與 Xcode 編譯分為兩個階段。先使用專案本身的匯出流程產生 Xcode 專案,再由雲端 Mac 執行封存與匯出。使用同一套資源設定比較封裝大小,才能判斷差異來自資源、編譯選項還是匯出方式。

明確界定匯出流程

  • UNITY_IOS_DIR 指向已匯出的 iOS 專案目錄。以下指令從 Xcode 階段開始執行,不會取代專案的 Unity 建置腳本。
  • 如果外掛程式產生了 workspace,請設定 UNITY_WORKSPACE;否則請使用 Unity-iPhone.xcodeproj。請勿混用這兩種入口。
  • 準備好簽署設定與 EXPORT_OPTIONS。若需要 App Thinning 報告,請在匯出設定中啟用相應選項。

驗收時要檢查什麼

檢查 IPA 檔案大小、匯出記錄與資源變更。IPA 壓縮後的大小不等於使用者實際下載或安裝的大小;發布決策還須參考匯出報告與發佈處理結果。

機型建議:Host M4 Pro 配備 64GB 統一記憶體與 2TB SSD,適合資源量較大的專案及封存快取。請先記錄資源匯入、編譯與匯出各階段的用量,再安排工作佇列。

Unity 匯出 → Xcode
set -euo pipefail
: "${UNITY_IOS_DIR:?Set UNITY_IOS_DIR}"
: "${EXPORT_OPTIONS:?Set EXPORT_OPTIONS}"

mkdir -p build
if [ -n "${UNITY_WORKSPACE:-}" ]; then
  xcodebuild -workspace "$UNITY_WORKSPACE" \
    -scheme Unity-iPhone -configuration Release \
    -destination 'generic/platform=iOS' \
    -archivePath build/Game.xcarchive archive
else
  xcodebuild \
    -project "$UNITY_IOS_DIR/Unity-iPhone.xcodeproj" \
    -scheme Unity-iPhone -configuration Release \
    -destination 'generic/platform=iOS' \
    -archivePath build/Game.xcarchive archive
fi

xcodebuild -exportArchive \
  -archivePath build/Game.xcarchive \
  -exportPath build/game-export \
  -exportOptionsPlist "$EXPORT_OPTIONS"

find build/game-export -type f -name '*.ipa' \
  -exec du -h {} \;
方案:Host M4 Pro · M4 Pro / 64GB / 2TB 建議節點:韓國(首爾)
租用 Host M4 Pro

原生 iOS · 相容性回歸測試

固定 Xcode 版本,逐一跑完模擬器測試矩陣。

新系統相容性不只看編譯是否成功。請將核心導覽、權限提示、深色模式與重要版面納入測試,並依 Xcode 版本與模擬器執行環境保存結果。先確保測試矩陣可按序重現,再決定哪些測試適合並行執行。

版本與裝置都要可追溯

  • 可使用 xcodes 管理多個 Xcode 版本。透過各項工作的 DEVELOPER_DIR 選擇版本,避免並行工作修改整台機器的預設工具鏈。
  • 先查看目前 Xcode 可用的模擬器,為 SIM_A 與 SIM_B 指定不同裝置的 UDID;執行前須先安裝對應的執行環境。
  • 保留 .xcresult,不要只保存終端機最後一行。UI 截圖、失敗案例與重試記錄,都必須能對應到同一個提交。

驗收時要檢查什麼

逐一核對各測試目標的結束碼與結果檔。模擬器回歸測試無法取代真機上的周邊設備、效能與發佈驗證;這些工作應另外安排。

機型建議:Host M4 Plus 可作為日常回歸測試的起點。模擬器數量應依實際記憶體壓力決定,24GB 不代表可以無限制並行。

Xcode · 模擬器測試矩陣
set -euo pipefail
: "${DEVELOPER_DIR:?Set DEVELOPER_DIR}"
: "${WORKSPACE:?Set WORKSPACE}"
: "${SCHEME:?Set SCHEME}"
: "${SIM_A:?Set SIM_A}"
: "${SIM_B:?Set SIM_B}"
export DEVELOPER_DIR

mkdir -p build
xcodebuild -version
xcrun simctl list devices available

RUN_ID="$(date +%s)-$$"
for DEVICE_ID in "$SIM_A" "$SIM_B"; do
  xcodebuild test \
    -workspace "$WORKSPACE" \
    -scheme "$SCHEME" \
    -destination "platform=iOS Simulator,id=$DEVICE_ID" \
    -parallel-testing-enabled NO \
    -resultBundlePath \
      "build/$RUN_ID-$DEVICE_ID.xcresult"
done
方案:Host M4 Plus · M4 / 24GB / 512GB 建議節點:香港
租用 Host M4 Plus

AI · MLX 推論實驗

將模型載入統一記憶體,先確認能否穩定執行。

在 Apple Silicon 實體節點上使用 MLX 載入相容模型,記錄生成速度、記憶體峰值與上下文長度。先驗證單一請求,再測試批次處理;建置工作與推論實驗會共用同一台機器的資源,未經測量不宜同時滿載執行。

先確認模型與資源限制

  • MODEL_DIR 指向已備妥的 MLX 相容模型目錄。請確認模型來源、使用授權、量化格式與依賴版本。
  • 64GB 是整台機器的統一記憶體,系統、模型權重、快取與其他程序都會占用。能否載入取決於模型與上下文設定。
  • 固定提示詞與生成長度,記錄冷啟動及後續請求。模型下載時間不應計入推論吞吐量。

驗收時要檢查什麼

保留模型版本、量化設定、MLX 環境與執行記錄。使用 /usr/bin/time -l 輔助觀察程序用量,再搭配系統記憶體壓力,判斷是否發生換頁。

機型建議:Host M4 Pro 的 64GB 統一記憶體,適合需要較大記憶體空間的實驗。2TB SSD 可儲存模型檔案與實驗產物,但不會增加模型可用的記憶體。

MLX · 本機推論
set -euo pipefail
: "${MODEL_DIR:?Set MODEL_DIR}"

python3 -m venv .venv
. .venv/bin/activate
python -m pip install mlx-lm
mkdir -p build

python -m pip freeze > build/mlx-environment.txt
/usr/bin/time -l \
  python -m mlx_lm.generate \
    --model "$MODEL_DIR" \
    --prompt "Explain reproducible builds." \
    --max-tokens 128 \
    > build/mlx-output.txt \
    2> build/mlx-metrics.txt

cat build/mlx-output.txt
cat build/mlx-metrics.txt
方案:Host M4 Pro · M4 Pro / 64GB / 2TB 建議節點:美國西部
租用 Host M4 Pro

複製指令後,請先在自己的專案目錄中確認變數與簽署設定,再執行。

建議配置不代表效能保證

先用一次完整工作校準配置。

上述節點是依團隊協作時區提出的建議,並非實測網路延遲。程式碼儲存庫、產物儲存位置與操作人員所在位置,也都會影響使用體驗。

01

記錄資源峰值

固定提交與依賴版本,執行一次完整工作。分別記錄記憶體壓力、快取大小與產物大小,避免只憑單次編譯時間選擇方案。

02

分開排程與執行

先使用單一執行器。確認工作穩定後,再增加並行數;請分別記錄 runner 等待時間、依賴下載時間與編譯時間。

03

選擇符合協作需求的節點

可選新加坡、日本(東京)、韓國(首爾)、香港、美國西部,共 5 個節點。先確認專案同步與互動連線順暢,再為團隊固定執行地點。

明確訂出驗收標準

你希望明早看到什麼?

以下列出三種角色的情境化使用目標,並非客戶評價或實測記錄。將目標納入流程驗收,比只追求單次建置更快更有幫助。

「我希望早上就能拿到對應提交的封存檔、測試結果與失敗記錄,不必再先檢查辦公室的打包機。」
iOS 負責人 · 夜間建置目標
「我只遷移 Flutter 的 iOS 工作。雙平台共用同一個提交,失敗時可單獨重跑,不必整條流程推倒重來。」
行動端架構師 · 流程拆分目標
「我需要一併保存模型版本、記憶體用量與生成結果。實驗必須能重現,才能作為下次選擇機器的依據。」
演算法工程師 · 推論實驗目標

先選執行工作,再選機器。

單一工作可從 Host M4 Lite 起步;多 target 與日常回歸測試可選 Host M4 Plus;大型專案及記憶體密集型實驗則可選 Host M4 Pro。前往方案頁確認三種規格、四種租期與附加項目,再提交訂單。

所有費用均以美元計價。僅支援 USDT-TRC20 與 Visa / Mastercard / Amex(透過 Stripe);實際可用的支付閘道以後端介面回傳為準。