Google Playへのデプロイツールを検証してみた。

# はじめに

[モバイルDevOps](http://qiita.com/advent-calendar/2015/mobile-devops)でGoogle Playへのアップロード手法について誰も書いてなかったので勢い余って参加しました。今さらなネタかもしれませんが書きたいから書きます。

# やらないこと

[Publisher API](https://developers.google.com/android-publisher/)を使っているツールの紹介はしますが、Publisher API自体の紹介はしません。

また、publisher api利用時に必要な設定などの説明もしません。

わからない人はクックパッド開発者ブログの[Android Publisherによるストア管理の自動化](http://techlife.cookpad.com/entry/2014/09/10/175601)を確認して下さい。(いつもお世話になっています。)

# 注意事項

この記事は個人的な主観のもと検証しており、これを使えば勝てる！と思わないでください。

紹介したものでセキュリティ上問題のあるツールなどありましたら、ご指摘下さい。

# 機能

以下の機能が自分には必要でした。

## 必須機能

* Google Playへapkをアップロード出来る。(できれば、alphaやbetaで上げ、問題ないことを確認した後、productionへ切り替えたい。)
* 基本Macだが、Windowsでも利用出来る。
* 作業者が複数人になり得るため、準備や作業が簡単。

## あればBetter

* Google Playへ説明文・スクショなどを変更出来る。

## 特に気にしない機能

* OBBファイルのアップロード
* ゲーム関連の機能

# 最終的に検証したツール

* [gradle-play-publisher](https://github.com/Triple-T/gradle-play-publisher) - Gradle Plugin
* [Google Play Android Publisher Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Google+Play+Android+Publisher+Plugin) - Jenkins Plugin
* [supply](https://github.com/fastlane/supply) - Android版fastlane

選定基準は、開発がActiveであることとStar数が多く信頼性が高いことです。

## 最終候補に残らなかったツール

他にも色々検証しましたが、機能的に重複していたり、特筆するようなものがなかったりしていたので、検証しなかったツールもあります。

* [Android Maven Plugin](http://simpligility.github.io/android-maven-plugin/playstore-publisher.html) - Mavenプラグイン(すでにGradleなしでは生きられない体に・・・)
* その他gradleのplay publisherプラグイン。(何個もありますが、gradle-play-publisherが一番高機能＋開発が停止している。)

# [gradle-play-publisher](https://github.com/Triple-T/gradle-play-publisher)

Android gradle pluginが持っていない機能を補完しようとして作られたgraldeプラグイン。

```bash
./gradlew publishApkRelease
```

このコマンドでReleaseのbuild typeのapkを生成し、アップロードできます。
flavorの選択も可能で、タスク名からリリースするflavorを選択出来ます。もしfreeというflavorがあるなら、以下のコマンドが実行出来ます。

```bash
./gradlew publishApkReleaseFree
```

## 特徴

* gradleで完結している
* ビルド出来る環境であれば、どこからでもアップロードが出来る
* Google Play内の情報の更新も可能。
* alpha、beta、rollout、productionへのアップロードが出来る。
* gradleが良きに計らってくれるので導入が楽。

## 感想

とりあえず自動化の一歩目へということであればこのツールで間違いないです。

`./gradlew bootstrapReleasePlayResources`すれば、現在のGoogle Playに掲載されている説明文などをダウンロード出来ます。ただし、スクリーンショットはこのライブラリが依存しているgoogle-api-clientが対応していないため、対応していません。

すでに作成したapkをアップロードする機能はないため、アップロード前に生成したapkを確認したいなどの場合はこのツールは避けるべきです。Google Playの仕様上、alpha/beta/production問わずアップロードしてしまったapkに問題がある場合はversionCodeを上げたapkでない限り、更新出来ないためです。

## サンプルコード

```groovy:build.gradle
buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0'
        classpath 'com.github.triplet.gradle:play-publisher:1.1.4'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
```

```groovy:app/build.gradle
apply plugin: 'com.android.application'
apply plugin: 'com.github.triplet.play'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "shiraji.github.com.myapplication"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 2
        versionName "1.0.1"
    }

    signingConfigs {
        release {
            storeFile file("keystore.jks")
            storePassword "STORE_PASSWORD"
            keyAlias "ALIAS"
            keyPassword "KEY_PASSWORD"
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
}

play {
    jsonFile = file('keys.json')
}
```

P12ファイルの場合は

```groovy:app/build.gradle
play {
    serviceAccountEmail = 'your-service-account-email'
    pk12File = file('key.p12')
}
```

## 問題点

* gradle-play-publisherは最近開発が滞り気味

当初の目的に外れた機能の追加はあまりしたくないとのこと[^1]で、新規機能の提案をしても今のところレスポンスがありません[^2][^3]。今後どのように発展していくのか注視していく必要があります。
(最近私がcontributeしているので、forkして別途開発してもいいよという許可は得ています、もし必要とあれば、私が開発していきますが、今のところ、別ツールも出てきており、モチベーションがかなり低いです。)

# [Google Play Android Publisher Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Google+Play+Android+Publisher+Plugin)

我らDevOps担当者の最強の執事[Jenkins](https://jenkins-ci.org/)おじさんのプラグイン。

特にこれ以上説明出来る余地がない・・・

## 特徴

* 設定がGUI
* 安定のJenkins
* ビルドフロー(ジョブ)と組み合わせることが出来る
* apk単体でアップロード出来る(未検証)

## 問題点

* Jenkinsがないと使えない
* Jenkinsが動かないような状態に陥った時どうするのかバックアッププランが別途必要(手動？)
* 説明文・スクリーンショットなどの更新ができない

# [supply](https://github.com/fastlane/supply)

fastlaneの派生ツールとして作られているsupply。gemとして公開されています。

## インストール手順

```bash
sudo gem install supply
```

## アップロード手順

最初に情報を同期するため、`supply init`コマンドを実行します。

```
% supply init
[10:25:13]: To not be asked about this value, you can specify it using 'key'
The p12 File used to authenticate with Google: app/key.p12 # p12ファイルのパスを入力
[10:25:21]: To not be asked about this value, you can specify it using 'issuer'
The issuer of the p12 file (email address of the service account): xxxxxxxxxxx@developer.gserviceaccount.com # service accountのメールアドレスを入力
[10:25:35]: Fetching a new access token from Google...
[10:25:36]: To not be asked about this value, you can specify it using 'package_name'
The package name of the Application to modify: com.your.package # パッケージ名を入力
[10:28:23]: Writing to metadata/ja-JP/title.txt...
[10:28:23]: Writing to metadata/ja-JP/short_description.txt...
[10:28:23]: Writing to metadata/ja-JP/full_description.txt...
[10:28:23]: Writing to metadata/ja-JP/video.txt...
[10:28:23]: Due to the limit of the Google Play API `supply` can't download your existing screenshots...
[10:28:23]: Downloading icon for ja-JP...
[10:28:25]: Downloading promoGraphic for ja-JP...
[10:28:25]: Downloading tvBanner for ja-JP...
[10:28:27]: Successfully stored metadata in 'metadata'
```

このコマンドを実行することで、Google Play上にある情報が`metadata`directoryにダウンロードされます。

```bash
metadata/
└── ja-JP
    ├── full_description.txt
    ├── images
    │   ├── icon.png
    │   ├── phoneScreenshots
    │   ├── sevenInchScreenshots
    │   ├── tenInchScreenshots
    │   ├── tvScreenshots
    │   └── wearScreenshots
    ├── short_description.txt
    ├── title.txt
    └── video.txt
```

こちらもスクリーンショットのダウンロードはまだのようです。

アップロードコマンド`supply run`を実行する

```
% supply run
[10:43:41]: To not be asked about this value, you can specify it using 'package_name'
The package name of the Application to modify: com.your.package # パッケージ名を入力
[10:43:50]: To not be asked about this value, you can specify it using 'key'
The p12 File used to authenticate with Google: app/key.p12 # p12ファイルのパスを入力
[10:44:05]: To not be asked about this value, you can specify it using 'issuer'
The issuer of the p12 file (email address of the service account): xxxxxxxxxxx@developer.gserviceaccount.com # service accountのメールアドレスを入力

+---------------+---------------------------------------+
|                Summary for sigh 0.2.2                 |
+---------------+---------------------------------------+
| package_name  | com.your.package                      |
| track         | production                            |
| rollout       | 1.0                                   |
| metadata_path | ./metadata                            |
| key           | app/key.p12                           |
| apk           | app/build/outputs/apk/app-Release.apk |
+---------------+---------------------------------------+

[10:44:13]: Fetching a new access token from Google...
[10:44:15]: Loading metadata for language 'ja-JP'...
[10:44:16]: Uploading image file ./metadata/ja-JP/images/icon.png...
[10:44:18]: Preparing apk at path 'app/build/outputs/apk/app-Release.apk' for upload...
[10:44:26]: Uploading all changes to Google Play...
[10:44:31]: Successfully finished the upload to Google Play
```

## 特徴

supplyは現在開発が活発で、今後の伸びに期待です。

コマンド実行時に毎回入力するのはダルいので、オプション指定することで回避します。
`supply --help`で確認すればわかりますがv0.2.2では以下のオプションがあります。

```bash
    -p, --package_name STRING パッケージ名
    -a, --track STRING   トラック名: production, beta, alpha or rollout
    -r, --rollout STRING 公開割合
    -m, --metadata_path STRING メタ情報が含まれているdirectoryの指定
    -k, --key STRING     p12ファイルの指定
    -i, --issuer STRING  issuer情報の指定。(service accountのメールアドレス)
    -b, --apk STRING     apkのパスを指定
    -h, --help           ヘルプ表示
    -v, --version        バージョン表示
```

gradle-publisher-pluginにない、存在しているapkのアップロードが出来ます。
トラックの切り替えなどはまだ出来ないようです。

## 問題点

* gemなのでWindows環境では苦しい
* apk作成はgradleなど別ツールを使う必要がある
 
# まとめ

この検証した3ツールはどれを選んでも特に問題ないです。
個人的な意見ですが、使ってみた印象から

* ruby環境が揃っているならsupply
* Jenkins環境で対応したいならGoogle Play Android Publisher Plugin
* gradleで完結させたいならgradle-play-publisher
* 説明文・写真などの管理がしたいなら、supply/gradle-play-publisher

で、自分は、JenkinsでCIぐるぐるしたいけど、説明文・写真を管理したくて、かつ、JenkinsサーバのJVMで完結したかったので、gradle-publisher-pluginを選択しました(そもそも当時supplyなかった。)。運用して、1年弱経ってますが、特に今まで問題ありません。Jenkins環境がなかった時は各自開発者がデプロイ出来たので、デプロイ職人を作る必要がなかったのも良かった点です。

# 注釈

[^1]: https://github.com/Triple-T/gradle-play-publisher/issues/109#issuecomment-157172738
[^2]: https://github.com/Triple-T/gradle-play-publisher/issues/108
[^3]: https://github.com/Triple-T/gradle-play-publisher/issues/110