minne事業部チーフテクニカルリードの @hisaichi5518 です。
minneのAndroidアプリは、2012年から開発されていてそれなりにコードベースも大きくなってきており、MacBook Pro (13-inch, 2016) プロセッサ 2.9 GHz Intel Core i5, メモリ 16 GB 2133 MHz LPDDR3 でビルドするとクリーンビルドで10分、キャッシュが効いていても3分ほどかかっていました。コードに変更を加えてビルドをするたび数分待ち、その間Twitterを眺めているのは開発効率が高いとは言えないので、リモートビルドを導入しました。
リモートビルドとは?
ここでいうリモートビルドとは、開発に利用しているマシン(以下、ローカルマシン)よりもハイスペックなインスタンスをGoogle Cloud Platform(以下、GCP)などに立ち上げて、そのインスタンスを利用してビルドを行い、ビルド結果をローカルマシンと同期することを指します。
リモートビルドを行ううえで必要となるのが、以下の2点です。
- GCPなどにインスタンスを立ち上げて、ビルドが出来る環境に整備する
- ファイルの同期やビルドの実行
どう実現するのか、1つずつ説明していきます。
GCPなどにインスタンスを立ち上げて、ビルドが出来る環境に整備する
minneには、リリース準備の自動化に利用しているtenmaというコマンドがあります。前まではOSSではありませんでしたが、今はOSSになっています。
https://github.com/hisaichi5518/tenma
このtenmaコマンドに、インスタンスの立ち上げとビルドが出来る環境に整備するまで行ってくれるtenma ichiba
があるのでそれを使っていきます。1
tenma ichiba
は、gcloudのインストールとセットアップが必要です。以下のリンクからダウンロードし、gcloud init
を実行しアカウントを紐付けてください。
https://cloud.google.com/sdk/gcloud
またどのAndroid SDKをインストールするか等の情報が必要になるので、Androidアプリのディレクトリ配下に tenma/ichiba.yml
を作る必要があります。
android_sdk:
license: "your license key"
update_list:
- platform-tools
- build-tools-27.0.3
- android-27
- extra-android-m2repository
- extra-google-m2repository
- extra-google-google_play_services
準備がおわり、Androidアプリのディレクトリで以下のコマンドを実行すればインスタンス作成とビルドが出来る環境が整います。2
bundle exec tenma ichiba --create-instance --provision-instance --instance-project <your-gcp-project>
tenma 0.9.0時点で作成されるインスタンスは以下の通りです。オプションで変更も可能です。
オプション | デフォルト値 |
---|---|
--instance-name |
remote-build |
--instance-zone |
asia-northeast1-c |
--instance-machine-type |
n1-highcpu-16 |
--instance-disk-size |
20(GB) |
以下は、インスタンス作成時にgcloudに渡すオプションですが、tenma ichiba
経由では変更出来ません。
gcloud オプション | 値 |
---|---|
--preemptible |
true |
--image-family |
ubuntu-1710 |
--image-project |
ubuntu-os-cloud |
ファイルの同期やビルドの実行
インスタンスの準備が出来たはずなので、次はファイルの同期やビルドを行います。これらは、tenmaではなく gojuno/mainframer を利用します。
Androidアプリのディレクトリに移動し、mainframerをダウンロードし、.mainframer/config
を作成します。
remote_machine=remote-build.asia-northeast1-c.<your-gcp-project>
ローカルからインスタンスに同期する必要がないファイルなどを指定したい場合は、ignore, localignore, remoteignoreを作成すれば、よしなにやってくれます。
設定が終われば、以下のコマンドでファイルの同期やビルドが行われます。
./mainframer.sh ./gradlew :app:assembleDebug
またAndroid StudioのRunボタンから実行したい場合はAndroid Studio Configuration to Run APKに書いてある通りにやれば、実現できます。
結果
tenma ichiba
+ mainframer
を利用することで、ビルド時間はクリーンビルドで3分, キャッシュが効いているビルドで30秒から1分ほどとなりました。
Androidエンジニアは4人いて、1人1日20回ビルドしてるとして、1ビルド3分かけてるとすると
20*3
=1日で1人あたり60分(1時間)ビルドを待っている20*3*31
=1ヶ月(31日間)で1人あたり1860分(約31時間)ビルドを待っている20*3*31*4
=1ヶ月(31日間)で4人あたり7440分(約124時間)ビルドを待っている
これをリモートビルドを実装したときの数字である1ビルド1分ほどにすると
20*1
=1日で1人あたり20分ビルドを待っている20*1*31
=1ヶ月(31日間)で1人あたり620分(約10時間)ビルドを待っている20*1*31*4
=1ヶ月(31日間)で4人あたり2480分(約41時間)ビルドを待っている
となり、ざっくりとした計算ではありますが 124時間-41時間で4人あたり1ヶ月約83時間待たなくて良くなりました。
節約術
Androidエンジニアが働く時にだけリモートビルドインスタンスが立ち上がっていればいいので、平日朝に自動でインスタンスを立ち上げて、夜には削除するようにしています。これはBitriseの定期実行機能を使って実現しています。
以下のようなワークフローになります。
---
format_version: '4'
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
project_type: android
workflows:
delete-remote-build-instance:
steps:
- activate-ssh-key:
run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
- git-clone: {}
- script:
title: Delete remote-build instance
inputs:
- content: |-
#!/usr/bin/env bash
set -e
set -x
curl -o /tmp/sacc_key.json $BITRISEIO_SERVICE_ACCOUNT_KEY_URL
gcloud auth activate-service-account -q --key-file /tmp/sacc_key.json
gcloud config set project $GCP_PROJECT
bundle install
bundle exec tenma ichiba --delete-instance
- deploy-to-bitrise-io: {}
- slack:
inputs:
- channel: "#minne_dev"
- text: ''
- pretext_on_error: Androidリモートビルドインスタンスの削除に失敗!!!!!!!!!1
- pretext: Androidリモートビルドインスタンスの削除を行いました
- channel_on_error: "#minne_dev"
- webhook_url: <webhook_url>
create-remote-build-instance:
steps:
- activate-ssh-key:
run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
- git-clone: {}
- script:
title: Set up remote machine
inputs:
- content: |-
#!/usr/bin/env bash
set -e
set -x
curl -o /tmp/sacc_key.json $BITRISEIO_SERVICE_ACCOUNT_KEY_URL
gcloud auth activate-service-account -q --key-file /tmp/sacc_key.json
gcloud config set project $GCP_PROJECT
bundle install
bundle exec tenma ichiba --create-instance
- deploy-to-bitrise-io: {}
- slack@2.7.2:
inputs:
- channel: "#minne_dev"
- pretext: Androidリモートビルドインスタンス作成に成功しました。
- pretext_on_error: Androidリモートビルドインスタンス作成に失敗!!!!!!1
- channel_on_error: "#minne_dev"
- webhook_url: <webhook_url>
app:
envs:
- opts:
is_expand: false
GRADLE_BUILD_FILE_PATH: build.gradle
- opts:
is_expand: false
GRADLEW_PATH: "./gradlew"
- opts:
is_expand: false
GCP_PROJECT: <your-gcp-project>
まとめ
- minneのAndroidアプリ開発では、リモートビルドを利用しています
- リモートビルドによって、4人あたり約83時間待つ時間を減らすことが出来ました
- 節約のために、インスタンスの立ち上げと削除は自動化しています
-
tenma ichiba
は、みなさんご存知活気あふれる浪花の台所 天満市場から取ってます。 ↩ -
都度プロジェクトを設定するのがめんどい人は、環境変数
TENMA_ICHIBA_INSTANCE_PROJECT
を設定すると適用されます ↩