AndroidアプリをビルドするBitriseのワークフローを効率化した話

# はじめに

私達のチームはBitriseと呼ばれるCI/CDツールでアプリをビルドしてします。

もともとAndroidはJenkins+Amazon EC2でビルド、iOSはJenkins+mac miniでビルドしていたのですが、環境のメンテナンスの手間やiOS側のビルド速度の遅さが気になってきたこともあるのと、bitriseのほうが各種サービスとの連携がしやすそうということから、乗り換えることにしました。

Bitriseは大変高機能で便利なツールですが、高機能でできることが多すぎるゆえにやや取っつきにくいという難点があります。
私自身もまだBitriseでわからないことだらけで手探りで使っています。

Bitriseにはワークフローと呼ばれる、ステップの集合体をつくることができますが、このワークフローをうまく整理しないとワークフローが増えたときにメンテナンスが大変になってきます。
この記事では、私達のチームでBitriseを使ったときに直面した問題と、そこで行ったワークフローの整備方針を紹介します。

# 前提
記事はAndroidアプリのビルドを前提としており、数カ国のアプリを1ソースで管理し、それをProductFlavorsで国やビルド種別を分けています。
そのため、iOSアプリや他の構成のアプリでは一部事情が異なる場合があります。

# 問題と解決策

## ワークフローの再利用性を高めて、Env Varsで値をセットする

### 問題

導入当初のノリでワークフローを次々増やしていったものの、ワークフローのデッドコピーが増え、管理が煩雑になってきた。

### 解決策

ワークフローの中身を変数を使うように工夫し、その変数をワークフローごとにEnv Varsでセットするようにしました。

この問題にぶち当たった際に最初に行ったのは、Workflow EditorのEnv Varsタブで、ワークフローごとに変数や接続先やコマンド種別をセットすることでした。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/38069/8d0fd699-3ad3-decd-6457-8bee2ac536f4.png)

Env Varsタブでは特定のワークフローごとに異なる環境変数を予めセットしておくことができます。
Bitriseではワークフローを組み合わせて他のワークフローも作ることができますが、環境変数をワークフローの中でべた書きすると、ワークフローの再利用性が低下してしまい、そのメリットを活かすことができません。
そこでEnv Varsで変数をセットすることで小分けしたワークフローをなるべく流用できるようにします。

※なお、ここでは詳しく紹介しませんが、ワークフローの再利用の方針に関しては、 弊社エンジニアのlovee の記事 [Bitrise のワークフローを分割して再利用性を高めよう](https://qiita.com/lovee/items/cc179ec2560ac6592d28) も参考になります。

## 2. ワークフローをより抽象化する

### 問題

しばらく1の方法で運用を続けていたのですが、ProductFlavorsのパターンが増えていくに連れて、日本版の開発環境、日本版の本番環境、米国版の開発環境、米国版の本番環境、それらのテストコード用…と、いくら再利用性を高めてもワークフローの数が増加することは避けられませんでした。

数が少ないうちはメンテはそこまで手間ではなかったのですが、これが何カ国にもなると、ワークフローを分割してももうワークフローの数が爆発し、管理しきれないだろうと思いました。
それに一部のEnv Varsが違うだけのWorkflowがいくつもあるのは正直言ってあまりスマートではないと感じていました。

### 解決策

今回はProductFlavorsの一部にもなっている国(locale)を別途ビルド時に渡すことにしました。
具体的にはビルド時のBuild configurationのAdvancedタブのCustom Environment Variablesで、カスタム変数を渡します。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/38069/6fdad5f6-7e8e-42cb-778e-419c0664303a.png)

こうすることで、開発環境用と本番環境用のワークフローだけ準備すれば良いので、いくら国が増えても困ることがなくなりました。

例えば、ProductFlavorsの数が少ない、あるいは単純なビルドしか行わない場合は、Workflowを分割した上で、全てのビルドパターンを網羅するワークフローをその数だけ作成しても良いでしょう。
しかし、ProductFlavorsの組み合わせや連携するシステムが多くなるにつれて、工夫しないとワークフローのメンテナンスが面倒になってきます。

余談ですが、ここまでくると、フラグ切り替えで本番環境と開発環境も一緒にできるのではと思いがちですが、
ワークフロー内での条件分岐はワークフローをみたときに各ステップで何をしているのかを常に意識しないといけなくなり、ミスが起こりやすいと考えています。
本番作業と普段の開発作業は分けておいたほうが開発用の設定が本番に入り込むこともなく安心です。

## 3. Custom Environment VariablesをAPI経由で設定してビルドする

### 問題

先のCustom Environment Variablesの面倒なところは毎回手で変数名と値を入力しなければならないことです。
正直なところ、「locale」が小文字だったか、大文字だったか、毎回忘れていましたし、接続先の環境のURLなんていちいち覚えていません。これはワークフローをへらすためとはいえ、ちょっと面倒でした。
冒頭でも触れましたが、もともと私達はCI/CDツールをBitriseにする前はJenkinsでビルドしていましたので、以下のようなプルダウンでjobに渡す値を選択できていたので、若干ビルド手順が非効率になっていると思いました。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/38069/03abe53a-dc32-23b6-1fb1-09805dda5787.png)

### 解決策

先のCustom Environment Variablesのページを下にスクロールしていくとわかりますが、curlのサンプルがあります。
bitriseのビルドはAPI経由でビルドを走らせることができます。
このAPIの公式のドキュメントは以下にあります。

[Build Trigger API](https://devcenter.bitrise.io/api/build-trigger/)
https://devcenter.bitrise.io/api/build-trigger/

サンプルとしては以下のような感じです。

```:curl
$ curl https://app.bitrise.io/app/XXXXXXXXXX/build/start.json --data '{"hook_info":{"type":"bitrise","build_trigger_token":"XXXXXXXX-token"},"build_params":{"branch":"develop","environments":[{"mapped_to":"locale","value":"jp","is_expand":true},{"mapped_to":"parameter","value":"value","is_expand":true}]},"triggered_by":"curl"}'
```
(認証情報などを一部置き換えています。)

Custom Environment Variablesの設定ページで適当な変数を入れると画面最下部のcurlのサンプルがリアルタイムで変わります。
カスタム変数が複数ある場合はbuild_params.environmentsの配列の要素が増えていきます。

APIが提供されているのであればbitriseのGUIコンソール上でいろいろ頑張る必要はないので、次のステップとしてcurl経由でビルドを行うことにしました。

#### PAWの設定

curlはMacのTerminalから実行してもよいのですが、リクエスト内容を毎回手で書き換えたくはないので、私はmacOS向けHTTPクライアント「[PAW](https://paw.cloud/)」からHTTPリクエストを行うことにしました。
リクエストさえできればいいので手段は何でも良さそうですが、GUIでわかりやすくHTTPリクエストで送る内容を指定できることから、私はこのソフトを重宝しています。
約50ドルとやや高額ですが、APIの疎通確認にも使えるのでアプリエンジニアでも持っていおいても損はないと思います。

以下はPAWでbitriseのbuild-triggerAPIを叩くようにしたサンプルです。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/38069/c4a1eb49-5fbe-2f7d-7f6b-2c4e888e2ba4.png)

ポイントはbitriseに渡す値やブランチ名をPAWのカスタム変数で設定できるようにしているところです。画像の青のラインの部分です。
PAWは予め環境変数をグループとして管理することができます。
![5.png](https://qiita-image-store.s3.amazonaws.com/0/38069/bc379552-590d-1ad0-dad0-509b3e0c591a.png)

ここでbitriseのCustom Environment Variablesにわたす変数を管理したり、ブランチを指定できるようにグループの値を設定しておけば、あとはプルダウンで選んで1クリックでPawからビルドの指示が出せます。
とても楽になりました。

Custom Environment Variablesの使い方は難しいものではありませんが、Pawの公式ブログ [How to use Environment Variables?](https://blog.paw.cloud/use-environment-variables/) が参考になると思います。

# 終わりに

乗り換えた当初は、分かりづらさからJenkinsでのビルドに戻りたいと何度も思いましたが、ワークフローの再利用性を高めたり、変数をうまく使うことで、効率よく進めることができるようになりました。

まだまだ、Bitriseで出来ることはたくさんありますので、外部ツールとの連携や便利なステップを探していろいろ試してみたいと思います。