GitHub+Travis CI+supply で Google Play への APK アップロードを自動化する


最近 Android 向けのアプリを開発している中で Google Play への APK アップロードを自動化できないかなと考えやってみました。
iOS 向けアプリであれば [fastlane](https://fastlane.tools) がありますが、Android 向けにも似たようなものがないかなと探してみたら [supply](https://github.com/fastlane/fastlane/tree/master/supply) というツールがありましたのでこちらを使用しました。

実際に自動化がされているサンプルアプリは[こちら](https://github.com/qmihara/hello-world-for-android)になります。

以下は Google Play へ公開している、あるいは公開できる状態の Android アプリが既に用意されていることが前提となっています。

## supply

### インストール

supply は Ruby の gem で配布されているためインストールをします。

    $ gem install supply
    
または bundler を使ってインストールします。

    $ bundle init
    $ vi Gemfile

```ruby:Gemfile
source "https://rubygems.org"
gem 'supply'
```

    $ bundle install --path vendor/bundle

### Google Developers Service Account

Google Play へ APK をアップロードをするには Google Developers Service Account(以下サービスアカウント) が必要となります。
以下の手順で取得できると思います。

- Google Play Developer Console で API の利用を許可する
  - `設定` > `API アクセス`
- `サービスアカウントを作成` をクリックして Google Developers Console へ移動する
- Google Developers Console で `新しい認証情報` をクリックし `サービスアカウント キー` を選択する
  - ![Google Developers Console 認証情報](https://qiita-image-store.s3.amazonaws.com/0/36383/b5fecfd1-2be4-4d40-9893-dc4d30e5320f.png "Google Developers Console 認証情報")
- サービスアカウント名を入れキーのタイプは `p12` を選択し作成する
  - ![Google Developers Console 認証情報](https://qiita-image-store.s3.amazonaws.com/0/36383/548daaf1-f1b9-952c-4390-5b3dfeea7041.png "Google Developers Console 認証情報")
- p12 ファイルがダウンロードされるのでどこかに保存しておく
- Google Play Developer Console に戻り追加されたサービスアカウントの `アクセスを許可` をクリックしリリースマネージャーとしてユーザー追加をする
  - ![Google Play Developer Console サービスアカウント](https://qiita-image-store.s3.amazonaws.com/0/36383/4e287c61-f969-c805-569e-039434889292.png "Google Play Developer Console サービスアカウント")

### やってみる

bundler をお使いの場合は以下のコマンドの前に `bundle exec` をお付け下さい。

    $ supply init

オプションに何も指定していない場合は対話式に p12 ファイルのパスとサービスアカウントのメールアドレス、対象とするアプリのパッケージ名を聞かれますので入力してください。
それぞれコマンドのオプションとしても指定できますので `supply --help` を見てみてください。

    $ supply run

## Google Play へ APK をアップロードするのを自動化してみる

自動化の流れは

1. git のタグを生成し GitHub へ push する
2. Travis CI のデプロイタスクが実行され GitHub Releases が作られる
  - APK が添付されている
3. デプロイ(GitHub Releases 作成)が成功したら Google Play のベータテストへ APK をアップロードする

このような流れとなるようにしてみます。

### .travis.yml

まずは Travis CI でデプロイ処理がされるよう `.travis.yml` を作成します。

```yaml:.travis.yml
language: android
env:
  global:
    - ADB_INSTALL_TIMEOUT=8
    - GRADLE_OPTS="-Xmx2048m -Xms2048m -XX:MaxPermSize=1024m"
    - secure: "XXXXXXXXXXXXX"
git:
  depth: 9999999
android:
  components:
    - tools
    - build-tools-23.0.2
    - android-23
    - sys-img-x86-android-21
    - extra-android-m2repository
    - extra-android-support
    - extra-google-google_play_services
    - extra-google-m2repository
before_install:
  - openssl aes-256-cbc -K $XXXXXXXX -iv $YYYYYYYYYY  -in secrets.tar.enc -out secrets.tar -d
  - tar xvf secrets.tar
  - rvm install 2.0.0
before_script:
  - echo no | android create avd --force -n test -t android-21  --abi armeabi-v7a
  - emulator -avd test -no-skin -no-audio -no-window &
  - android-wait-for-emulator
  - adb shell input keyevent 82 &
  - make setup
script:
  - ./gradlew connectedAndroidTest
notifications:
  email: false
before_deploy:
  - make release.zip
deploy:
  provider: releases
  api_key:
    secure: XXXXXXXXXXXXXXXXXXXX
  file: release.zip
  on:
    repo: your/repository-name
    tags: true
    all_branches: true
after_deploy:
  - make deploy2gp
```

何箇所か補足をします。

### env.global の secure

これはキーストアファイルのパスワードを `travis encrypt` コマンドで暗号化したものです。

    $ travis encrypt STORE_PASSWORD=XXXXXXXXXXXXXXX KEY_PASSWORD=YYYYYYYYYYYYYY
    
ここで暗号化した環境変数は `make setup` の中で行われる `singingConfigRelease.gradle` ファイルを生成する際に使用されます。

### before_install

GitHub リポジトリにはキーストアファイルと p12 ファイルをそのまま置くわけにもいかないので tar でまとめたものを暗号化して管理しています。
それを復号するものになります。

暗号化は以下のようにして行いました。

    $ tar cvf secrets.tar helloworld.jks key.p12
    $ travis encrypt-file secrets.tar

before_install では暗号化したファイルの復号と展開をしています。
`rvm install 2.0.0` は `supply` が ruby 2.0 以上を必要とし、Travis CI の android 用イメージの ruby が 1.9.x だったためです。

### before_deploy

GitHub Releases に添付できるファイルは zip ファイルであるためこのタイミングで添付したいファイルを zip で圧縮しています。

### deploy

`api_key` に指定するのは GitHub の OAuth トークンとなります。トークンはそのままではまずいのでこれも travis コマンドで暗号化します。
なおトークンは GitHub の `Personal settings` > `Personal access tokens` より発行しておいてください。

    $ travis encrypt XXXXXXXXXXXXXXXXXXX

GitHub Releases のデプロイについては[公式ドキュメント](https://docs.travis-ci.com/user/deployment/releases)にも目を通しておくと良いです。

### after_deploy

ようやくここで Google Play へ APK をアップロードします。
make タスクの中身は以下の通りです。

```Makefile
deploy2gp:
        bundle install --path .bundle
        bundle exec supply init -k $(KEY) -p $(PACKAGE_NAME)
        bundle exec supply -k $(KEY) -p $(PACKAGE_NAME) -b app/build/outputs/apk/app-release.apk --track beta --skip_upload_metadata --skip_upload_images --skip_upload_screenshots
```

`KEY` と `PACKAGE_NAME` は適宜変更してください。
コマンドのオプションでサービスアカウントの指定がされていませんが、サービスアカウントは Travis CI の設定画面で環境変数(`SUPPLY_ISSUER`)としてセットしています。
supply のヘルプを見ればわかりますが、環境変数をセットすることでオプションの指定を省略することが可能です。

今回私は APK をベータテストとしてアップロードしたかっただけなのでそれ以外はスキップするようにしています。
必要に応じてオプションを外したり `--track` オプションの値を変えて試してみてください。

## まとめ

思ったよりも簡単に実現することができました。
Android(Google) はこの辺りの API が用意されている点が良いですね。
この記事をご覧になった方はぜひ試してみてください。