FlutterプロジェクトのCI/CD構築にあたって、Bitriseを使用しました。
BitriseはGUI操作だけでなく、YAMLファイルを編集してWorkflowのStepを管理することもできるため、柔軟なCI環境を構築できます。
基本的な設定はドキュメントを見ながらの構築になりますが、Flutterプロジェクトの場合、ある程度工夫しないと求めている挙動を実現できなかったため、工夫した部分をまとめていきます。
実現したワークフロー
test_and_deploy_debug
• コードの静的解析とテスト実行
• debug環境をビルド
• AndroidアプリをビルドしてDeployGateへデプロイ
• iOSはアーカイブしてApp Store Connectにアップロード
test_and_deploy_release
• コードの静的解析とテスト実行
• release環境をビルド
• AndroidアプリをビルドしてDeployGateへデプロイ
• さらにGooglePlayConsoleに.aabファイルをアップロード
• iOSはアーカイブしてApp Store Connectにアップロード
Flutter Test
そのままこのステップを実行すると、ずっとワークフローが終わらない状態になります。
ログの中に
ERR : The current activation of
junitreport
cannot resolve to the same set of dependencies.
とあるのを発見しました。
❗️原因: junitreport = Flutterのテスト結果をJUnit形式のXMLに変換するツールです。
Bitriseでテストカバレッジを出力する際に必要となります。
原因を調査したところ、ビルドマシン上にインストールされている junitreport と、実際に使用しようとしている junitreport の依存関係が一致していないことが分かりました。
そのため、ビルドマシン上で改めて junitreport を正しくインストール・有効化する必要があります。
✅対策:
Flutter Testステップの前にScriptステップを追加する
flutter pub global activate junitreport
Flutter環境に junitreport というツールをグローバルインストールして使えるようにします。
Change Android versionCode and versionName
Bitrise側でversionName, versionCodeを変更したい場合に使用するステップです。ドキュメント通りに設定してもversionCodeが設定した値に反映されません。
❗️原因: Flutterのデフォルトの設定では、versionNameとversionCodeの設定は
versionCode = flutterVersionCode.toInteger()
versionName = flutterVersionName
このように設定されています。
ビルドマシンではこの値を参照することが出来ないため、更新されません。
✅対策:
ビルドマシン上にflutter.versionCodeとflutter.versionNameを作成し、その値を参照するように設計する
Change Android versionCode and versionNameステップの前にScriptステップを追加する。
echo "flutter.versionCode=$BITRISE_BUILD_NUMBER" > "$BITRISE_SOURCE_DIR/android/local.properties"
echo "flutter.versionName=1.0.0" >> "$BITRISE_SOURCE_DIR/android/local.properties"
上記は仮に1.0.0のように固定値を入れています、Env varsで設定した値を入れてもOKです。
Google Play Deploy
見落としやすいですが、ステップのConfiguring the Stepにこのように記載されていました
Please note that in order to successfully use this Step, you must upload your first APK or AAB file manually,
なので、まずは手動でGooglePlayConsoleに.apkファイルまたは.aabファイルをアップロードする必要ありです。
👉json key fileインストールエラーについて
Authenticating
Failed to create HTTP client: failed to create auth config from json key file [REDACTED], error: %!s()
💡やった事
ProjectSettings→FilesにserviceAccount.jsonkeyを保存。そこで生成されるDownloadURLをWorkflow画面のSecretsの変数に設定
Secretes変数をService Account JSON key file pathに設定
このように設定しても上記エラーは解消できませんでした...😂
✅対策: workflowのYamlファイルにFilesで設定されたDownloadURLを指定する
GUI上では設定できませんが(Secrets変数しか設定できない)、yamlファイルで指定してビルドを実行したところ、エラー回避できました🎉
👉 keystoreの設定時のエラーについて
ドキュメント通りに設定し、ビルドを実行すると、
A failure occurred while executingcom.android.build.gradle.tasks.PackageAndroidArtifact$IncrementalSplitterRunnable
SigningConfig "release" is missing required property "storeFile".
というエラーになります。
❗️原因: 公式通りにAndroidの署名設定を行うと、keystoreとkey.propertiesを連携させて署名を実現している構成になります。
通常、これらのファイルはセキュリティ上gitignoreでリポジトリ上に存在しないため、ビルドマシン上にkey.propertiesとkeysotreを作成し、ローカル上のFlutterプロジェクトと構成を合わせる必要があります。
✅対策: Flutter Buildステップ以前にSciriptステップとFile Downloderステップを使用し、ローカル環境と同じ構成にする。
echo "storeFile=./upload.jks" > android/key.properties
echo "storePassword=$BITRISEIO_ANDROID_KEYSTORE_PASSWORD" >> android/key.properties
echo "keyPassword=$BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD" >> android/key.properties
echo "keyAlias=$BITRISEIO_ANDROID_KEYSTORE_ALIAS" >> android/key.properties
まずこのスクリプトでビルドマシン上にkey.propertiesを作成します。
そして、FileDownloaderで
Download source URLに$BITRISEIO_ANDROID_KEYSTORE_URLを設定し、
Download destination pathにandroid/app/upload.jksを設定すればOKです
まとめ
ビルド → エラー → 対策の繰り返しでしたが、最終的にやりたかった挙動を実現できたのは非常に良い経験となりました。
Bitriseでは、このビルドをトリガーによって柔軟に起動させる設定も可能です。
そのため、一度ワークフローをしっかり構築しておけば、アプリ運用が長期化すればするほど、作業者の負担はどんどん減っていくことになります。
これは非常にありがたい仕組みだと感じました🎉
ただ、Bitriseのドキュメントは情報量がとても多く、日本語ページも用意されてはいるのですが、
翻訳の精度が低く、内容の理解が難しいと感じました。
結局、英語のページを参照しながら、自力で翻訳しつつ作業を進める必要があり、大変でした。