先日、無事に(?)Rocket.Chat.Androidのコミッタになりました。(プロジェクト名はLily)
ということで、「自分の環境だけでビルドができればいいや」みたいな考えは捨て、CircleCIでビルドできるようにしました。
Rocket.Chatチームから要望があったのでFabric betaでのアプリ配布もふくめて対応をしたのですが、案外ハマリポイントが多かったので、共有のため記事を残しておきたいと思います。
方針
- circle.yml を作らない、なるべくCircleCIのProject Settingsで頑張る
- Android StudioでもCIでも使えるように、環境変数の依存性は少なく
- Fabricプラグインは邪魔くさいので使わない
CIでビルドを通すために…
JAVA_HOMEの設定
Rocket.Chat.Android.Lilyでは、retrolambdaをつかっているためか、Java 8じゃないとビルドが通りません。
Circle CIの環境はデフォルトだとJava7が設定されているので、ビルドにコケます。
環境変数のところで
NAME | VALUE
----------+---------------------
JAVA_HOME |/usr/lib/jvm/jdk1.8.0
と設定します。
ANDROID_HOMEの設定・・・は不要!
CIがデフォルトで入れてくれるらしい。
git submodule の設定、local.propertiesのセット
Travis CIだったら勝手に git submodule init && git submodule update
ってやってくれるんですが、CircleCIではやってくれません。
あと、local.propertiesにsdk.dir
ってのを定義してないとビルドが通りません。
Pre-dependency commandsのところに
git submodule init && git submodule update
echo "sdk.dir="$ANDROID_HOME > local.properties
と設定します。
ビルドコマンドに注意
Circle CIは、メモリ使用が4GBこえるとプロセス強制終了される、という動作仕様があり、
./gradlew assembleDebug
だと、
> Building 93% > :app:preDexDebug
> Building 93% > :app:preDexDebug./gradlew assembleDebug --info --stacktrace died unexpectedly
みたいなかんじで突然死を食らわされることがあります。
どっかのStackOverfowで紹介されてた(わすれたw)とおり
./gradlew assembleDebug --stacktrace -Pcom.android.build.threadPoolSize=1 -Dorg.gradle.parallel=false -Dorg.gradle.jvmargs="-Xms512m -Xmx2048m" -Dorg.gradle.daemon=false
こんなかんじでビルドコマンドをかけば、強制終了することなくアプリのビルドが完了します。
Fabric SDKの組み込み
リファレンスに載ってはいますが、それなりにやることがあります。
diff --git a/build.gradle b/build.gradle
index 9e8f838..c1d3551 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,20 +3,26 @@
buildscript {
repositories {
jcenter()
+ maven { url 'https://maven.fabric.io/public' }
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.3.0'
+ classpath 'com.android.tools.build:gradle:1.5.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1'
+
+ // The Fabric Gradle plugin uses an open ended version to react
+ // quickly to Android tooling updates
+ classpath 'io.fabric.tools:gradle:1.+'
}
}
allprojects {
repositories {
jcenter()
+ maven { url 'https://maven.fabric.io/public' }
}
}
diff --git a/app/build.gradle b/app/build.gradle
index b979a36..cd0f12f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,17 +1,22 @@
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
apply plugin: 'com.jakewharton.hugo'
+apply plugin: 'io.fabric'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
+ Properties properties = new Properties()
+ properties.load(project.rootProject.file('local.properties').newDataInputStream())
+
defaultConfig {
applicationId "chat.rocket.android"
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
+ manifestPlaceholders = [fabric_api_key:properties.getProperty("FABRIC_API_KEY", System.getenv("FABRIC_API_KEY"))]
}
buildTypes {
release {
@@ -41,4 +46,9 @@ dependencies {
compile 'com.facebook.stetho:stetho:1.2.0'
compile 'com.facebook.stetho:stetho-okhttp:1.2.0'
+
+ // Crashlytics Kit
+ compile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar') {
+ transitive = true
+ }
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d48f872..dae2df4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -32,6 +32,10 @@
android:authorities="chat.rocket.android"
android:name=".content.RocketChatProvider"
android:exported="true"/>
+
+ <meta-data
+ android:name="io.fabric.ApiKey"
+ android:value="${fabric_api_key}" />
</application>
</manifest>
FABRIC_API_KEYのところがちょっと工夫してあって、
- local.properties に
FABRIC_API_KEY=XXXxxxXXXXxxx
の定義があればそれを使う - ↑がなければ、環境変数の
$FABRIC_API_KEY
を使う
という構成にしてます。前者がAndroid Studioでビルド通るようにするため、後者はCircle CIで楽するために、こういう感じにしました。
Fabric SDKの初期化処理を追加
アプリケーションクラスに Fabric.with()
の呼び出しを追加すればよいです。
diff --git a/app/src/main/java/chat/rocket/android/RocketChatApplication.java b/app/src/main/java/chat/rocket/android/RocketChatApplication.java
index d837b0b..62b0961 100644
--- a/app/src/main/java/chat/rocket/android/RocketChatApplication.java
+++ b/app/src/main/java/chat/rocket/android/RocketChatApplication.java
@@ -2,12 +2,15 @@ package chat.rocket.android;
import android.app.Application;
+import com.crashlytics.android.Crashlytics;
+import com.crashlytics.android.core.CrashlyticsCore;
import com.facebook.stetho.Stetho;
import com.facebook.stetho.okhttp.StethoInterceptor;
import com.squareup.picasso.OkHttpDownloader;
import com.squareup.picasso.Picasso;
import chat.rocket.android.api.OkHttpHelper;
+import io.fabric.sdk.android.Fabric;
public class RocketChatApplication extends Application {
@Override
@@ -25,5 +28,8 @@ public class RocketChatApplication extends Application {
Picasso picasso = new Picasso.Builder(this).downloader(new OkHttpDownloader(OkHttpHelper.getClient())).build();
Picasso.setSingletonInstance(picasso);
+
+ CrashlyticsCore core = new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build();
+ Fabric.with(this, new Crashlytics.Builder().core(core).build());
}
}
デバッグ中のクラッシュがバンバン報告されるのは勘弁なので、Crashlyticsをデバッグビルドでは無効化でコメント頂いたのを参考に、DEBUGビルドでは無効になるようにしてます。
Beta用の設定ファイルをつくる
apiSecret=XXXXXXxxxXXXXXXxxxxxxXXXXXXxxxXXXXXXxxxxxx
apiKey=XXXXXXxxxXXXXXXxxxxxx
ローカルでビルドする用には、↑のようなファイルを持っておけばいいだけなんですが、こんな機密情報含んだファイルをGitHubに上げるわけにいきません。
CIでは環境変数にこういう機密情報(?)を設定しておくことができるので、それを利用します
↑のようにFABRIC_API_KEY
とFABRIC_BUILD_SECRET
をあらかじめ入れておいて、
↑のようにそれをechoしてapp/fabric.propertiesに詰め込みます。
β版配布時のリリースノート
Circle CIは、circle.ymlで制限しないかぎりは馬鹿正直に全ブランチの全コミットに対してビルドをしようとするので
- どのブランチをビルドしたものか
- どのコミットを取り込んだものか
くらいはリリースノートで見れないと、わりと困ったことになります。
diff --git a/app/build.gradle b/app/build.gradle
index cd0f12f..bad25e6 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -3,6 +3,12 @@ apply plugin: 'com.neenbedankt.android-apt'
apply plugin: 'com.jakewharton.hugo'
apply plugin: 'io.fabric'
+def getCurrentCommitMessage() {
+ def gitlog = 'git log origin/develop...HEAD --decorate'.execute().text
+ if (gitlog.trim().length()>0) return gitlog
+ return 'git log -n 1 --decorate'.execute().text
+}
+
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
@@ -17,6 +23,8 @@ android {
versionCode 1
versionName "1.0"
manifestPlaceholders = [fabric_api_key:properties.getProperty("FABRIC_API_KEY", System.getenv("FABRIC_API_KEY"))]
+ ext.betaDistributionNotifications=false
+ ext.betaDistributionReleaseNotes=getCurrentCommitMessage()
}
buildTypes {
release {
とりあえず、超適当ですが、 git log --decorate で 「origin/develop〜HEADまでのコミット または 最新の1コミット」をだすようにしてみました。
Beta配布!
こんな感じの Post-test commands を定義して、CIでビルドをかけると・・・
キタ━━━━(゚∀゚)━━━━!! ってなります。