GitHub / Bitrise / Firebase App DistributionでCI/CD環境を構築する

[GitHub](https://github.com/)と[Bitrise](https://www.bitrise.io/)と[Firebase App Distribution](https://firebase.google.com/docs/app-distribution)を使ってCI/CD環境を構築します。

- masterからブランチを切る
- PRを出してmasterへマージ
- BitriseでAndroidアプリをビルド
- Firebase App Distributionでアプリ配布
- Slackへ通知

を回せる環境を作りたいと思います！

## 環境

- macOS Catalina (10.15.2 Beta)
- Android Studio 3.5.2

## 必要な物

- GitHubアカウント
- Bitriseアカウント
- Firebaseアカウント
- [Homebrew](https://brew.sh/)
- [gibo](https://github.com/simonwhitaker/gibo)
- [hub](https://github.com/github/hub)

```sh
brew install gibo hub
```

今回のアプリはBitriseの使用時間が`4m52s`だったので、試すだけなら[無料アカウント](https://www.bitrise.io/pricing/teams)でも大丈夫だと思います。

## Androidアプリ作成

[Android Studio](https://developer.android.com/studio/)をインストールしてプロジェクトを作成します。

![android.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/629f88fa-d023-3647-4fdf-90bee45b82c6.png)

今回は`Empty Activity`を選択。

![android2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/84d7ce6c-ddb6-7553-c701-c0afbdc9db21.png)

- Name: 好きなアプリ名
- Package name: 他のアプリと被らないようなもの。(GitHubアカウントがあれば`io.github.<username>.<app_name>`とかが良いかも)


![android3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/03b85db9-2509-5a7a-e423-e282a53201b0.png)


## GitHubにリポジトリ作成

`Android Studio`でターミナルを開く。

![android4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/e0c15987-1440-b433-89fd-88c6f4bce986.png)


自動でプロジェクト直下にいる状態になるので下記のコマンドを実行する。

```sh
# cd <project_root>
# gitリポジトリ初期化
git init
# Android用gitignore作成
gibo dump android > .gitignore
git add .
git commit -m "init"
```

GitHubへPushするとリポジトリが作成されます。

```sh
hub create -p # -pオプションつけないと公開リポジトリになる注意
# https://github.com/takagisou/BitriseFirebaseExample

git push -u origin master
# To github.com:takagisou/BitriseFirebaseExample.git
#  * [new branch]      master -> master
# Branch 'master' set up to track remote branch 'master' from 'origin'.
```

## Bitrise

[Dashboard](https://app.bitrise.io/dashboard/builds) ->`Add New App`-> `Add New App on web UI` でアプリを追加します。

`Add New App from CLI` の方はよく分かっていません。

![bitrise2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/9ae2b798-dcc5-2337-311c-afa0603abbc3.png)

アカウントとリポジトリの公開状態（？）を選択します。

![bitrise3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/8b0d64a8-2e3a-b44f-d2bc-a9240b6f7bd8.png)


リポジトリ選択

![bitrise4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/c9c17222-cfb2-595b-2a4a-28b2a5fa83b2.png)

Bitriseがリポジトリにアクセスするための`SSH key`を設定します。
とりあえず自動で設定してくれる方(`No, auto-add SSH key`)で大丈夫です。

![bitrise5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/08e59bc6-2adb-43c6-1f10-a58db8f4f974.png)


ブランチ名を記入します（ここでは`master`)

![bitrise6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/5818ab90-9d00-3f15-f724-5ea43a4a294c.png)

VALIDATINGが始まります…（多分プロジェクト構成などを元にAndroidアプリかiOSアプリかなどを判定してる）


![bitrise7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/cc51af50-0409-fc03-64ef-7dc0d88bcc9d.png)

無事Androidアプリと認識されたので各種設定を行い`Confirm`します。

- Module: app
- Variant: debug (多分)

![bitrise8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/dca13f0d-0072-51f6-d26c-08d818eecb77.png)

アイコン設定（ここではデフォルト） -> `Choose Image and Proceed`

![bitrise9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/845e00be-19f3-4564-14fb-190f9c0a1877.png)

`Register a Webhook for me!`を選択します。
ただ今回は`master`にマージされたときに`Firebase App Distribution`へアップロードしたいだけなので後で設定を変更します。

![bitrise10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/3e03def8-3b0f-557a-5fe7-8c7c72ec7776.png)

`We've kicked off your first test build for you!`をクリックしてビルドを開始します！


![bitrise11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/aafd960f-9510-a998-0488-7803695000ec.png)

ビルドが始まります！

![bitrise12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/ab71e391-f606-40fd-08a7-0af19fa537ce.png)


しばらくするとビルド成功メッセージが表示されると思います！ :tada: 

![bitrise12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/cd3bb9b2-0e39-fcc0-cad3-b83c3cbc6004.png)

とりあえずここまでにして次はFirebaseの設定をします。


## Firebase

[Firebaseコンソール](https://console.firebase.google.com/)からプロジェクトを追加します。

![firebase.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/77b888a6-9ba8-cad3-efc5-a7b10b776f75.png)

プロジェクト名は好きなプロジェクト名で大丈夫です。

![Firebase2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/e805f9f7-4fa4-6321-9098-12316f094135.png)

`このプロジェクトでGoogleアナリティクスを有効にする`は`Firebase App Distribution`を使うだけなら有効にしなくても良いかもしれませんが、よく分かってないので有効にしてます…。

![firebase3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/e8b1e377-0565-df79-01bc-1eec47988768.png)

Googleアナリティクスアカウントもよく分かっていませんが適当に作成し、`プロジェクトを作成`をクリックします…。

![firebase4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/47457cec-ea25-79df-23ab-386b68e1bd23.png)


`App Distribution`を選択し`Androidアプリ`を追加します。

![app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/d935ea62-822f-95db-a856-1e00b395c44c.png)

表示される手順通りにAndroidプロジェクトにFirebaseを組み込んでいきます。
最後のステップの`アプリを実行してインストールを確認`は少しチェックが通りづらいような気がしました。
アプリを再度インストールしたり、ステップを行ったり来たりしてるとチェックが通ると思います。

![app2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/678868fe-6804-1ce9-c24a-08e30bd1e024.png)

コンソールに進むをクリックして、利用規約に同意して開始ボタンを押します。


テスターとグループを追加します。
このグループ名は後でBitriseで使用します。

![app5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/57270af5-0bbe-78cb-5c0e-a0989b42c24f.png)

招待を受けたテスターはメールの指示に従って`Firebase App Distribution`アプリをインストールします。

インストール完了すると`App Tester`というアプリが増えていると思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/596e81c5-bc54-9805-90c5-38636899db9a.png" width=320 alt="App Tester" />


## Firebase その2

下記をメモっておきます。

- アプリID
- Firebase token

`Bitrise`から`Firebase App Distribution`へアプリをアップロードする際に使用します。


プロジェクト設定 > 全般 > アプリID

![bitapp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/f4e63b1e-49e2-839e-c94d-628574e902b8.png)

[Firebase CLI](https://firebase.google.com/docs/cli#install-cli-mac-linux)をインストールして、`token`を取得します。

```sh
# インストール
$ curl -sL firebase.tools | bash # npm install -g firebase-tools

# ログイン（ブラウザが開きます）
$ firebase login

# トークン取得
$ firebase login:ci

.........
.........
.........

✔  Success! Use this token to login on a CI server:

# 下記がトークン
1//0eUwb.......................
```

Bitriseに戻ります。


## Bitrise その2

### Code Signing

`Workflow` > `Code Signing`からkeystoreファイルをアップロードします。

今回は`~/.android/debug.keystore`を使用します。

よく分かっていませんでしたが、debugビルドのapkはコード署名が必要ないのでは無く、AndroidStudioが自動で生成してそれを使って署名してくれてる感じなんですね。

勉強になるなぁ…。

![keystore.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/e6ff7378-2a61-493d-48d3-e05a0095c3fc.png)

password(Keystore, Key両方): android
alias名: androiddebugkey
https://qiita.com/taka0125/items/c408df4061a0af49c9b3

入力したら`Save metadata`クリックして保存します。

![metadata.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/a6320d35-127f-f4f5-c7c7-f9ad83204e1a.png)

### Workflows

`Workflow`を開きます。

下記のような感じにします。

| 変更前 | 変更後 |
| --- | --- |
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/b076302a-f1ed-ac8d-a605-a5ed44e6b531.png" width=320 alt="before" />| <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/ba6f517e-f799-7013-40aa-ead51f6dee5b.png" width=320 alt="after" />|

初期状態からいくつか`Workflow`を追加しています。

#### Gradle Runner

最初apk書き出す`Workflow`無くて焦りましたが、`Gradle Runner`で書き出せました。
正しいかはよく分かりません…。

- Gradle task to run: `assembleDebug`
- gradlew file path: `./gradlew`

と設定するとapkが書き出されるみたいです。

![gradle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/c36d9842-0213-6a2f-26c6-597c1e776586.png)

#### Android Sign

`Keystore`ファイルがアップロードされていていれば特に設定はいらないと思います（多分）

#### [BETA] Firebase App Distribution

- Firebase Token: `firebase login:ci`で取得したtoken
- Firebase App ID: FirebaseのダッシュボードでメモったアプリID
- Test Groups: `Firebase App Distribution`で作成したグループ名

`Firebase Token`は`Secret Variable`を追加してそれを参照するような形になると思います。
変数名は分かりやすい名前なら何でも大丈夫です。

![secrets.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/6e092b4b-bd3d-e93d-3676-e418a08bc2bd.png)

![token2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/d54e6d05-107b-401d-e8a1-18bba0a39069.png)


#### Send a Slack message

`Slack Webhook URL`か`API token`のいずれかの指定が必要みたいです。
今回は`Slack Webhook URL`を使用しました。

https://slack.com/intl/ja-jp/help/articles/115005265063

`Secret Variable`を追加して`Slack Webhook URL`を設定します。
変数名は分かりやすいものなら何でも大丈夫です。


## Bitrise その3

もう配布できる状態なのですが、このままだとPRやコミットの度Workflowが走ってしまうので、`Triggers`から不要な設定を削除します。

![triggers.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/509043de-6b78-f4b8-0c67-c369f3967474.png)

これで`Bitrise`から`Firebase App Distribution`へアプリをアップロードする準備が整いました！

## GitHubでPRを作ってmasterにマージしてみる


`master`からブランチを切って適当な変更を加えて`GitHub`にpushしてPRを出します。

![github.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/5d1eb029-fd4f-e486-552d-cdd8e1a98628.png)

そうすると`Bitrise`のビルドが走り始め…


![bitrise.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/4ef82f7d-e4ef-30d6-3fc1-c516bbb8fdb2.png)

無事ビルドが成功すると`Slack`に通知が来て…

![slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/b92c969f-e57d-06d9-4895-0848aa4c55d4.png)

端末の方にも配布されます :tada: 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/3778efb2-dab5-747c-bdf5-4b0646a5e92e.png" width=320 alt="android_app_distribution" />

## その他

一応`master`に変更が加わったら配布してSlack通知まで構築できましたが、以下のような課題があります。

- ビルド番号が更新されていない
- リリースノートが無い
- Slackメッセージが設定されていない

`Bitrise`の`Workflow`だけで構築しましたが、[fastlane](https://qiita.com/xxminamixx/items/b569311050fb42859e56)を使えばもう少し柔軟な環境が構築できそうですね。

もしかしたらBitriseだけでもできるのかもしれませんが、Bitrise全然使いこなせて無いので詳しいことはよく分かっていません…。

もっと使いこなして行きたいですね！