起
はじめまして、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 でもよいので是非お気軽にお声がけください!