Flutter + GitHub Actions + Firebase App Distributionで自動リリースサイクルを作る（Android編）


Flutterアプリ開発を進めるにあたり、masterにマージしたら、誰でもアプリが実機にインストールできるフローを作りたい。


たまにしかやらなくて忘れそうなので備忘。

## やりたいこと
1. ローカルでもCIでもリリースビルドを作れるようにする
2. GitHubに署名ファイルはあげない
3. 自動でバージョンをインクリメントして、Firebase App Distributionにuploadする


## ローカルでリリースビルド作れるようにする
*[オフィシャルドキュメントのこの辺](https://flutter.dev/docs/deployment/android#signing-the-app)にも書いてある。*

### 1. （無ければ）keystoreファイル作る

サンプルはたくさん転がってるので割愛。
git管理からは外しておく。

### 2. ローカルでのビルド用に`key.properties`作る

```
storePassword=<password from previous step>
keyPassword=<password from previous step>
keyAlias=key
storeFile=<location of the key store file, such as /Users/<user name>/key.jks>
```
これもgit管理からは外しておく。

### 3. アプリの`build.gradle`に下記を追加。

```
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
    // For Local
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
} else {
    // For CI
    keystoreProperties.setProperty('storePassword', System.getenv('KEY_STORE_PASSWORD'))
    keystoreProperties.setProperty('keyPassword', System.getenv('KEY_PASSWORD'))
    keystoreProperties.setProperty('keyAlias', System.getenv('ALIAS'))
    keystoreProperties.setProperty('storeFile', System.getenv('KEY_PATH'))
}
```

`android`ブロックに下記を追加（＆書換え）

```
    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }

```

### 4. 確認
とりあえずAPK作ってみる
`flutter build apk --release`

## GitHub Actionsでリリースビルド作れるようにする
参照：[Signing Flutter Android apps for release in GitHub Actions](https://dev.to/cddelta/signing-flutter-android-apps-for-release-in-github-actions-2892)

### 1. （無ければ）workflow作る
サンプルはたくさん転がってるので割愛。

### 2. GitHub Secretsにもろもろ入れとく
`key.properties`の代わり。
この後、これをGitHub Actionsで読み取る。
<img width="1341" alt="スクリーンショット 2020-08-10 14.16.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13189/089a9287-a298-96cc-a6da-8926d7e2eb2f.png">

- `ANDROID_KEY_STORE_PASSWORD` :point_right: storePassword
- `ANDROID_KEY_PASSWORD` :point_right: keyPassword
- `ANDROID_KEY_ALIAS` :point_right: keyAlias
- `ANDROID_KEY_JKS` :point_right: keystoreファイルをbase64エンコードしたもの。
`openssl base64 -A -in key.jks`


*使わなかったけど、こんなactionもあったりする。
https://github.com/marketplace/actions/sign-android-release*

### 3. workflowにリリースビルドを作るステップを追加
前のステップでGitHub Secretsに保存した値を環境変数に保存。

```
      - name: set up private files
        run: |
          echo $SIGNING_KEY | base64 -di > android/app/key.jks
        env:
          SIGNING_KEY: ${{ secrets.ANDROID_KEY_JKS }}

      - name: build release apk
        run: |
          flutter build apk --release --build-name=0.0.$GITHUB_RUN_NUMBER --build-number=$GITHUB_RUN_NUMBER
        env:
          KEY_STORE_PASSWORD: ${{ secrets.ANDROID_KEY_STORE_PASSWORD }}
          KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
          ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
          KEY_PATH: key.jks

```

- keystoreを復元してるところは、`i`オプションつけないと自分の環境ではこけた。
- `android/app`の`build.gradle`でビルドするので、`android/app/`にファイル置いてる。
- `$GITHUB_RUN_NUMBER`使って、ビルドごとにパッチバージョンとバージョン番号があがるようにする


## Firebase App Distributionへリリース
[既存のGitHub Action](https://github.com/marketplace/actions/firebase-app-distribution)の恩恵にあずかって楽する

（App Distributionのセットアップも忘れずに）

```
      - name: upload artifact to Firebase App Distribution
        uses: wzieba/Firebase-Distribution-Github-Action@v1
        with:
          appId: ${{secrets.FIREBASE_ANDROID_APP_ID}}
          token: ${{secrets.FIREBASE_TOKEN}}
          groups: Developer
          file: build/app/outputs/flutter-apk/app-release.apk

```

## もう一声

- メジャー・マイナーバージョン名は、workflowの外で定義したい
- やっぱり署名も[既存のaction](https://github.com/marketplace/actions/sign-android-release)を使った方が楽かもしれん