← 技術ブログに戻る

Flutter iOS CI/CD:Mac mini M4 で IPA を組み、CocoaPods キャッシュを最適化する

Flutter iOS CI/CD:Mac mini M4 上の flutter build ipa と self-hosted Runner
典型的な分担:Windows/Linux で Dart、Mac mini M4 Runner で IPA。

この記事は一点に絞ります:Flutter iOS CI/CD(主キーワード:Flutter iOS build on Mac mini)——Mac mini M4 上で flutter build ipa を安定させ、CocoaPods キャッシュself-hosted macOS Runner、Linux 側の Android/テスト job を分離する方法です。Flutter の本当のボトルネックは Dart ではなく、iOS ビルドチェーンの Mac 依存pod installxcodebuild archive → 署名 → TestFlight アップロード。この一連は Mac 以外では完結しません。当チームは典型的なクロスプラットフォーム分担:Android は Windows/Linux CI、Flutter iOS CI はラックの専用 Mac mini 固定。ネイティブ Xcode 混在なら Xcode ビルドをクラウドへ、Runner 登録と TCO は 自前 macOS Runner を参照。

1)Flutter iOS CI が専用 Mac を要する理由

「一つのコードベース」が解くのはビジネスロジックの再利用であり、ビルド面の再利用ではありません。iOS 成果物は依然としてフル Xcode パイプラインを通り、ubuntu-latest では Flutter iOS CI は成立しません。GitHub ホステッド macOS は分単価が高くキューも不安定で、job ごとにキャッシュが消えると flutter build ipa は再び 15–25 分帯に戻ります。Flutter iOS CI/CD を永続環境の Mac mini に置く価値は、Flutter/Xcode 版の固定3 層キャッシュの再利用24/7 スリープなし——Android と iOS のリリース cadence を本当に切り離せます。

境界: flutter testbuild apk は Linux に残す。Flutter iOS CI 専用機は iOS 統合ビルドと署名関連のみ。

2)Flutter iOS CI クラウド構成図

以下は本番で運用中の Flutter iOS CI/CD トポロジ。開発者全員が手元に Mac を持つ必要はなく、iOS パッケージは self-hosted Runner が生成します。

Flutter iOS CI クラウド構成

開発者(Windows/Linux/Mac)
ローカル:Dart · Android · git push
GitHub Actions · ubuntu-latest
flutter test · build apk
Mac mini M4 · self-hosted Runner
labels: macos, flutter-ios
fvm flutter build ipa
pod install · xcodebuild archive
TestFlight/App Store Connect

Mac mini 上の永続キャッシュ層(Flutter iOS CI 高速化の要)

  • ~/.pub-cache
  • CocoaPods cache
  • DerivedData

3)Flutter iOS CI の 3 つの運用パターン

パターンローカル/他 CIクラウド M4 Mac向き
A. iOS ビルドだけクラウド日常 flutter run、Android パッケージbuild ipa、ストア提出ハイブリッド主力(Win/Linux + 実機)
B. Flutter フルリモート(稀)エディタ + git のみシミュレータ、flutter doctor 全緑手元 Mac なし、VNC 遅延許容
C. クラウド Mac = iOS RunnerPR で Linux jobラベル macos の self-hosted Runner頻繁リリース、強キャッシュ

当方は A + C:マージ後 Linux で flutter testFlutter iOS CI は tag/main マージ時のみ Mac mini Runner。B は短期の Mac なし接続向け、長期は Runner 化推奨。

4)Flutter iOS CI 環境チェックリスト(Mac mini 初回セットアップ)

  1. Xcode + CLT: ios/Podfile と Flutter チャネルが要求する最低版に合わせる。インストール後 sudo xcodebuild -license accept
  2. Flutter SDK: fvm または ~/flutter 固定。リポに .fvmrc を書き、メンバーと CI の版ズレを防ぐ。
  3. CocoaPods: gem install cocoapods または Homebrew。大規模リポは Podfile.lock をコミット。
  4. 署名: Fastlane Match または Xcode 自動署名。p12 とプロビジョニングはGit に入れない。暗号化リポまたは CI Secret へ。
  5. ネットワーク: Git リモートと pub.dev/CDN に近いリージョン。社内 Git は VPN/専線。出口要件は ヘルプセンター

新マシンで初回 flutter doctor -v を実行し、出力を Wiki に貼る——以降のトラブルシュートはこの「ゴールデンスナップショット」から。

5)CocoaPods キャッシュ最適化:Flutter iOS CI 高速化の核(Before/After 付き)

中規模 Flutter リポ(plugins 40+、Release IPA)を 3 環境で各 3 回、中央値で比較——Flutter iOS CI の差はほぼ「キャッシュが Mac mini に残るか」だけです。

表:Flutter iOS CI フル build ipa 所要時間(分・同一リポ · 2026-05 実測)
環境初回ビルド(コールド)2 回目(キャッシュヒット)
手元 MacBook Air M2(8GB、蓋閉じ/降クロック)18–25 min12–15 min
GitHub ホステッド macos-latest(カスタムキャッシュなし)16–22 min14–18 min
Mac mini M4(16GB)· Flutter iOS CI + 3 層キャッシュ15–20 min4–8 min

2 回目を 12 分以上から一桁分へ圧縮できるのは構成図の 3 層永続化のおかげ——Flutter iOS build on Mac mini を「ビルドできる」から「CI として使える」へ引き上げた分岐点です。

  • PUB_CACHE~/.pub-cache Runner 環境変数でパス固定、job 間で Dart 依存を再利用。
  • CocoaPods cache + ios/Pods Podfile.lock 不変なら pod install スキップ。変更時は増分のみ。
  • DerivedData: ~/DerivedData 固定。Xcode メジャーアップ以外は clean しない。
定量: 週 1 回以上 iOS リリースなら、Mac mini 上の Flutter iOS CI でキャッシュヒット後、1 pipeline あたり約 8–12 分短縮。月 4 回 × 3 名待ち = 丸一日分のキュー時間。

6)Flutter iOS CI コマンドフロー(SSH または Runner スクリプト)

リポルートで実行。Flutter 版はプロジェクト固定版に置き換えてください:

cd ~/work/my_flutter_app
export PUB_CACHE=$HOME/.pub-cache
fvm flutter pub get
cd ios && pod install --repo-update && cd ..
fvm flutter build ipa --release \
  --export-options-plist=ios/ExportOptions.plist

GitHub Actions では上記を release-ios.yml に記述し、runs-on: [self-hosted, macos, flutter-ios]。TestFlight アップロード時、Mac mini の出口帯域と App Store Connect 経路は、自宅 Wi‑Fi より安定しがちです。

7)GitHub Actions:Flutter iOS CI/CD workflow の分割

2 workflow に分ける(または matrix の if で分流)ことを推奨:

  • test-android.yml ubuntu-latestflutter testbuild apk
  • release-ios.yml runs-on: [self-hosted, macos, flutter]。tag または main マージ時のみ build ipa + アップロード。

クラウド Mac で VNC デバッグと Runner を併用する場合、ビルド用の別システムユーザーを切る——手動編集と自動 checkout の衝突を防ぐ。並列とディスクは Runner TCO を参照。Windows 主力の全体像は Windows + クラウド Mac——Flutter でもローカルに Xcode がない点は同じです。

8)よくある問題:Flutter iOS CI が止まる理由(how/fix)

Google で多い why/how/fix/error 検索に対応——チーム Wiki の入口でもあります。

pod install が 10 分以上かかるのは正常?

Why: Runner が毎回一時ディレクトリに checkout し、CocoaPods ダウンロードキャッシュがマウントされていない。または pod install --repo-update がデフォルトスクリプトに入っている。
Fix: WORK パスを固定。Podfile.lock の hash を比較し、不変ならスキップ。--repo-update は週次メンテ job に移す。

xcodebuild archive 失敗/exit code 65

Why: Flutter と Xcode の版不一致、DerivedData 破損、native plugin が現 SDK 非対応。
Fix: CI 冒頭で fvm flutter doctor -v をログ保存。DerivedData 削除後再実行。Xcode Release Notes でチャネル確認。

signing failed/プロビジョニング不一致

Why: キーチェーンに p12 未インポート、bundle id とプロファイル不一致、Match リポ権限期限切れ。
Fix: Mac mini Runner 専用キーチェーン。Fastlane Match 更新。必要なら VNC で「常に信頼」——Flutter iOS CI で最頻の「コード以外」失敗。

DerivedData 肥大でディスク満杯

Why: 複数ブランチの並列 job、古い Archives 未削除、複数 Flutter 版共存。
Fix: cron で ~/Library/Developer/Xcode/Archives 清理。Runner 並列 1–2。ディスク ≥512GB または定期拡張。

Flutter 版不一致による plugin コンパイルエラー

Why: 開発者が fvm 未使用、CI が別チャネル。
Fix: .fvmrc をコミット。CI は fvm install && fvm flutter pub get 統一。PR テンプレに「Flutter SDK 変更」チェックを追加。

9)専用 Mac mini で Flutter iOS CI を始めるタイミング

状況同僚 Mac 借用/中古購入クラウド M4 Mac mini
月 4 回以上 iOS リリース調整コスト大推奨 固定ビルド機 + キャッシュ
チームに Mac なし、Flutter のみ継続困難日額で試行 本番 build ipa
オフィスに Mac mini を 24/7 設置済み自前で十分クラウド Mac は DR またはピーク
多数の iOS plugin でネイティブ調整手元 Mac が便利クラウドで release、手元で debug

10)FAQ(Flutter iOS CI/CD)

Flutter iOS CI とネイティブ iOS CI の違いは?
flutter pub get と plugin コード生成が 1 層増え、版は .fvmrc と一致必須。Xcode 側は Pods + archive のまま。

Codemagic/ホステッド macOS との比較は?
ホステッドは検証向き。2 回目ビルドを 10 分以内 に安定させ、強キャッシュが必要なら Flutter iOS build on Mac mini + self-hosted Runner の方が制御しやすい。

初回 Flutter iOS CI 通過までの目安は?
慣れていれば約 1 営業日:Xcode/Flutter 導入、Runner 登録、署名設定、build ipa → TestFlight まで 1 本。

エンジニアリング結論:Flutter iOS CI 最小構成(MVF)

Flutter プロジェクトで週 1 回以上 iOS を出す、かつ Windows/Linux 主力がいるなら、現実的な最小構成は次のとおりです:

  1. 16GB Mac mini M4 を 1 台(物理または専用クラウド)で Flutter iOS CI 専任;
  2. self-hosted macOS Runner を登録し、Linux 側 flutter testbuild apk と workflow 分離;
  3. .pub-cache、CocoaPods cache、DerivedData の 3 層を永続化;
  4. 目標:48 時間以内に本番リポで最初の flutter build ipa → TestFlight。その後、並列・DR 用 2 台目を検討。

当方は同じ MVF で 2 回目ビルドを 4–8 分 帯に圧縮(第 5 節の表参照)。専用 Mac mini ノードと SSH 納品は 料金ヘルプセンター でリリース頻度に照らして試算——まず pipeline を検証し、拡張はその後。