
起
はじめまして、GameWithのエンジニアのソンです。 今回はGameWith本体アプリのAndroidプロジェクトにCIを導入した話をします。
まずはどうしてCIを導入しようと思うのを説明させていただきます。 PullRequestを作る時に、人為的なミスでそもそもBuildやUnitTestが通らないことたまにあります。この問題はCIの導入でReviewする前に必要ない人力が省けます。
また、複数人のプロジェクトにはある程度のCode Styleを制限しないとCodeの可読性がすぐ悪くなります。
ゴール

- CircleCI 2を導入
- UnitTestを行う
- APKをビルド
- Danger経由で、GithubにKtlintからのエラーメッセージをコメント
3.で生成したAPKをDeployGateにアップロード
Circle CI 2を導入
社内のGithubアカウントは既にCircleCiと連携してますので、新しいプロジェクトに導入するのは難しくないです。
導入したいプロジェクトの「Set Up Project」を押すと、そこには簡単なconfig.ymlの例文があります。チュートリアルに沿ってプロジェクトに配置すると、最初の構築が終わります。次はconfig.ymlにどんどんJob(実行させたいタスク)を追加する感じです。
一応CircleCIは複数のJobを同時に実行することができるので、ここはUnitTest、Build、Ktlintと三つのJobに分けまして、平行で走らせます。
また、各JobでGradleの初期化を行うと時間がかかりますので、CircleCiのworkspaceを使って、初期化したものを各Jobに提供してます。
UnitTestを行う
unitTest:
<<: *defaults
steps:
- attach_workspace:
at: ~/
- run:
name: Run UnitTest
command: ./gradlew testProductDebugUnitTest
- store_artifacts:
path: app/build/reports
destination: reports
- store_test_results:
path: app/build/test-results
store_artifactsとstore_test_resultsはテスト項目の結果を保存するMethodです。Jobが実行した後にArtifactsで見れます。

APKをビルド
normalBuild:
<<: *defaults
steps:
- attach_workspace:
at: ~/
- run:
name: Build
command: ./gradlew assembleQualityAssuranceDebug
- persist_to_workspace:
root: ~/
paths: code/app/build/outputs/apk/qualityAssurance/debug/
最後のpersist_to_workspaceは生成したAPKをDeployGateにアップロードできるように、workspaceに保留する。
ktlintの実行
ktlint:
<<: *defaults
steps:
- attach_workspace:
at: ~/
- run: ./gradlew ktlintProductReleaseCheck
- persist_to_workspace:
root: ~/
paths: code/app/build/reports/ktlint/
ktlintはGradle pluginsのKtlint Gradleを使ってます
(https://github.com/JLLeitschuh/ktlint-gradle)
OutputはCHECKSTYLEに設定する、この後はDangerから読み込んでGithubにコメントする。
dangerの実行
danger:
working_directory: ~/code
environment:
- LANG: C.UTF-8
docker:
- image: ruby:2.1
steps:
- attach_workspace:
at: ~/
- run: gem update --system 2.4.8
- run: gem install bundler
- restore_cache:
key: gem-cache-{{ .Branch }}-{{ checksum "Gemfile" }}
- run: bundle install --path vendor/bundle
- save_cache:
key: gem-cache-{{ .Branch }}-{{ checksum "Gemfile" }}
paths:
- vendor/bundle
- run: bundle exec danger --verbose
DangerはRuby版を使ってます。(https://danger.systems/ruby/)
Dangerfileはdanger-checkstyle_formatとdanger-lgtmくらい簡単なものしか入れてないです。
- エラーになる時

- 成功する時

DeployGateにアップロード
deploy:
<<: *defaults
steps:
- attach_workspace:
at: ~/
- run:
name: Deploy APK
command: curl -F "token=${DEPLOY_GATE_API_KEY}" -F "file=app-qualityAssurance-debug.apk" -F "message=$(git log --oneline -1)" https://deploygate.com/api/users/
リリースする前にQA版のAPKを使って自動テストを実行してるので、そこの手動生成の手間が省略できます。
結
以上で簡単なCI導入の手順でした。導入してよかったと思ったところがいくつあります。
- Ktlintの導入によって、書き方のミスが防げるようになりました。基本的に人工でチェックするのは不可能ので、非常に助かります。
- QAテスト向けのAPKを手動でビルドして、DeployGateにアップロードする手間も省略できました。
- 開発する時にDebugBuildすることは多いですが、実際ReleaseBuildの時にBuildが通らないこともたまにあります、これもCIによって事前にわかります。
また、この記事を書いてる途中で気づきましたけど、DangerさんがKtlintを対応してくれました。また試してみます。 :thinking_face:
終わりに
GameWith は、ゲームの楽しさをもっと世界に伝えていきたいエンジニアを大募集中です。 Wantedly でもよいので是非お気軽にお声がけください!