Flutterで作ったAndroidアプリをGitHubActionsを使ってAppDistributionに自動デプロイする
はじめに
最近subskunというAndroidアプリをリリースした。
機能の追加や修正時に実機でデバッグをするのにAppDistributionを使っているが、これをdevelop
ブランチにマージがあったタイミングで自動でAppDistributionに配信したいと考えた。
そこで、GitHubActionsを使ってワークフローを組んでみることにした。
組んだワークフロー
ワークフローの全体は以下となった。開発用のブランチであるdevelop
ブランチへのpushをトリガーにワークフローが走るようにしている。
name: Deploy to App Distribution
on:
push:
branches:
- develop
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.0.1'
channel: 'stable'
cache: true
- name: Run gen-l10n
run: flutter gen-l10n
- name: Build aab
run: |
echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > android/app/google-services.json
echo '${{ secrets.ANDROID_JKS_BASE64 }}' | base64 -d > android/app/release.keystore
export KEY_ALIAS='${{ secrets.KEY_ALIAS }}'
export KEY_PASSWORD='${{ secrets.KEY_PASSWORD }}'
export KEYSTORE_PASSWORD='${{ secrets.KEYSTORE_PASSWORD }}'
flutter build appbundle --release --flavor production --dart-define=FLAVOR=production --build-number='${{ secrets.ANDROID_BUILD_NUMBER }}' --obfuscate --split-debug-info=obfuscate/android
- name: Upload artifact to Firebase App Distribution
uses: wzieba/Firebase-Distribution-Github-Action@v1
with:
appId: ${{secrets.FIREBASE_APP_ID}}
token: ${{secrets.FIREBASE_TOKEN}}
groups: testers
file: build/app/outputs/bundle/productionRelease/app-production-release.aab
各ステップを解説
actions/checkout@v3
レポジトリをチェックアウトしているだけなので割愛。
Set up Flutter
Flutter
の環境構築をしている。subosito/flutter-action
はそのためによく使われるActionだ。
ちなみにsubskunではFlutter3を使っている。
Run gen-l10n
subskunでは多言語対応しているので、以下のコマンドを走らせることでLocalization用のコードをビルドの前に生成しておく必要がある。
flutter gen-l10n
Build aab
ここでやっとビルドを走らせるが、まずはその下準備をする。
subskunではFirebaseを使っているので設定ファイルをGitHub ActionsのSecretsから生成している。
mkdir android/app/src/productionRelease
echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > android/app/src/productionRelease/google-services.json
以下ではAndroidアプリを署名するためのパスワードなどの準備をしている。jksファイルはバイナリなので、base64したものをGitHub ActionsのSecretsに設定し、ここでデコードしている。
echo '${{ secrets.ANDROID_JKS_BASE64 }}' | base64 -d > android/app/release.keystore
export KEY_ALIAS='${{ secrets.KEY_ALIAS }}'
export KEY_PASSWORD='${{ secrets.KEY_PASSWORD }}'
export KEYSTORE_PASSWORD='${{ secrets.KEYSTORE_PASSWORD }}'
ちなみに上記からも分かる通り、パスワードなどは環境変数から読み取る形式にしているのでandroid/app/build.gradle
のsigningConfigs
はこうなっている。
signingConfigs {
release {
keyAlias System.getenv('KEY_ALIAS')
keyPassword System.getenv('KEY_PASSWORD')
storeFile file('release.keystore')
storePassword System.getenv('KEYSTORE_PASSWORD')
}
}
次にやっとビルドだ。
実際にリリースされるものと同じ環境で動作確認したいのでもちろんリリースビルド。dart-define
を使って環境の出し分けをおこない、--obfuscate
ではコードの難読化をおこなっている。
ビルド番号もSecretsから与えるようにしているが、アプリのバージョン番号から自動でビルド番号を読み取る方式にしようかどうか考え中。個人的にはiOSも含めてビルド番号はコードに依存させずに外部から与えるようにしたいと思っているが、もっと手軽にできるのであればそうしたいとも思っている。
flutter build appbundle --release --flavor production --dart-define=FLAVOR=production --build-number='${{ secrets.ANDROID_BUILD_NUMBER }}' --obfuscate --split-debug-info=obfuscate/android
2022-10-05追記
ビルド番号についてだが、コミット数から設定する方法を教えていただいた。以下の記事で紹介しているのでよければ読んでいただきたい。
FlutterアプリをGitHubActionsでビルドする際にコミット数をビルド番号として設定する
追記おわり
Upload artifact to Firebase App Distribution
最後にAppDistributionへのアップロードだ。
先ほどのビルドによってaabファイルが以下のパスへ生成された。これをアップロードする。
build/app/outputs/bundle/productionRelease/app-production-release.aab
それにはwzieba/Firebase-Distribution-Github-Action@v1
というActionを利用させてもらった。
FirebaseのappId
とtoken
(またはserviceCredentialsFile
)を与えてやるだけで簡単にアップロードすることができる。
ちなみにappId
はFirebaseのプロジェクトIDではなく、Firebaseプロジェクト内のAndroidアプリのIDなので注意。また、token
はfirebase login:ci
コマンドで取得することができる。
firebase
コマンドを使うにはFirebase CLIをインストールする必要がある。詳しくは公式ドキュメントを参照されたい。
おわり
AppDistributionへのアップロードは作成済みのActionを使うことができたので簡単に実現することができた。
個人開発においてはめんどくさい
をどれだけ少なくできるかがモチベーションを維持する上でも重要だと思っており、こういったCI/CDの構築は早めにやっておきたかったので大変助かった。