okaryo.log

Flutterで作ったAndroidアプリをGitHubActionsを使ってGooglePlayに自動デプロイする | okaryo.log

Flutterで作ったAndroidアプリをGitHubActionsを使ってGooglePlayに自動デプロイする

    #Flutter#Android#GitHubActions#GitHub#CI/CD

はじめに

最近subskunというAndroidアプリをリリースした。

最初のリリースの際はローカルでビルドして手動でストアにアップロードしたが、毎回それをしていては流石に面倒なので自動化したいと考えた。

そこで、GitHubActionsを使ってワークフローを組んでみることにした。

組んだワークフロー

ワークフローの全体は以下となった。リリース用のブランチであるmainブランチにマージがあったタイミングでワークフローが実行されるようにしている。

name: Deploy to Google Play

on:
  push:
    branches:
      - main

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: Create service_account.json
        run: echo '${{ secrets.ANDROID_SERVICE_ACCOUNT_JSON }}' > service_account.json
      - name: Upload artifact to Google Play
        uses: r0adkll/upload-google-play@v1
        with:
          serviceAccountJson: service_account.json
          packageName: ${{ secrets.PACKAGE_NAME }}
          releaseFiles: build/app/outputs/bundle/productionRelease/app-production-release.aab
          track: production
          status: completed

各ステップを解説

aabのビルドステップまでは以下の記事で紹介したワークフローと同じものを使っているので、すでにご存知の方はCreate service_account.jsonまで飛ばしていただいて構わない。

Flutterで作ったAndroidアプリをGitHubActionsを使ってAppDistributionに自動デプロイする

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.gradlesigningConfigsはこうなっている。

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でビルドする際にコミット数をビルド番号として設定する

追記おわり

Create service_account.json

ストアへAPI経由でアップロードするためにサービスアカウントというのが必要になるので、そのためのファイルを作成している。

echo '${{ secrets.ANDROID_SERVICE_ACCOUNT_JSON }}' > service_account.json

サービスアカウント自体の作成については以下の記事を参考にさせていただいた。

Google Play Store向けサービスアカウントの作り方

Upload artifact to Google Play

準備が整ったのでいよいよGooglePlayにビルドをアップロードする。

ここでは0adkll/upload-google-play@v1というActionを利用させていただいた。

- name: Upload artifact to Google Play
  uses: r0adkll/upload-google-play@v1
  with:
    serviceAccountJson: service_account.json
    packageName: ${{ secrets.PACKAGE_NAME }}
    releaseFiles: build/app/outputs/bundle/productionRelease/app-production-release.aab
    track: production
    status: completed

アプリのアップデート優先度やストアに公開する際のユーザーへの公開率、リリースノートなども設定することができる。もっと詳しく知りたい方はREADMEを参考にしていただきたい。

おわり

これでmainブランチへのマージをトリガーにしてPlayStoreへのデプロイを自動化することができた。

ここで自分の失敗談だが、ワークフローのデバッグ中にワークフローが成功してしまい、意図せずPlayStoreへアプリが審査に出されてしまった。アプリ自体に更新があったし近々審査に出そうと思っていたのでそのまま審査に出すことにしたが、意図せず審査に出したとしてもそれを削除することができずに困ってしまった。みなさんも注意していただきたい。


関連記事
最新記事
プロモーション

This site uses Google Analytics.