CircleCiでAndroid開発を爆速にする

CHDcyXDVAAElf12

コベリンの継続的インテグレーション

feather for twitterのAndroid版では開発フローの中に積極的に継続的インテグレーションを取り入れています。ツールとしてはCircleCIを利用しています。今回はCircleCIを利用する際のTipsを紹介します。

現在やっていること。

アプリケーション開発に関わる幾つかのタスクを自動化し、開発効率や品質の向上を狙っています。

Android開発において自動化を行っているタスクは現時点で以下となります。

これらのタスクを自動化することで、常にアクセス可能なテストに合格したバイナリの利用や個人の開発環境では気がつかないミスやエラーの早期発見、またビルドタスクがソースコードになることからプロジェクトが属人化せずメンバーのスケールアウトが容易になると考えられます。

さて、CircleCIですがAndroidアプリのビルド・テストを行う上で幾つか問題が発生しました。問題とその解決方法を紹介します。

メモリが足りなくなる問題

CircleCIはビルドを行う仮想マシンにメモリなどの制約が指定されています。使用可能なメモリ上限を上回って利用する状態が続くとThe build VMs have a memory limit of 4G. Your build hit this limit on one or more containers, and your build results are likely invalid.が表示され、タスクが失敗します。

これを防ぐために、いくつかの設定を行います。

まずはJVMのヒープサイズ、最大ヒープサイズを指定します。

machine:
    java:
        version: oraclejdk8
    environment:
        JAVA_OPTS: "-Xms256m -Xmx512m"

初期ヒープサイズ、最大ヒープサイズを設定することでgradleによるビルドの際のメモリ利用量を調整します。

次にdexファイル生成時のオーバーヘッドを抑えるための設定を行います。今度はbuild.gradleに以下を記入します。

android {
    dexOptions {
        javaMaxHeapSize "512M"
        preDexLibraries !(System.getenv()["CIRCLECI"] as boolean)
    }
}

javaMaxHeepSizeはdexファイル生成時のヒープサイズの最大値のようです。environmentで指定したJAVA_OPTSはdexファイル生成時には利用されないらしいので、こちらで指定をします。

preDexLibrariesはインクリメンタルビルドを利用する際のオプションです。Androidのビルドでは、インクリメンタルビルドを行いビルド時間を削減するため、初めてのビルドの際にライブラリのdex化をマルチタスクに行います。しかし、その分初めてのビルドではマシンリソースを大量に必要とする側面もあります。CI環境ではインクリメンタルビルドを必要としないので、無効にしてしまいます。

エミュレータに接続できなくなる問題

エミュレータで実行するユニットテストを利用している場合、エミュレータへ接続する必要がありますが、この際にタイムアウトが発生しビルドが失敗することがあります。そこで、環境変数の設定を行って対応します。

machine:
    java:
        version: oraclejdk8
    environment:
        ADB_INSTALL_TIMEOUT: 100 

ADB_INSTALL_TIMEOUTエミュレータに接続する際の待ち時間を指定できます。1

また、ユニットテストエミュレータで実行をするよりも可能な限りJVMで実行をした方が高速です。デバイスでは無いという制約がありますので、導入の際はお気をつけを。

その辺りの内容については、次の記事が参考になると思います。

まとめ

CircleCIを利用した継続的インテグレーション実現の際のTipsを紹介しました。クラウドサービスは便利な反面、制約があることも事実です。これらの特性を知って、適した場で活用をしていきたいですね。

宣伝

feather for Androidは開発を支援していただける方を募集しています!よろしくお願いします。

--- 1. この方法はCircleCIのサポートへの問い合わせの結果得られた方法ですが、AndroidやCircleCIのドキュメントには記載されていないようでした。 ↩