🛠️
[Flutter] Xcode Cloudを使って配布を自動化したときのメモ
自分が何ヶ月後かに同じ作業をすることになった場合のためのメモです。
Xcode Cloudを設定する
- 接続をXcodeから行う必要がある
Integrate > Create Wolkflow...
- 接続するアプリを選択し、GitHubとも接続する。そのため、当然だけどAppStoreConnectにアプリを作っておく必要がある。
- 1回Xcodeから接続が完了すれば、あとは基本的にAppStoreConnectの該当アプリページにある
Xcode Cloud
からワークフローの編集が可能。
Custom Build Scriptsの作成
- flutterアプリのため、ビルド前に実行させたい処理も多いためCustom Build Scirptsを設定します。
-
ios
フォルダ以下にci_scripts
フォルダを作成し、その下にシェルスクリプトを配置します。ios/ci_scripts/*
- Writing custom build scripts
- 以下の3種類のファイルを認識します。
- ci_post_clone.sh
- Xcode Cloud が Git リポジトリをクローンした後に実行される。
- 追加のツールをインストールしたり、プロパティにエントリを追加したり。
- ci_pre_xcodebuild.sh
- Xcode Cloud がxcodebuildを実行する前に実行される
- 追加の依存関係をコンパイルしたり。
- ci_post_xcodebuild.sh
- Xcode Cloud がxcodebuildを実行した後に実行される。
- 成果物をストレージや他のサービスにアップロードする処理などに使う
- ci_post_clone.sh
ci_post_clone.sh
- まだfvmのバージョンが2系だからfvm_config参照してるけど参考サイトに貼ってる記事の方なら
.fvmrc
使われてるのでそっち参考にしたほうがいいかもね。 - flutter buildをflavorで環境切り分けてるので、Xcode CloudのWolkflowから環境変数として
buildFlavor
を追加して共通の記述から処理が分岐するようにしています。
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.
# Extract the Flutter version from fvm_config file
FLUTTER_VERSION=$(cat .fvm/fvm_config.json | grep "flutterSdkVersion" | cut -d '"' -f 4)
# Clone the Flutter repository with the specified version
git clone https://github.com/flutter/flutter.git --depth 1 -b $FLUTTER_VERSION $HOME/flutter
export PATH="$PATH:$HOME/flutter/bin"
# Print the Flutter version
flutter --version
# 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.
# The flutterfire command is used in Xcode Build Phases and must be installed in advance.
dart pub global activate flutterfire_cli
export PATH="$PATH":"$HOME/.pub-cache/bin"
flutter build ios --config-only --flavor ${buildFlavor} --dart-define=FLAVOR="${buildFlavor}"
exit 0
ci_post_xcodebuild.sh
- xcodebuildの完了後にipaをFirebase Distributionにアップロードします。
- 現状、Xcode Cloudにはビルドしてアーカイブするワークフローしかないので場合分けをしていないが、test実行などを追加する場合は
$CI_WORKFLOW
などを利用してif
分岐すること - Environment variable reference
ci_post_xcodebuild.sh
brew install firebase-cli
firebase appdistribution:distribute "$CI_AD_HOC_SIGNED_APP_PATH/${ipaName}.ipa" --app "${firebaseAppId}" --token "${FIREBASE_TOKEN}" --groups "${firebaseGroup}"
クリーンビルド
- TestFlightで配布する場合は必須でチェックが入る
環境変数の追加
- firebaseAppId
- Firebaseの管理画面から設定にあるAppleアプリを選択
-
アプリ ID
欄にあるIDを指定
- firebaseGroup
- Firebase Distributionで配布する
テスターグループ
を指定する。 -
テスターとグループ
欄から配布先に指定したいグループを選択すると、「テスターを検索」欄の右上あたりにヘルプマークでコマンドライン ツールでグループを指定する際に、このエイリアスを使用します。
と設定されてる文字列があると思うのでそれをコピー。
- Firebase Distributionで配布する
- FIREBASE_TOKEN
- 以下で取得できるtokenを指定。
- そのうちGCPのサービスアカウントに変更が必要かも・・・。
firebase login:ci
- ipaName
- アプリ名として自分が指定している名前でipaが作られるはず。
- よくわからなければ、1回Xcode Cloudを実行したあとで成果物に登録されるipaをダウンロードして確認
開始条件
- デフォルトだと全てのブランチがpushされるたびに実行される設定になっているため、必ず変更する
- 現在の環境では以下を設定している。dev版の場合はproductionではなくdevelopment
-
ブランチの変更
としてupload-production/
で始まるブランチが変更された場合 -
タグの変更
としてproduction
で始まるタグ
-
アクション
- アーカイブ - iOS
- 本番の場合は本番向けのスキームを指定
- 配信準備は「App Store Connect」にするとTestFlight向けの準備もされる。
- dev版でTestFlightへの配信も必要ない場合は「なし」で大丈夫。
ポストアクション
- TestFlight内部テスト - iOS
- アクションの配信準備でTestFlightまたはAppStoreConnectを選択していないと実行できない
- これを指定しないと、自動的にTestFlightビルドは配布されない。
- 通知する - 成功と失敗
- Slack通知を設定しておくと便利
その他
- ローカルで古い環境を使っていたりすると、新しいXcodeバージョン要因のエラーが出ることがある。
- 例えばxcode 16 beta3 - ambiguous use of 'evaluateJavaScript(:completionHandler:)' build error
- これに関しては明示的にurl_launcher_iosの最新バージョンをインストールするように記述すると直る。
pubspec.yaml
dependency_overrides:
url_launcher_ios: 6.3.1
- カスタムビルドスクリプトに
chmod +x &ci_post_clone.sh
などの形で実行権限を付与する
Discussion