2015-11-30
関西モバイルアプリ研究会 #8
Android アプリ
Jenkins でビルドして
GitHub に “リリース” を作る
id:nobuoka
株式会社はてな
自己紹介と前置き
● id:nobuoka
 Android アプリ開発
 Windows アプリ開発
 サーバーサイド (Scala)
● 今日 : CI・ビルド周りの話
 最終的な目的 : GitHub にリリースを作る
 ビルドシステム周りの基本的な話
やりたいこと
● Jenkins 上でビルドして GitHub に “リリー
ス” を作って APK ファイルをアップロード
 Gradle 上で APK ファイルを扱う
なんで?
● リリースフローを自動化したい → Jenkins
 手元ビルドだとクラッシュする APK ができる
ことがある
● 過去のリリースを振り返りやすくする →
GitHub のリリース機能
 過去バージョンでのリリース内容を見たり、実
際にその時の APK を使ったりしやすくしたい
Android のビルドシステム : Gradle
● Android アプリの標準のビルドシステム
 Android Studio でサポート
● Java 界隈のビルドシステム
● Groovy による DSL
● Android Gradle Plugin により Android ア
プリをビルド可能に
Build Variants
● Android Gradle plugin の機能
● Product flavors × Build types
● ビルドに種類があって名前がついてるという話
 今回のスライドで重要なのはこれだけ
 “productionRelease” とか
“previewDebug とか”
APK パッケージへの署名
● パスワードは Gradle プロパティにする
android {
signingConfigs {
release {
storeFile file("your.key")
storePassword project.getProperties().get("storePassword")
keyAlias "yourAlias"
keyPassword project.getProperties().get("keyPassword")
}
}
buildTypes {
release {
signingConfig signingConfigs.release
Gradle 上で APK パッケージを扱う
● android.applicationVariants から
 find で指定の build variant を取得
 → Assemble タスクや出力ファイルの情報
// 別 project からでも扱える。
Project appProject = project(':app')
def targetVariant = appProject.android.applicationVariants.
find { it.name == "productionRelease" }
def assembleTask = targetVariant.assemble
def outputs = targetVariant.outputs
Assemble タスクに依存するタスクの定義
● APK ファイルを操作するなら assemble タス
クに依存させる
task putRelease, dependsOn: assembleTask << {
String versionName = targetVariant.versionName
String versionCode = targetVariant.versionCode
String title = "Version ${versionName} (${versionCode})"
MyGheClient gheClient = new MyGheClient()
gheClient.setOAuth2Token(gheOAuth2Token)
// ここでリリースの作成や APK ファイルのアップロードをする。
// (後述)
}
GitHub に “リリース” を作成する機能
● GitHub Java API を拡張 (Groovy は楽)
buildscript {
repositories { mavenCentral() }
dependencies {
classpath 'org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5' }}
class MyGheClient extends GitHubClient {
public MyGheClient() { super("ghe.example.com") }
Map<String, Object> createGheRelease(String name, String versionName) {
def release = [
"tag_name": "v" + versionName,
"target_commitish": "master", "name": name,
"body": "Description of the release",
"draft": true, "prerelease": false
]
(Map<String, Object>) post("/repos/{team}/{repo}/releases", release, Map)
}
}
“リリース” 作成実行
MyGheClient gheClient = new MyGheClient()
gheClient.setOAuth2Token(gheOAuth2Token)
def release = gheClient.createGheRelease(title, versionName)
● リリース用のファイルアップロードも似たよう
な感じで実装しよう!
Jenkins で実行
export ANDROID_HOME=/Users/steve/.jenkins/tools/android-sdk
./gradlew 
-PstorePassword="${STORE_PASSWORD}" 
-PkeyPassword="${KEY_PASSWORD}" 
-PgheOAuth2Token="${GHE_OAUTH_2_TOKEN}" 
clean putRelease
おわり
● 署名した APK ファイルを作るのは Android
Gradle plugin の機能でできる
 パスワードは Gradle プロパティとして渡す
● Assemble タスクに依存したアップロードタ
スクを定義して Jenkins で実行
 Build variants の扱いが特殊
 Groovy なので API 叩くの楽

Android アプリを Jenkins でビルドして GitHub に “リリース” を作る

  • 1.
    2015-11-30 関西モバイルアプリ研究会 #8 Android アプリ Jenkinsでビルドして GitHub に “リリース” を作る id:nobuoka 株式会社はてな
  • 2.
    自己紹介と前置き ● id:nobuoka  Androidアプリ開発  Windows アプリ開発  サーバーサイド (Scala) ● 今日 : CI・ビルド周りの話  最終的な目的 : GitHub にリリースを作る  ビルドシステム周りの基本的な話
  • 3.
    やりたいこと ● Jenkins 上でビルドしてGitHub に “リリー ス” を作って APK ファイルをアップロード  Gradle 上で APK ファイルを扱う
  • 4.
    なんで? ● リリースフローを自動化したい →Jenkins  手元ビルドだとクラッシュする APK ができる ことがある ● 過去のリリースを振り返りやすくする → GitHub のリリース機能  過去バージョンでのリリース内容を見たり、実 際にその時の APK を使ったりしやすくしたい
  • 5.
    Android のビルドシステム :Gradle ● Android アプリの標準のビルドシステム  Android Studio でサポート ● Java 界隈のビルドシステム ● Groovy による DSL ● Android Gradle Plugin により Android ア プリをビルド可能に
  • 6.
    Build Variants ● AndroidGradle plugin の機能 ● Product flavors × Build types ● ビルドに種類があって名前がついてるという話  今回のスライドで重要なのはこれだけ  “productionRelease” とか “previewDebug とか”
  • 7.
    APK パッケージへの署名 ● パスワードはGradle プロパティにする android { signingConfigs { release { storeFile file("your.key") storePassword project.getProperties().get("storePassword") keyAlias "yourAlias" keyPassword project.getProperties().get("keyPassword") } } buildTypes { release { signingConfig signingConfigs.release
  • 8.
    Gradle 上で APKパッケージを扱う ● android.applicationVariants から  find で指定の build variant を取得  → Assemble タスクや出力ファイルの情報 // 別 project からでも扱える。 Project appProject = project(':app') def targetVariant = appProject.android.applicationVariants. find { it.name == "productionRelease" } def assembleTask = targetVariant.assemble def outputs = targetVariant.outputs
  • 9.
    Assemble タスクに依存するタスクの定義 ● APKファイルを操作するなら assemble タス クに依存させる task putRelease, dependsOn: assembleTask << { String versionName = targetVariant.versionName String versionCode = targetVariant.versionCode String title = "Version ${versionName} (${versionCode})" MyGheClient gheClient = new MyGheClient() gheClient.setOAuth2Token(gheOAuth2Token) // ここでリリースの作成や APK ファイルのアップロードをする。 // (後述) }
  • 10.
    GitHub に “リリース”を作成する機能 ● GitHub Java API を拡張 (Groovy は楽) buildscript { repositories { mavenCentral() } dependencies { classpath 'org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5' }} class MyGheClient extends GitHubClient { public MyGheClient() { super("ghe.example.com") } Map<String, Object> createGheRelease(String name, String versionName) { def release = [ "tag_name": "v" + versionName, "target_commitish": "master", "name": name, "body": "Description of the release", "draft": true, "prerelease": false ] (Map<String, Object>) post("/repos/{team}/{repo}/releases", release, Map) } }
  • 11.
    “リリース” 作成実行 MyGheClient gheClient= new MyGheClient() gheClient.setOAuth2Token(gheOAuth2Token) def release = gheClient.createGheRelease(title, versionName) ● リリース用のファイルアップロードも似たよう な感じで実装しよう!
  • 12.
    Jenkins で実行 export ANDROID_HOME=/Users/steve/.jenkins/tools/android-sdk ./gradlew -PstorePassword="${STORE_PASSWORD}" -PkeyPassword="${KEY_PASSWORD}" -PgheOAuth2Token="${GHE_OAUTH_2_TOKEN}" clean putRelease
  • 13.
    おわり ● 署名した APKファイルを作るのは Android Gradle plugin の機能でできる  パスワードは Gradle プロパティとして渡す ● Assemble タスクに依存したアップロードタ スクを定義して Jenkins で実行  Build variants の扱いが特殊  Groovy なので API 叩くの楽