Circle CIでJavaを使ってビルドする
ここ何日か Circle CI を使ってみて何となく分かってきた事をまとめておきます。
完成した circle.yml だけ欲しい方はこちらをどうぞ。
checkout:
post:
- chmod +x ./gradlew
machine:
timezone: Asia/Tokyo
environment:
GRADLE_OPTS: -Xmx4G -Dorg.gradle.daemon=true
JAVA_HOME: /usr/lib/jvm/java-8-oracle
post:
- sudo service mysql stop
- sudo service postgresql stop
dependencies:
pre:
- sudo apt-get install software-properties-common
- sudo add-apt-repository -y ppa:webupd8team/java
- sudo apt-get update
- echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections
- sudo apt-get install oracle-java8-installer
override:
- ./gradlew -v
- ./gradlew testClasses
test:
override:
- ./gradlew --full-stacktrace check
シェルスクリプトの実行権限
Windows を使っているとつい忘れがちですけども、シェルスクリプトに実行権限を付けるのを忘れないようにしましょう。
checkout:
post:
- chmod +x ./gradlew
タイムゾーンを自分達が作業しているものに変えよう
ログの中の時間が分かり易いようにタイムゾーンをデフォルト値から変更しておきましょう。
僕は概ね日本時間の夜中に活動しているのでAsia/Tokyo
に変更しています。
CircleCI は RDB は二つの RDB が起動している
mysql と postgresql という二つの RDB が標準で動作しています。デフォルトで使えるメモリは 4GBなので、必要のないものは止めてしまいましょう。
machine:
post:
- sudo service mysql stop
- sudo service postgresql stop
尚、サポートに連絡すればメモリは増やして貰えるようです。
CircleCI は言語ランタイムのバージョンが固定されている
Circle CI では、machine
設定でプログラミング言語のバージョンを指定できるようになっていますが、細かいリビジョンを指定できません。
例えば、Oracle JDK 8
を利用する場合、以下の ように設定します。
machine:
java:
version: oraclejdk8
2015/11/30 現在、この指定で動作するのは1.8.0_40
です。これがリリースされたのは 2015/03/03 なのでちょっと古すぎるように感じます。
最新の Java を使ってビルドする
Circle CI 上で最新の Java を使ってビルドする方法について模索してみましょう。
方法としては 2 種類あります。
- Docker を使って最新の Java が入ったイメージをビルドして使う方法
- apt-get コマンドで最新の Java をインストールする方法
今回は apt-get コマンドで Java をインストールしてみましょう。Circle CI でビルドする際に動作する OS は、公式のマニュアルによるとUbuntu 12.04
です。
これにコマンドだけで Java 8 をインストールする場合、以下のように実行します。
sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:webupd8team/java
sudo apt-get update
echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections
sudo apt-get install oracle-java8-installer
まず、software-properties-common
をインストールして、add-apt-repository
コマンドを使えるようにしています。
次に、add-apt-repository
コマンドで Oracle Java 8 のメタデータが格納されているppa:webupd8team/java
リポジトリを追加します。
次の、 apt-get update
はパッケージのメタデータをローカルに取込んでいます。
次は、少し長めのコマンドになっています。Circle CI 上では対話的にパッケージをインストールすることは出来ませんが、Oracle Java のインストーラはかなり細かくウィザードに回答しなければなりません。そこで、debconf-utils のdebconf-set-selections
を使ってウィザードに自動回答するようにしています。
最後に、oracle-java8-installer
をインストールしています。これによってインストールされた Java は、/usr/lib/jvm/java-8-oracle
というパスに格納されています。
Gradle や Maven から Java を使う際には、JAVA_HOME
環境変数の書き換えが必要になりますので忘れないようにしましょう。以下のように記述します。
machine:
environment:
JAVA_HOME: /usr/lib/jvm/java-8-oracle
Gradle Daemon を使おう
Gradle の起動時間は決して速いとは言えませんので、起動時間を少しでも短縮するために Gradle Daemon を使いましょう。
gradlew コマンドのオプションとして--daemon
を付けても良いのですが、--daemon
が有効なものとそうでないものを切り分けるのが面倒なので、 -Dorg.gradle.daemon=true
を常に起動オプションとして指定してしまいましょう。
その場合、環境変数GRADLE_OPTS
が使えます。
Circle CI で環境変数を指定するにはmachine
設定のenvironment
セクションを使って以下のように記述します。
machine:
environment:
GRADLE_OPTS: -Xmx4G -Dorg.gradle.daemon=true
ライブラリの依存性解決は dependencies フェイズ内でやろう
Gradle を使ってビルドする場合、必要になるギリギリまで依存ライブラリのダウンロードが行われません。
Circle CI では、database フェイズ中にダウンロードキャッシュの保存を行うため test フェイズ中に依存ライブラリのダウンロードを行ってしまうと上手く保存されず、ビルドのたびに依存ライブラリをダウンロード してしまいます。
これに対応するために、dependencies
設定内でテストコードのビルドまではやってしまいましょう。Gradle でテストコードのビルド及びテストに必要なリソースのコピーを行う標準のタスクはtestClasses
でしたね。
つまり、以下のようになります。
dependencies:
override:
- ./gradlew -v
- ./gradlew testClasses
ここでは、Gradle や Java のバージョンをまとめて確認できるように、-v
を付けて Gradle をとりあえず起動しています。以下のような出力が得られますので、上手くビルド出来ない時の手掛かりにな ります。
------------------------------------------------------------
Gradle 2.9
------------------------------------------------------------
Build time: 2015-11-17 07:02:17 UTC
Build number: none
Revision: b463d7980c40d44c4657dc80025275b84a29e31f
Groovy: 2.4.4
Ant: Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM: 1.8.0_66 (Oracle Corporation 25.66-b17)
OS: Linux 3.14.28-031428-generic amd64
テストだけでなく静的解析の類も実行しよう
CI サーバでユニットテストだけ実行するのでは物足りませんので、check タスクを実行しましょう。その際に、--full-stacktrace
オプションを追加しておくと失敗した際に原因が分かり易くなります。
test:
override:
- ./gradlew --full-stacktrace check
以上です。
より良い方法をご存じの方は@ryushiまでメンションを下さい。