8
4

More than 1 year has passed since last update.

【Flutter-Android】【GithubActions】flutterのCD環境を整備してみた

Posted at

はじめに

普段仕事ではiOSアプリを開発していますが、
昨年5月頃からFlutterに興味を持ち始め、趣味の時間でFlutterアプリの勉強を始めました。
アプリの配信は毎回手間に感じていて自動化できないか?と調査をしていた内容を共有します。

今回はAndroid編です。iOS編はこちら

目標

Githubにコードがpushされたときに、AndroidアプリをStoreにビルド配信する。

Storeにビルド配信する。

では作業を開始します。

最終的なフォルダ構成

.
├── .github
│   └── workflows
│       ├── cd_aos.yml・・・・Android用githubActionsの設定ファイル
├── android
│   └── fastlane
│       ├── Appfile・・・・Store関係の設定が書かれたファイル
│       └── Fastfile・・・・fastlaneの設定ファイル
└── 以下省略

注意!!~今回説明しないもの~

申し訳ないのですが、今回は以下の環境設定方法については省略します。
- GooglePlayStore(deveploper)の登録や設定方法
- Githubの登録や設定方法
- GithubActionsの知識

作業の流れ

  1. fastlaneを用意する
  2. Storeに配信するための設定
  3. Fastfileを設定する
  4. github actionsを準備
  5. あとはコミット!!

1. fastlaneを用意する

※作業ディレクトリは、/android/ で実施します。
今回は署名の管理や面倒なビルドコマンドの省略のためにfastlaneを使用しました。
(xcodebuildやgradleなどのコマンド、flutterのコマンドからでもビルドが作成できれば、それでも良いと思います)

fastlaneには多くの便利な"アクション"が定義されています。アプリのビルドであったり、配信であったり、単体テストなども、fastlaneに定義されているアクションを利用可能です。

1-1. fastlaneを準備する

fastlaneは、iOSアプリ開発 及び Androidアプリ開発をサポートするツールです。
https://docs.fastlane.tools/

fastlaneの導入は以下のコマンドより実行します。

xcode-select --install
sudo gem install fastlane -NV
fastlane init

fastlane/にファイルが作成されたでしょうか?
作成されたAppfileやFastfileに設定を書き加えていきます。

2. Storeに配信するための設定

いよいよfastlaneを使って、ビルドから配信を行うまでの設定を行います、fastlaneの細かな設定はFastfileで行います。
と、、その前に更にいくつかの設定を行います。Storeに配信するための設定です。

2-1. fastlane supplyの準備

Android側では、fastlane supplyを使ってAndroidのStore配信を行います。

その準備として、iOSと同じようにStoreアップロード用にAPIなどを用意します。

iOSと比べて、こちらは少し面倒です。。。

2-1-1. 認証用のjsonファイルを作成

Google Play Consoleを開いて、メニューから「アカウントの詳細」を開いて「ディベロッパーアカウントID」をメモしておきます
image.png

次に、メニューから「設定」→「APIアクセス」を開きます。
image.png

「リンクするプロジェクトを選択」を押下すると、次のような画面となります。
image.png
image.png

そこで「新しいサービスアカウントを作成」を押下します。ダイアログが開くため指示に従っていきます。
image.png

GCPを開きます。メニューから「サービスアカウント」を開きます。アカウントがない場合は次の画像のような画面が開きます。そこで「+サービスアカウントを作成」を選びます。

image.png

サービスアカウントの作成では以下のような画面になります。サービスアカウント名を入力します。その後に「@...」の部分に、手順2でメモした「ディベロッパーアカウントID」があることを確認して下さい。また、「.iam.gserviceaccount.com」があることも確認して下さい。問題なければ「作成して続行」を押下します。

image.png

次のステップではアカウントにロールを設定します。ここでは「サービスアカウントユーザー」を設定します。

image.png

次のステップは特に何もせずに完了とします。
GCPの画面では下記のような状態になります。

image.png

キーがないため、キーを作成します。3点リーダーでメニューを開き、「鍵を管理」を選びます。

image.png

次の画面にて「新しい鍵を作成」します。

image.png

JSONを選択していることを確認して、鍵を作成します。

image.png

image.png

元の画面(GooglePlayConsole)に戻ります。元表示されていたダイアログを閉じる、再リロードすると作成したサービスアカウントの情報が反映されます。 

image.png

ここでアクセス権を設定します。fastlaneのドキュメント上ではAdminが推奨されていますが、リリース関係のみ許可をして「ユーザーを招待」します。

image.png

ここまででjsonファイルの作成は完了です。

2-1-2. 作成したjsonファイルの確認

まずは下記のコマンドで動きを確認します。

fastlane run validate_play_store_json_key json_key:/path/to/your/downloaded/file.json

下記の結果が得られれば成功です。

[21:08:37]: ------------------------------------------
[21:08:37]: --- Step: validate_play_store_json_key ---
[21:08:37]: ------------------------------------------
+----------+--------------------------------------+
|    Summary for validate_play_store_json_key     |
+----------+--------------------------------------+
| json_key | /Users/hogetaro/Desktop/pc-api-4XXXX  |
|          | 4YYYYYYYYYYYYYYYYYYYYYYYYYYYYY.json  |
| timeout  | 300                                  |
+----------+--------------------------------------+
[21:08:37]: Successfully established connection to Google Play Store.

2-1-3. AppFileを設定

今作成したjsonファイルなどをAppfile内に設定します。

json_key_file("path/to/your/play-store-credentials.json") package_name("my.package.name")

記載を終えたら、

fastlane supply init

これでsupplyの準備は完了です。

3. Fastfileを設定する

fastlaneでは、Fastfileに自動化タスクを「レーン」として定義することで、1コマンド(fastlane {レーン名})でタスクが実行できるようになります。

3-1. 署名済みaabファイルをfastlaneで作成

まずはローカル環境で署名済みaabファイルをfastlaneで作成してみましょう。

default_platform(:android)
platform :android do

desc "Deploy a new version to the Google Play"
  lane :deploy do
    gradle(
      task: "clean bundle",    
      build_type: "Release",    
      print_command: false,    
      properties: {    
        "android.injected.signing.store.file" => "{ビルドマシン内のjksファイルのパス}",
        "android.injected.signing.store.password" => "{KeyStoreのパスワード}",        
        "android.injected.signing.key.alias" => "{keyエイリアス}",
        "android.injected.signing.key.password" => "{keyエイリアスのパスワード}",
      }
    )
  end
end

上記は、laneにdeployを定義しました。
署名つきのaabファイルを作成するfastlaneのアクションを探したところ「gradle」が使えそうなので、
「gradle」というアクションを使っています。

propertiesの設定は、ビルド時の署名情報です。リリース時に設定している内容を使います。

こちらをFastflieに記述したら、動かしてみます。

fastlane deploy

これで以下のフォルダに作成されていればOKです。

/build/app/outputs/bundle/release/app-release.aab 

ログは以下のような感じです。

[20:19:34]: ▸ BUILD SUCCESSFUL in 53s
[20:19:34]: ▸ 154 actionable tasks: 133 executed, 21 up-to-date
[20:19:34]: Couldn't find any new signed apk files...
+------+---------------------+-------------+
| fastlane summary |
+------+---------------------+-------------+
| Step | Action | Time (in s) |
+------+---------------------+-------------+
| 1 | default_platform | 0 |
| 2 | clean bundleRelease | 53 |
+------+---------------------+-------------+
[20:19:34]: fastlane.tools finished successfully 🎉

3-2. ローカルで作成した署名済みaabファイルをアップロードする

3-1で作成したFastfileに以下の処理を追加します。

    upload_to_play_store(
      aab: "../build/app/outputs/bundle/release/app-release.aab",
      skip_upload_metadata: true,
      skip_upload_images: true,
      skip_upload_screenshots: true
    )

こちらのactionも、play storeに配信するfastlaneのアクションを探して見つけました。
Fastflieに追記したら、動かしてみます。

fastlane deploy

以下のログを得られたらOKです!

[22:37:49]: Preparing aab at path '../build/app/outputs/bundle/release/app-release.aab' for upload...
[22:38:17]: Updating track 'production'...
[22:38:19]: Preparing to upload for language 'ja-JP'...
[22:38:20]: Updating changelog for '4' and language 'ja-JP'...
[22:38:20]: Uploading all changes to Google Play...
[22:38:23]: Successfully finished the upload to Google Play
+------+----------------------+-------------+
|             fastlane summary              |
+------+----------------------+-------------+
| Step | Action               | Time (in s) |
+------+----------------------+-------------+
| 1    | default_platform     | 0           |
| 2    | clean bundleRelease  | 32          |
| 3    | upload_to_play_store | 39          |
+------+----------------------+-------------+
[22:38:23]: fastlane.tools finished successfully 🎉

4. github actionsを準備

ルートの直下に、以下の構成でファイルを用意します。

.github/workflows/{githubActionsの設定ファイル名}.yml

バイナリの署名の設定を「app/build.gradle」に移動します。
署名のファイルをリポジトリ管理するようにして、以下のような設定を行います。
※iOSのfastlaneのような署名管理方法があれば教えて欲しいです・・・

signingConfigs {
    release {
        storeFile file("../config/KeyStore.jks") //check that the file exists
        storePassword "KeyStorePassword"
        keyAlias "keyAlias"
        keyPassword "keyPassword"
    }
}

buildTypes {
    release {
        signingConfig signingConfigs.release
    }
}

署名関係については、
・supplyの設定で作成したjsonファイル
・リリース用のjksファイル
・署名設定を反映したapp/build.gradleファイル
以上が準備できていればOKと思います。

さて、ようやくですが。。yamlファイルの中身は以下を設定しました。

name: CD_Android

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the master branch
  push:
    branches: [ master ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  aos_distribution:
    runs-on: macos-11
    if: |
      contains(github.event.head_commit.message, '[Release]') == true && contains(github.event.head_commit.message, '[AOS]') == true
    name: Distribution(AOS)
    steps:
    - uses: actions/checkout@v2

    # install fastlane
    - name: Install fastlane
      run: gem install fastlane

    - name: Setup flutter
      uses: subosito/flutter-action@v1
      with:
        flutter-version: '2.5.3'

    - name: Set up tools
      run: |
        flutter pub get
    - name: ExportPath
      run: |
        export PATH=$PATH:${FLUTTER_HOME}/bin/cache/dart-sdk/bin
        export PATH=$PATH:${FLUTTER_HOME}/.pub-cache/bin
    # Build & Deploy
    - name: Run builds(fastlane)
      run: |
        cd android/
        ls
        fastlane deploy
      env:
          JSON_KEY_PATH: ${{ secrets.JSON_KEY_PATH }}

GithubSecrets上に環境変数を定義します。

  • JSON_KEY_PATH:fastlane supplyの設定で作成したJSONファイルへのパス

簡単な説明や補足

flutterのリポジトリのため、コミットメッセージに[Release]と[AOS]がある場合にTestFlightへのアップロードを行うこととしました。

    if: |
      contains(github.event.head_commit.message, '[Release]') == true && contains(github.event.head_commit.message, '[AOS]') == true

gradlewに関する以下のエラーが発生した場合は、gradle関連のファイルをコミットします。

エラー: Couldn't find gradlew at path

gradle関連のファイルがコミットされていなければコミットします。

android/gradle/
android/gradlew

localPropertiesFileに関する以下のエラーが発生した場合も修正します。

エラー: assert localPropertiesFile.exists()

こちらを参考にして修正しました。

Flutter SDKが見つからないエラーがあったため、SDKのセットアップ処理を追加しました。

エラー: Flutter SDK not found.
    - name: Set up tools
      run: |
        flutter pub get

    - name: ExportPath
      run: |
        export PATH=$PATH:${FLUTTER_HOME}/bin/cache/dart-sdk/bin
        export PATH=$PATH:${FLUTTER_HOME}/.pub-cache/bin
    - name: Setup flutter
      uses: subosito/flutter-action@v1
      with:
        flutter-version: '2.5.3'

5. あとはコミット。祈るだけ。

あとはコミットしてみて祈るだけです。

さいごに

お疲れ様でした。
iOS、Androidの二部構成で記事を作成しています。もしよければiOS側の記事もご覧いただけますと幸いです。Flutterの良さは1コードで2OSに配信できることです。CD環境を整備して、そのリリース速度を加速していければと思います。

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4