😎

【Flutter】 Pub workspacesを使ったMonorepoプロジェクトをXcode Cloudに上げた時に出たエラー対処方法

2025/01/08に公開

はじめに

Flutter 3.27.0 から Pub workspaces がリリースされたので、早速使ってみました。
プロジェクトを Xcode Cloud 上でビルドし、TestFlight にデプロイする際にいろいろと詰まったところがあったので、遭遇したエラーとその解決方法をまとめます。

準備:Pub workspaces導入

https://dart.dev/tools/pub/workspaces

この機能により、これまで melos に頼っていた Monorepo プロジェクトの構築が、ツールなしで簡単にできるようになりました 🎉

そこで、すでに melos を使っていた手元のプロジェクトにさっそく適用してみました。
導入・入れ替えに必要な手順は上記のページに書かれている通りに進めれば、比較的簡単に行えます。

melos を除外した結果、プロジェクト構成は以下のようになりました。

├── app/
│   ├── android/
│   ├── ios/
│   ├── lib/
│   │   └── main.dart
│   ├── web/
│   └── pubspec.yaml
│
├── packages/
│   ├── core/
│   │   ├── constants/
│   │   │   └── pubspec.yaml
│   │   ├── entities/
│   │   │   └── pubspec.yaml
│   │   ├── .../
│   │   ...
│   │
│   ├── features/
│   │   ├── feature1/
│   │   │   └── pubspec.yaml
│   │   ├── feature2/
│   │   │   └── pubspec.yaml
│   │   ├── .../
│   │   ...
│   ...
│
├── analysis_options.yaml
├── pubspec.lock
├── pubspec.yaml
└── README.md

今回はこのプロジェクトを Xcode Cloud に上げ、TestFlight 経由で手元の iPhone で動作確認をしたいので、次は Xcode Cloud 上での対応についてお話しします。

Xcode Cloudにあげてみる

https://docs.flutter.dev/deployment/cd#xcode-cloud

👆ここにある Xcode Cloud の設定例をコピーして試してみます。

ci_post_clone.sh
#!/bin/sh

# Fail this script if any subcommand fails.
set -e

# The default execution directory of this script is the ci_scripts directory.
cd $CI_PRIMARY_REPOSITORY_PATH # change working directory to the root of your cloned repo.

# Install Flutter using git.
git clone https://github.com/flutter/flutter.git --depth 1 -b stable $HOME/flutter
export PATH="$PATH:$HOME/flutter/bin"

# Install Flutter artifacts for iOS (--ios), or macOS (--macos) platforms.
flutter precache --ios

# Install Flutter dependencies.
flutter pub get

# Install CocoaPods using Homebrew.
HOMEBREW_NO_AUTO_UPDATE=1 # disable homebrew's automatic updates.
brew install cocoapods

# Install CocoaPods dependencies.
cd ios && pod install # run `pod install` in the `ios` directory.

exit 0

デフォルトのプロジェクト構成であれば、このままでもビルドが成功するはずです。
ですが、Monorepo 構成にしたことで、いろいろと問題が出てきました。ここからは、それらのトラブルシューティングを記します。

パスが合ってないエラー 🫥

失敗したログを見ると、ci_post_clone.sh が見つからなかった様です。

今回の構成ではiosフォルダはルートからappフォルダ配下に移動しているので、デフォルトのまま(ルートにiosフォルダがある構成)だと使えないのは当然ですね😅

# Install Flutter dependencies.
flutter pub get

cd app  👈 HERE!

# Install CocoaPods using Homebrew.
HOMEBREW_NO_AUTO_UPDATE=1 # disable homebrew's automatic updates.
brew install cocoapods

build_runnerが走ってない 🧍🏻

プロジェクトの構造上、ビルド前に build_runner を実行しないといけないことをすっかり忘れており、自動生成ファイルが軒並み not found に...
今まではmelos script経由でbuild_runnerを実行していたので、melosに頼らずに実行する必要がありました。

cd packages/core/constants  << build_runnerを実行したいパッケージのpubspec.yamlのあるフォルダに移動

dart run build_runner build -d  << build_runnerを実行

cd ../../../app  << iosフォルダがあるフォルダまで戻る

Generated.xcconfigが無い ❓

Flutter の iOS プロジェクトでは、CocoaPods を使って外部ライブラリの管理をしているようです。

iOS のパッケージ管理は CocoaPods から Apple 純正の SwiftPM にトレンドが移って久しいので、久々に CocoaPods を扱うと戸惑いますね 😅

[!] Invalid `Podfile` file: /Volumes/workspace/repository/app/ios/Flutter/Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first.

このログによれば、Generated.xcconfig というファイルが見つからないとのこと。名前からして自動生成されるファイルっぽいので、どこかでファイル生成をトリガーしているはずです。

いろいろ調べたところ、下記ドキュメントによると原因はシンプルでした。

https://docs.agora.io/en/help/integration-issues/flutter_pod

要は、pod install を実行する前にiosフォルダの親フォルダで flutter pub get を実行する必要があるとのことでした。

実際、ローカルでも同じディレクトリ構造下で試してみると、flutter pub get を実行後に Generated.xcconfig が生成されるのを確認できました。

cd ../../../app  << iosフォルダがあるフォルダまで戻る

# prepare for cocoapods install
flutter pub get  << HERE!!

# Install CocoaPods using Homebrew.
HOMEBREW_NO_AUTO_UPDATE=1 # disable homebrew's automatic updates.
brew install cocoapods

# Install CocoaPods dependencies.
cd ios && pod install # run `pod install` in the `ios` directory.

結果

最終的に、ci_post_clone.sh は以下のようになりました。

ci_post_clone.sh
#!/bin/sh

set -e

cd $CI_PRIMARY_REPOSITORY_PATH # change working directory to the root of your cloned repo.

git clone https://github.com/flutter/flutter.git --depth 1 -b stable $HOME/flutter
export PATH="$PATH:$HOME/flutter/bin"

flutter precache --ios
flutter pub get

cd packages/core/constants

dart run build_runner build -dv

cd ../../../app

flutter pub get

HOMEBREW_NO_AUTO_UPDATE=1
brew install cocoapods

cd ios && pod install
exit 0

CI で発生するエラーは、よくログを見て原因を特定することが大事だと改めて痛感しました。
リリースされたばかりなので情報が少なく、まだまだつまづくことも多いですが、melos にロックインされなくても Monorepo プロジェクトを管理できるようになったのはとても大きな進歩ですね。

Discussion