AndroidアプリにCircleCI2.0を導入してDeployGateへ自動アップロード

Androidアプリ開発プロセスの効率化のためCIの導入を検討しました。
CI環境の選択肢はいくつか中で、「自社のサーバサイドプロジェクトで導入済みで追加コストがかからない」「社内外での知見が現時点では最も多そう」「移行して早くなったという話がネット上でちらほら」といった理由から、CircleCI2.0を導入することに決めました。

# CircleCIの導入手順
まず今回の内容の前提として、GitHubでプロジェクトを管理していることと、DeployGateのアカウントが必要となります。あとは以下の流れでCircleCIをとAndroidアプリプロジェクトを連携させることができます。

1. [CircleCI](https://circleci.com/)にGitHubアカウントでサインイン。
2. 表示される画面の左メニューから「ADD PROJECTS」を選択し、一覧表示された中の対象プロジェクトの「Set Up Project」を選択。
3. 次の画面に表示される選択肢の中からGradle(Java)を選択。
4. 表示される手順を参考に、Androidプロジェクトのルートに.cicleciフォルダとconfig.ymlファイルを作成しgitHubにプッシュ。
5. 画面上のStartBuildingボタンをクリックしてセットアップ完了。

<img width="1344" alt="スクリーンショット 2019-09-18 16.09.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315759/f0a80274-cdda-9cd2-df90-e6814eb12081.png">


# config.ymlの記述
CIの内容はconfig.ymlに記述します。出来上がりはこんな感じです（DeployGateの箇所は環境に合わせて書き換えが必要）。主な項目の説明は後述します。

``` config.yml

anchors:
  android_docker: &android_docker
    docker:
      - image: circleci/android:api-29
  android_enviroment: &android_enviroment
    enviroment:
      JVM_OPS: -Xmx3200m
  steps:
    - cashe_key: &cashe_key jars-{{ checksum "build.gradle" }}-{{ checksum  "app/build.gradle" }}

version: 2
jobs:
  build:
    <<: *android_docker
    <<: *android_enviroment
    steps:
      - checkout
      - restore_cache:
          key: *cashe_key
      - run:
          name: Download dependencies
          command: ./gradlew androidDependencies
      - save_cache:
          paths:
            - ~/.gradle
          key: *cashe_key
      - run:
          name: Build APK
          command: ./gradlew assembleDebug
      - persist_to_workspace:
          root: .
          paths:
            - .
  lint:
    <<: *android_docker
    <<: *android_enviroment
    steps:
      - attach_workspace:
          at: .
      - run:
          name: Check lint
          command: ./gradlew ktlintCheck
      - store_artifacts:
          path: app/build/reports
          destination: reports
  deploy:
    <<: *android_docker
    <<: *android_enviroment
    steps:
      - attach_workspace:
          at: .
      - run:
          name: Upload DeployGate
          command: curl -F "token={TOKEN}" -F "file=@{FILE}" -F "message={MESSAGE}" https://deploygate.com/api/users/{NAME}/apps

workflows:
  version: 2
  build_deploy:
    jobs:
      - build
      - lint:
          requires:
            - build
      - deploy:
          requires:
            - build
            - lint
          filters:
            branches:
              only: develop
```


## anchors
複数の箇所で使いまわすものはYAMLのアンカー&エイリアスの機能を使い、anchors以下に定義しています。&name（アンカー）で宣言しておくと、*name（エイリアス）で参照できます。

dockerにはCircleCIが提供する[Androidのdocker image](https://github.com/CircleCI-Public/circleci-dockerfiles/tree/master/android/images)を利用しています。利用するバージョンはcompileSdkVersionに合ったものにしましょう。


## jobs
実際に実行されるタスクはjobs以下に記述します。ここではbuild、lint、deployの三つのジョブを定義しています。

#### persist_to_workspase/attach_workspase
persist_to_workspaseで指定したディレクトリを、attach_workspaseしてジョブ間で共有できます。ここではbuildを実行したディレクトリ丸ごとを、lint、deployのジョブでも引き継いで利用するようにしています。

#### store_artifacts
指定したパスにテスト結果の成果物を保存することができます。保存した成果物はCircleCIの画面上で確認しダウンロードできます。

<img width="1325" alt="スクリーンショット 2019-09-18 17.19.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315759/79c2fb2e-4fc9-442c-bded-a58989914886.png">

#### DeployGateへのアップロード
アップロードには[DeployGateのAPI](https://docs.deploygate.com/reference)を利用します。
{TOKEN}にはDeployGateのプロフィール画面にあるAPIkeyを、{FILE}にはapkの出力先のパスを、{MESSAGE}には任意のメッセージを、{NAME}にはDeployGateのユーザー名を記載します。

## workflows
ジョブの実行計画を定義しています。ジョブをはしらせる順番を同期させたり並列にしたり、フィルターを設定したりできます。

#### requires
指定したジョブが完了してから実行するように設定できます。ここではbuild -> lint -> deployと順番にはしるようにしています。

#### filters
ジョブが実行される条件を設定できます。ここではdevelopブランチへのプッシュがあった時のみDeployGateにアップロードするようにしています。

# おわりに
ゆくゆくはテストをはしらせたり、slackへ通知させたり、GitHubのプルリク上に自動でコメントしたりしたい。