[BITRISE][iOS][Android] BITRISE でブランチにpushされたらビルド→Fabric Betaにアップロード→テスターに通知→Slackに通知するようにしてみた

[前回](https://qiita.com/a_jike/items/f3c87845da8456e26526)の続きです。
BITRISEで以下のようにします。

1. 指定ブランチへのpushをトリガーにしてビルド開始
2. Fabric Betaにアップロードし、テスターにメールで通知する
3. Slackの特定のチャンネルにアプリの情報、FabricのリリースノートとURL、QRコードを通知する


これらを設定したymlのtriggers, workflow部分を抜粋して貼っておきます。

iOS

```
...

trigger_map:
- push_branch: master
  workflow: WORKFLOW_NAME

...

  WORKFLOW_NAME:
    steps:
    - activate-ssh-key@3.1.1:
        run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
    - git-clone@3.5.2: {}
    - cache-pull@1.0.0: {}
    - script@1.1.4:
        title: Do anything with Script step
    - certificate-and-profile-installer@1.8.8: {}
    - xcode-archive@2.3.7:
        inputs:
        - configuration: Debug
    - deploy-to-bitrise-io@1.3.7: {}
    - cache-push@1.1.4: {}
    - fabric-crashlytics-beta-deploy@2.2.1:
        inputs:
        - api_key: TBD_FABRIC_APIKEY
        - build_secret: TBD_FABRIC_SECRET
        - release_notes: "$BITRISE_GIT_MESSAGE"
        - group_aliases_list: "$FABRIC_GROUP_ALIASES"
    - ipa-info@1.0.1: {}
    - script@1.1.5:
        inputs:
        - content: |-
            #!/usr/bin/env bash
            # fail if any commands fails
            set -e
            # debug log
            set -x

            # write your script here

            buildNumber="$IOS_APP_VERSION_NAME ($IOS_APP_VERSION_NAME.$BITRISE_BUILD_NUMBER)"
            appName=$IOS_APP_NAME
            bundleId=$IOS_IPA_PACKAGE_NAME
            workflowId=$BITRISE_TRIGGERED_WORKFLOW_ID
            url="https://apps-ios.crashlytics.com/projects/"
            echo "$BITRISE_APP_TITLE $buildNumber $workflowId $url"
            message="The workflow \"$workflowId\" was succeeded!\n$appName $buildNumber\n$bundleId\n$BITRISE_GIT_MESSAGE\n$url"

            envman add --key SLACK_MESSAGE_BODY --value "$message"
            envman add --key SLACK_MESSAGE_URL --value "$url"
            echo "SLACK_MESSAGE_BODY is $SLACK_MESSAGE_BODY"
            echo "SLACK_MESSAGE_URL is $SLACK_MESSAGE_URL"

            # or run a script from your repository, like:
            # bash ./path/to/script.sh
            # not just bash, e.g.:
            # ruby ./path/to/script.rb
    - create-install-page-qr-code@0.1.2:
        inputs:
        - public_install_page_url: "$SLACK_MESSAGE_URL"
    - slack@2.6.3:
        is_always_run: false
        inputs:
        - message: "$SLACK_MESSAGE_BODY"
        - emoji: ":bitrise:"
        - webhook_url: https://hooks.slack.com/services/PATH_OF_IDS
        - channel: "#CHANNEL_NAME"
        - from_username: Bitrise CI
        - image_url: "$BITRISE_PUBLIC_INSTALL_PAGE_QR_CODE_IMAGE_URL"
```

Android

```
...

trigger_map:
- push_branch: master
  workflow: WORKFLOW_NAME

...
  WORKFLOW_NAME:
    steps:
    - activate-ssh-key@3.1.1:
        run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
    - git-clone@3.5.2: {}
    - cache-pull@1.0.0: {}
    - script@1.1.4:
        title: Do anything with Script step
    - generate-text-file@0.0.3:
        inputs:
        - file_name: "$FABRIC_GROUP_ALIASES_FILE_PATH"
        - file_content: "$FABRIC_GROUP_ALIASES"
    - generate-text-file@0.0.3:
        inputs:
        - file_name: "$FABRIC_PROPERTIES_FILE_PATH"
        - file_content: |-
            apiSecret=$FABRIC_API_SECRET
            apiKey=$FABRIC_API_KEY
            betaDistributionReleaseNotes=\"$BITRISE_GIT_MESSAGE\"
            betaDistributionGroupAliasesFilePath=$FABRIC_GROUP_ALIASES_FILE_PATH
    - install-missing-android-tools@2.0.2: {}
    - gradle-runner@1.7.7:
        inputs:
        - gradle_file: "$GRADLE_BUILD_FILE_PATH"
        - gradle_task: assembleDebug crashlyticsUploadDistributionDebug
        - gradlew_path: "$GRADLEW_PATH"
    - deploy-to-bitrise-io@1.3.7: {}
    - cache-push@1.1.4: {}
    - apk-info@1.3.0: {}
    - script@1.1.5:
        inputs:
        - content: |-
            #!/usr/bin/env bash
            # fail if any commands fails
            set -e
            # debug log
            set -x

            # write your script here
            plistPath=$BITRISE_INFO_PLIST_PATH
            echo "Writing to $plistPath"

            versionNumber=$ANDROID_APP_VERSION_NAME
            packageName=$ANDROID_APP_PACKAGE_NAME
            buildNumber="$versionNumber ($BITRISE_BUILD_NUMBER)"
            workflowId=$BITRISE_TRIGGERED_WORKFLOW_ID
            url="https://apps-ios.crashlytics.com/projects/"
            echo "$BITRISE_APP_TITLE $buildNumber $workflowId $packageName $url"
            message="The workflow \"$workflowId\" was succeeded!\n$BITRISE_APP_TITLE $buildNumber\n$packageName\n$BITRISE_GIT_MESSAGE\n$url"

            envman add --key SLACK_MESSAGE_BODY --value "$message"
            envman add --key SLACK_MESSAGE_URL --value "$url"
            echo "SLACK_MESSAGE_BODY is $SLACK_MESSAGE_BODY"
            echo "SLACK_MESSAGE_URL is $SLACK_MESSAGE_URL"

            # or run a script from your repository, like:
            # bash ./path/to/script.sh
            # not just bash, e.g.:
            # ruby ./path/to/script.rb
    - create-install-page-qr-code@0.1.2:
        inputs:
        - public_install_page_url: "$SLACK_MESSAGE_URL"
    - slack@2.6.3:
        is_always_run: false
        inputs:
        - message: "$SLACK_MESSAGE_BODY"
        - emoji: ":bitrise:"
        - webhook_url: https://hooks.slack.com/services/CHANNEL_OF_PATH
        - channel: "#CHANNEL_NAME"
        - from_username: Bitrise CI
        - image_url: "$BITRISE_PUBLIC_INSTALL_PAGE_QR_CODE_IMAGE_URL"
```

以上！

というわけにもいかないので以下説明になります。

# 1. 指定ブランチへのpushをトリガーにしてビルド開始
## BITIRISEからWebhook URLをコピー
1. `アプリ > Workflow > Codeタブ`を選択します。
2. WEBHOOKSでGitHubを選択し、Webhook URLをコピーします。
![webhook_setting.png](https://qiita-image-store.s3.amazonaws.com/0/156085/a33b273d-7d76-8b6c-5728-2c10ab733473.png)

## 1-1. GitHubの設定 - webhook URLの追加
1. プロジェクトをブラウザで開きます。
2. `Settings`タブを選択します。
3. 左メニューの`Webhooks`を選択します。
  ![github_webhook.png](https://qiita-image-store.s3.amazonaws.com/0/156085/a8927e9e-2310-c790-e883-2cea6ae40cc1.png)

4. 右上の`Add webhook`を選択して、以下の値で設定します。
  Payload URL: BITRISEでコピーしたWebhook URL
  Content type: `application/json`
  Which events would you like to trigger this webhook?: `Let me select individual events.`
  ![github_webhook_add_1.png](https://qiita-image-store.s3.amazonaws.com/0/156085/294be434-54c0-682b-e2fb-51de69d3238b.png)

5. `Let me select individual events.`で必要なイベントにチェックを入れます。
6. `Add webhook`を選択して追加します。
  ![github_webhook_add_2.png](https://qiita-image-store.s3.amazonaws.com/0/156085/6d82f880-a48e-2c02-b54e-4cec8f732510.png)


## 1-2. BITRISEの設定 - トリガーの追加
![add_triggers.png](https://qiita-image-store.s3.amazonaws.com/0/156085/bfd80f9c-360a-e946-6747-85dce482eb18.png)
1. `アプリ > Workflow > Triggersタブ`を選択します。
2. *PUSH* タブを選択します。
3. \+ ADD TRIGGERボタンを押下してトリガーを追加します。
4. 左側でブランチ名を指定します。
5. 右側に実行したいWorkflowを選択します。

# 2. Fabric Betaにアップロードする
## 2-1. iOS
プロジェクトにFabricを導入済みの前提です。
導入していない方は[こちら](https://fabric.io/kits/ios/crashlytics/install)を参照してください。

### 2-1-1. Archive
Fabricにあげるためにipaを作る必要があります。
初めからdeployというWorkflowが作られていますが、もし下記のstepが見当たらない場合追加しなければなりません。
`Xcode Archive & Export`
<img width="901" alt="add_archive_step.png" src="https://qiita-image-store.s3.amazonaws.com/0/156085/343d73b1-b4da-5f0d-ffb3-36fb3d8fc2e6.png">

### 2-1-2. Fabric Beta
非常に便利なstepが用意されています。
*Fabric / Crashlytics deployer*
<img width="354" alt="add_fabric_step.png" src="https://qiita-image-store.s3.amazonaws.com/0/156085/4a7645fc-4a09-5863-1e42-467c05fc6e1b.png">

#### :arrow_up: Uploading Distribution
`Fabric: API Key`と`Fabric: Build Secret`を設定するだけでOK!
<img width="857" alt="set_fabric_step.png" src="https://qiita-image-store.s3.amazonaws.com/0/156085/625e8120-9e8a-a349-0dcc-f9577793263a.png">

#### :pencil: Release Notes
`Release Notes`はFabric上のRelease Notesにそのまま反映されます。
自分の場合は、`$BITRISE_GIT_MESSAGE` を入れています。
こうしておけば、マニュアルでビルドした場合にはMessageで指定した文字列がセットされ、Triggerでビルドした場合はgitのcommitメッセージがそのまま反映されます。

#### :bell: Notify
Fabricアップロード時の通知は、`Notify: Emails`を指定します。

複数人に配布したい場合、`Notify: Group Aliases`でグループ名を指定します。
グループはFabric上で編集します（後述）

## 2-2. Android
プロジェクトにFabricを導入済みの前提です。
Fabricの導入は[ここ](https://docs.fabric.io/android/fabric/overview.html)や[ここ](https://fabric.io/kits/android/crashlytics/install)などをご参照ください。

### 2-2-1. Fabric Beta
iOSとは異なり便利なstepはありません。

#### :arrow_up: Uploading Distribution
*Gradle Runner* stepの`Gradle task to run`で設定します。
gradle taskを指定する形になります。
![gradletasktorun.png](https://qiita-image-store.s3.amazonaws.com/0/156085/18b771ab-31e9-172b-22f3-619a374c000c.png)


指定可能なtaskは以下のコマンドで確認可能です。

```
./gradle tasks
```

Fabric Betaへのdistributionは、

```
./gradle assemble[Flavor]Debug crashlyticsUploadDistribution[Flavor]Debug
```

の形で行いますので、`Gradle task to run`での指定は以下のようにになります。

```
assemble[Flavor]Debug crashlyticsUploadDistribution[Flavor]Debug
```
もしくは
```
assemble[Flavor]Release crashlyticsUploadDistribution[Flavor]Release
```

API KeyとBuild Secretの指定は、プロジェクトにapp/fabric.propertiesというファイルを追加してそこに記述します。
ただし、リポジトリで直接fabric.propertiesを管理するのは良くないらしいので、BITRISE上でファイルを生成します。

1. *Git Clone Repository* から *Gradle Runner* の間に適当に *Generate Text File* というstepを追加します。

2. Configの`Content of the text file`にファイルの内容を記述します。
ファイルの内容は以下です。

```
apiSecret=$FABRIC_API_SECRET
apiKey=$FABRIC_API_KEY
betaDistributionReleaseNotes=\"$BITRISE_GIT_MESSAGE\"
betaDistributionGroupAliasesFilePath=Fabric上で設定したグループのAlias
```

<img width="994" alt="android_fabric.png" src="https://qiita-image-store.s3.amazonaws.com/0/156085/fa07ea94-8c05-da6e-6e42-805b66a4e5eb.png">


`$FABRIC_API_SECRET`と`$FABRIC_API_KEY`は直接描いてもいいですが環境変数に定義します。


#### :pencil: Release Notes
`betaDistributionReleaseNotes `で指定します。
`$BITRISE_GIT_MESSAGE`は前述の通りです。

#### :bell: Notify
`betaDistributionGroupAliases`か`betaDistributionGroupAliasesFilePath`で指定します。
例ではファイルの内容から取得しています。

# 3. Slackの特定のチャンネルにアプリの情報、FabricのリリースノートとURL、QRコードを通知する
## 3-1. SlackでWebhook URLを取得する
1. Slackの[Incoming WebHooks](https://slack.com/services/new/incoming-webhook)にアクセスする。
2. "Post to Channel"で投稿先のチャンネルを選択する、もしくは新規作成。
3. "Add Incoming WebHooks integration"ボタンを押下
4. "Webhook URL"に表示されているURLを控える
![slack_webhook.png](https://qiita-image-store.s3.amazonaws.com/0/156085/28bb7f15-ef99-a28e-06cb-c547da0973e5.png)

参考: 
[SlackのWebhook URL取得手順](https://qiita.com/vmmhypervisor/items/18c99624a84df8b31008)

## 3-2. BITRISEでSlackのステップを追加する
### 3-2-1. Slackに投げるメッセージに含む情報を取得する  
1. `IPA Info`ステップを追加  
このステップを追加しておくと、アプリ名やファイルサイズ、バージョンなど規定の環境変数に格納してくれる  
2. `Script`ステップを追加  
以下のようにSlackメッセージに含むための要素を生成しておく  

```
// アプリのバージョンとビルド番号
buildNumber="$IOS_APP_VERSION_NAME ($IOS_APP_VERSION_NAME.$BITRISE_BUILD_NUMBER)"
// アプリ名
appName=$IOS_APP_NAME
// Bundle ID
bundleId=$IOS_IPA_PACKAGE_NAME
// 実行したworkflow ID
workflowId=$BITRISE_TRIGGERED_WORKFLOW_ID
// FabricのURL
url="https://apps-ios.crashlytics.com/projects/"
echo "$BITRISE_APP_TITLE $buildNumber $workflowId $url"
// workflow ID、アプリ名、ビルド番号、バンドルID、リリースノート、URLを連結してSlack用のメッセージにする
message="The workflow \"$workflowId\" was succeeded!\n$appName $buildNumber\n$bundleId\n$BITRISE_GIT_MESSAGE\n$url"

envman add --key SLACK_MESSAGE_BODY --value "$message"
envman add --key SLACK_MESSAGE_URL --value "$url"
echo "SLACK_MESSAGE_BODY is $SLACK_MESSAGE_BODY"
echo "SLACK_MESSAGE_URL is $SLACK_MESSAGE_URL"
```

それぞれ`$SLACK_MESSAGE_BODY`, `$SLACK_MESSAGE_URL`という環境変数に格納しておく

![ipainfo.png](https://qiita-image-store.s3.amazonaws.com/0/156085/24e7134d-90a9-7cec-73c3-e06b8e0ab3dd.png)


### 3-2-2. QRを生成するステップを追加
![qrstep_icon.png](https://qiita-image-store.s3.amazonaws.com/0/156085/43b52892-ec81-027c-5738-dbcbff791e15.png)
このステップの追加しておけば、MacのSlackで見ていてもiPhoneでQRを撮影すればすぐにアクセスできる。いちいちiOSのSlackで表示し直す必要がなくなる。

1. `Install page QR code`ステップを追加する
2. *Input variables* に以下の値を設定する  
  *Public Install Page URL* : 3-2で生成した`$SLACK_MESSAGE_URL`を指定  
  *Public Install Page QR Code Image size* : 適当なサイズを指定
![qrstep_variabled.png](https://qiita-image-store.s3.amazonaws.com/0/156085/0f8f806f-0633-9db0-04d2-294d6c9224c1.png)


### 3-2-3. Slackに投稿するステップを追加する
![sendslack_icon.png](https://qiita-image-store.s3.amazonaws.com/0/156085/4ba408c2-ff35-76ea-77e8-bf4ac2b96cb0.png)

1. `Send a Slack message`ステップを追加する
2. *Input variables* に以下の値を設定する  
  *Slack Webhook URL* : 1-1で控えたURLを指定
  *Target Slack channel, group or username* : 投稿先のSlackチャンネル名を指定
  *The message you want to send* : 3-2で生成した`$SLACK_MESSAGE_BODY`を指定
  *Image URL* : 3-2-2でoutputされる`$BITRISE_PUBLIC_INSTALL_PAGE_QR_CODE_IMAGE_URL`を指定
  *Emoji Icon* : Slack側でBITRISEのアイコンを絵文字登録したものを指定しておいた
![send_slack_variables.png](https://qiita-image-store.s3.amazonaws.com/0/156085/82e64c43-0eea-ca17-3544-b18acb652da9.png)

---
次回は、リリースビルドの *iTunes Connect へのDeployでコケた箇所* について纏めたいと思います。（時期未定:sweat_smile:）

---
https://www.bitrise.io/

```
                              MMMMMMMMMMMM                                
                              MMMMddddNMMM                                
                              MMMM    mMMM                                
                              MMMMssssNMMM                                
                              MMMMMMMMMMMM                                
                                 sMMMMd                                   
                                 yMMMMd                                   
      MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM      
      MMMMdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdMMMM      
      MMMM                                                      MMMM      
      MMMM                                                      MMMM      
     MMMMM                                                      MMMMMM    
  MMMMMMMM                                                      MMMMMMMM  
 MMM' MMMM           .yy.                        .yy.           MMM  'MMM 
MMMh  MMMM         .MMMMMMl.                  .lMMMMMMM.        MMM   hMMM
MMM   MMMM       .MMMMMmNMMMl.               .MMMMNmMMMM.       MMM    MMM
MMMs  MMMM       .hhhh   yhhh.               .hhhh   hhh+       MMM   sMMM
 MMM. MMMM                                                      MMM  .MMM 
  MMMNMMMM                                                      MMMMNMMM  
    MMMMMM                                                      MMMMMM    
      MMMM                                                      MMMM      
      MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM      
      MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM      
      MMMM                                                      MMMM      
      MMMM                                                      MMMM      
      MMMM                                                      MMMM      
      MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM      
      MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM      
```