Android GitHub Actions Hands-on

## 内容
GitHub Actionsを使って、AndroidのCI環境を構築する。最低限のビルド&デプロイができるところまで。

1. masterの更新時とmasterへのPRを作成したブランチに対して、apkをビルド
2. ビルドしたapkを保存できるようにする
3. masterブランチを更新したとき、アプリをFirebase App Distributionで配布する

## 0. 準備
Android Studioで新規にプロジェクトを作成する。
そのプロジェクトをGitHubのリポジトリにpushする。

完成したサンプルはこちら。
https://github.com/KamikazeZirou/android-github-actions-sample

## 1. とりあえずビルドする
(1) GitHubのリポジトリのページを開く
(2) GitHub Actionsを押す
(3) AndroidでSetupする(下図)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/960502f5-7d41-b8de-78ce-82b33b6b34fd.png" width=50%>

Setupを進めると初期設定ファイルが「.github/workflows/android.yml」に生成される。変更できるが、ここでは変更しないで進める。

### Androidビルドの初期設定
(2020/08/20時点。変更不要)

```yaml
name: Android CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: set up JDK 1.8
      uses: actions/setup-java@v1
      with:
        java-version: 1.8
    - name: Build with Gradle
      run: ./gradlew build
```

(4) GitHubリポジトリ上のGitHub Actionsを開いて、ビルドが実行されていることを確認
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/5ca851c4-6ff3-3504-616a-17569a809455.png" width=50%>


## 2. ビルドしたapkを取得できるようにする
(1)  .github/workflows/android.ymlの末尾に以下を追記。

```yaml
    - name: Store test results
      uses: actions/upload-artifact@v2
      with:
        name: reports
        path: ./**/build/outputs/apk
```

(2) ブランチ「chore/store_apk_as_artifact」を作って、変更をコミット&pushする

(3) GitHubからmasterへのPRを作成してビルドを実行させる
PRのページが下図のようになっていれば、GitHub Actionsのビルドが実行されている。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/71acd686-f4cf-74cf-5ceb-48e35300ba44.png" width=50%>

(4) apkがartifactとして保存されていることを確認する
PRのページの「Checks」を選択。GitHub Actionsで実行されたworkflowが確認できる(下図)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/ecfc758b-1ddf-00ec-7c5a-e50e5e1d272c.png)

「Artifacts」を押して、ファイルを解凍すると、以下の2つのapkファイルが取得できる。

- ./app/build/outputs/apk/release/app-release-unsigned.apk
- ./app/build/outputs/apk/debug/app-debug.apk

これをスマホから開くと、ビルドしたアプリがインストールできる。
レビュー時にコードだけでなく、実際の動作を見るときなどに使える。

(5) ここで作ったPRをmasterにマージしておく

## 3. masterブランチが更新されたらFirebase App Distributionに配布する

既成のActionsを利用して実現する。
https://github.com/marketplace/actions/firebase-app-distribution

### 3.1 Firebaseのプロジェクトを作る

(1) Firebase Consoleにアクセスする
https://console.firebase.google.com/u/1/?pli=1

(2) プロジェクトを作る
名前は適当でOK。「hello-github-actions」など。
設定も全部デフォルトでOK。

(3) FirebaseにAndroidアプリを追加する
アプリのパッケージ名には実際のアプリのパッケージ名を入れる。
後はデフォルトでOK。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/1dbe122f-0e19-2f5c-5646-0667791cb800.png" width=50%>

(4)Firebaseの指示に従って、アプリを設定する(省略可だが、設定した方が実戦的)
設定をする場合は、build.gradleを修正することになるのでmasterにpushしておく。
「google-services.json」は、appフォルダ直下に保存しておく。

(5)アプリのIDを確認する
Firebaseのプロジェクト概要
→ プロジェクト設定
→ 全般タブ
→ 下スクロールするとアプリIDが見える(下図)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/fcddc5b8-0400-7734-791d-cde7c7b5eb37.png" width=50%>

後で使うのでアプリIDをメモしておく。

(6) Firebase App Distributionを開始しておく
Firebaseのプロジェクトのトップ
→ 品質のApp Distribution
→ 開始

下図のような画面の状態になったらOK。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/0fa9401e-c862-8952-05b8-01cbd46e8348.png)


### 3.2 Firebaseの認証トークンを取得しておく
こちらを見ながら、認証トークンを取得する。後で使うのでメモしておく。

https://firebase.google.com/docs/cli?hl=ja#cli-ci-systems

### 3.3 セキュアなビルドパラメータをGitHubのSecretsに保存する
GitHubのリポジトリのページ
→ Settings
→ Secret

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/eecfe912-4323-3c77-d39f-6028306b85fc.png)

2つシークレットを設定する。

|名前|値|
|---|---|
|FIREBASE_APP_ID|アプリID|
|FIREBASE_TOKEN|Firebaseの認証トークン|

FIREBASE_TOKENをGitHubのSecretsとして保存するのは、これらがセキュアな情報だから。
FIREBASE_APP_IDはworkflowファイルに直接書いても良さそうだが、FIREBASE_TOKENとまとめて記述した方が管理しやすそうなので、Secretsにしておく。

### 3.4 GitHub Actionsのワークフローを設定する
(1)適当なブランチを作成する

(2)android.ymlの「Build with Gradle」の付近を変更する

```yaml
    - name: Build with Gradle
      run: ./gradlew build
    - name: upload artifact to Firebase App Distribution
      if: github.event_name == 'push'
      uses: wzieba/Firebase-Distribution-Github-Action@v1
      with:
        appId: ${{secrets.FIREBASE_APP_ID}}
        token: ${{secrets.FIREBASE_TOKEN}}
        file: app/build/outputs/apk/debug/app-debug.apk
```
示していない範囲は変更なし。

Firebase App Distributionの配布は、既成のGitHub Actionsを利用している。
詳細はこちら。
https://github.com/marketplace/actions/firebase-app-distribution

(3)変更をプッシュしてPRを作る
PRのChecksからGitHub Actionsを見ると、Firebase App Distributionの配布はスキップされていることが確認できる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/43fd5aa7-691e-f7c3-0ca6-7f54107b1755.png" width=50%>

(4)PRをmasterにマージする
PRのChecksからGitHub Actionsを見ると、、Firebase App Distributionの配布はスキップされていないことが確認できる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/ecc699fd-c80d-c717-7ef4-62a91d22ff29.png" width=50%>

Firebase App Distributionを見ると、アプリが配布されていることが確認できる。
(Firebase上のアプリのプロジェクトを開く -> 品質のApp Distribution)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/61ce7453-2e8c-6a07-d521-2beaee9d2454.png" width=50%>

未配信になっているのは、Firebase App Distributionにテスターのグループを設定していないから。
これを設定して、GitHub ActionsのFirebase App Distributionの配布でテスターのグループを指定すれば、配信できる。宿題として丁度良いと思う(この記事を見る人がいるのかは謎だが)。

## 終わりに

以上で、最低限のCI/CD環境は構築できた。
後は、依存ライブラリのキャッシュなどのビルド速度のチューニング、自動テスト実行、Store配布までやれば、「モバイルアプリのCI/CDの構築経験があります」と言っても良いレベルになれると思う。