最初に押さえるポイント
- 遅い原因は xcodebuild 単体ではなく、キャッシュと実行環境のライフサイクル差です。
- GitHub-hosted は毎回コールドスタート、自前Runner はウォーム状態を維持しやすいです。
- DerivedData と CocoaPods を持続化できると、待ち時間の主要部分を削れます。
- ディスク逼迫や署名準備は「コンパイル遅延」に見えるため、段階計測が必須です。
- Flutter iOS チームはまず Macレンタルで 48 時間の実測を取り、月額運用へ進むのが安全です。
ローカル Mac と GitHub Actions の差はどこで生まれるか
ローカルで計測するとき、多くのチームは次のような前提で比較しています。
- ローカル: 持続 SSD + 温まった依存状態 / CI: 使い捨て VM + コールド依存。
- ローカル: 同じ署名環境 / CI: 毎回 keychain ブートストラップ。
- ローカル: 同一ホスト反復ビルド / CI: 分岐ごとのキャッシュミス。
一方 CI パイプラインでは、だいたい次のような運用になります。
- 毎回クリーンなワークスペースに checkout する。
flutter build ipaやxcodebuild archiveを Release で実行する。- ホステッド Runner ではキャッシュが残りにくく、毎回コールドスタートになる。
多くの比較は `xcodebuild archive` だけを見ますが、実際には checkout、pod install、keychain 解錠、DerivedData 失効が積み重なります。これが体感 2〜3 倍の正体です。
xcodebuild が CI で 2〜3 倍遅くなる 5 つの原因
GitHub Actions 利用中でも、自前Runnerへ移行中でも、Flutter iOS で繰り返し出る要因です。
- 1) 無状態 Runner が依存レイヤーを毎回リセット GitHub-hosted VM はジョブごとに新規生成されるため、SPM・Pods・モジュールキャッシュが安定して温まりません。actions/cache だけでは吸収し切れないケースが多いです。
- 2) DerivedData パスの揺れで増分ビルドが崩れる 一時パスを使うと、ローカルで再利用できる成果物が CI では無効扱いになり、再コンパイルが増えます。
- 3) Flutter プラグイン更新で Pods 解決がコールド化 プラグイン更新により lockfile が揺れると `pod install` が毎回重くなります。deployment モードで再現性を固定してください。
- 4) 署名と keychain 準備が直列オーバーヘッド 証明書インポート、keychain 作成・解錠は CI で毎回発生します。ローカルでは既存状態を活かせるため差が出ます。
- 5) ディスク/ inode 圧迫が静かにビルドを遅くする CPU だけ見ても不十分です。空き容量不足や inode 枯渇は、インデックス更新と書き込みを確実に遅くします。
ステージ別計測ログ(Flutter iOS 例)
まずこの形式で可視化し、原因を定量化してから環境移行を判断してください。
| ステージ | ローカル Mac | GitHub Actions | 典型要因 |
|---|---|---|---|
| flutter pub get | 0m25s | 1m10s | pub キャッシュが十分温まっていない |
| pod install | 1m30s | 4m45s | Specs と plugin pod 解決がコールド |
| xcodebuild compile/archive | 6m40s | 12m20s | DerivedData 非再利用 |
| codesign/export | 0m55s | 2m00s | keychain 準備を毎回実施 |
| 合計 | 9m30s | 20m15s | 約 2.1 倍 |
xcodebuild を疑う前に
xcodebuild の前に pod install を見落としていないか確認してください。CI で CocoaPods が遅くなる典型原因は次の 3 つです。
Podfile.lock未コミット — 依存解決が毎回不安定になる。ios/Podsのキャッシュなし — ジョブ終了後に消える。- 不要な
pod repo update— lockfile があるなら通常不要。
CI では pod install --deployment を使い、Pods を同一 SSD パスに保持します。セルフホスト Mac mini なら GitHub へのキャッシュ転送待ちを避けられます。
DerivedData / Pods / キャッシュの実務設計
Flutter iOS では DerivedData の絶対パス固定と Pods キャッシュの整流化が最も効くことが多いです。自前Runnerなら、CI を使い捨てから継続運用型へ変えられます。
GitHub-hosted 継続でもパスと lockfile を決め打ちにすれば改善します。移行可能なら、Macレンタルで検証後に自前Runner化するとローカルに近い挙動になります。
- target ごとに固定 derivedDataPath を採用。
- `pod install --deployment` で lockfile ドリフト抑制。
- 空きディスクと inode を CI 指標として継続監視。
修正テンプレート: パス固定 + 依存解決の決定性
以下は過度な最適化を避けた現実的なベースです。まず再現性を優先します。
- workflow に
concurrencyを追加 — 同一ブランチの古いビルドをキャンセル。 - テストは Linux で実行 — Mac 時間を
flutter testに使わない。 - Pods + DerivedData を永続化 — セルフホストは固定パス、ホステッドは細かい cache key。
- 配布する flavor だけビルド — 6 flavor スキャンは不要。
- Xcode / Flutter バージョンを固定 — CI 内の
upgradeを避ける。
# .github/workflows/ios-ci.yml
jobs:
ios:
runs-on: [self-hosted, macOS, ARM64, flutter-ios]
steps:
- uses: actions/checkout@v4
- name: Restore caches
run: |
mkdir -p "$HOME/Library/Caches/CocoaPods"
mkdir -p "$HOME/.pub-cache"
- name: Build with stable DerivedData path
run: |
flutter pub get
cd ios
xcodebuild -workspace Runner.xcworkspace -scheme Runner -configuration Release -destination 'generic/platform=iOS' -derivedDataPath "$HOME/ci-derived/runner" CODE_SIGNING_ALLOWED=NO
- name: Keep pod install deterministic
run: |
cd ios
pod install --deployment
この土台だけで 30〜50% 改善するチームは珍しくありません。次に自前Runnerプールで中央値を詰めていきます。
速度回帰のマージ前チェック
Flutter / Xcode 更新後に CI が遅くなったら毎回実施。
- ☐ CI は Release / IPA、ローカル比較は Debug
- ☐ Job で
flutter cleanや DerivedData 削除を実行 - ☐
pod installログで毎回大量 Installing - ☐ GitHub ホステッド Runner でローカル SSD キャッシュなし
- ☐ 16GB マシンで複数 Job やシミュレータを同時実行
- ☐ README 変更でも iOS フルビルドが走る
- ☐ CI の Xcode バージョンがローカルと不一致
上 3 項目にチェックがあればキャッシュ優先。下 2 項目ならトリガー条件とマシン仕様を見直してください。
FAQ
GitHub Actions は常にローカルより遅いですか?
常にではありませんが、Flutter iOS ではキャッシュが温まらない構成だと遅くなりやすいです。自前Runnerで差を縮められます。
すぐ自前Runnerへ移行すべきですか?
まず計測です。冷スタート損失が継続しているなら 1 workflow を自前Runnerで A/B 比較してください。
高価なマシンが必須ですか?
必須ではありません。安定キャッシュ前提なら、Macレンタルの Apple Silicon で十分改善できます。
チーム説得の材料は?
ステージ別時間を待機コストに換算し、速度だけでなくリリース予測性の改善も示すのが有効です。
クラスタ関連記事
xcodebuild の CI 遅延を体系的に潰すなら、この順番が実務向きです。
- ハブ: Flutter iOS CI 全体設計
- キャッシュ設計: DerivedData / CocoaPods / SPM
- GitHub Actions 向け自前Runner導入(クラウドMac)
- iOS CI 署名運用を安定化する方法
- 長期 Runner のディスク・inode 監視
安定した iOS CI を実機 Apple Silicon で
kvmboot のクラウド Mac なら Flutter iOS パイプライン向けに専有運用できます。まず Macレンタル(日次)で計測し、合えば月額の自前Runnerへ。
CI のばらつきを減らしてリリース速度を戻したいなら、 プランを見る