2021食べチョクAndroidが取り入れた技術まわりを振り返っていく

この記事は [ビビッドガーデン Advent Calendar 2021](https://qiita.com/advent-calendar/2021/vivid-garden) の1日目です。

## 食べチョクAndroidアプリは1周年を迎えました🎊

https://play.google.com/store/apps/details?id=com.tabechoku.android

2020/11/2にリリースした食べチョクAndroidアプリは先日1歳のお誕生日を迎えました🎂

1stリリースへの開発期間は3ヶ月ととても短く、更に先行していたiOSアプリに追いつくためにもリリースから一定期間は機能開発に集中する時間が続いていました。

そんな食べチョクAndroidにおいてもリリースから半年を過ぎた頃から少しずつではありますがモダンな開発に近づけていく努力を行っていけるようになりました。今回はそんな食べチョクAndroidアプリの1年間の軌跡を振り返っていきたいと思います。

## リリース前(~2020/11)
### Bitrise

https://www.bitrise.io/

iOS/AndroidアプリのCIはどちらもBitriseを利用しています。
このときは

- PR時にdebug build/release buildが正しくビルドできるかを検証するWorkflow
- Firebase App Distributionに指定ブランチアプリをアップロードするWorkflow
- Firebase TestLabでRoboテストを実行するWorkflow

の簡易的なWorkflowを作って稼働していました。

### dependabot
リリース前ではありましたがGradleでのライブラリバージョン管理としてdependabotを導入しました。
個人的にライブラリのバージョン最新化ツールをAndroidプロジェクトで導入するのは初めてだったのですが
それまでAndroid Studioのハイライト表示だけだと見落としがちなバージョン管理をPRとして常に最新化できる仕組みは非常に便利みを感じており、今でも稼働させています。

### codeclimate

https://codeclimate.com/

静的解析ツールとして導入していました。
ルールを細かく設定すればKotlinでも使いやすいのでしょうが、弊社プロダクトだと扱いづらい印象を受け、現在は別のツールに置き換えました。
開発初期〜現在までAndroidプロジェクトは１〜２人体制のため、満足なコードチェックをできないこともあり静的解析の指摘だけでも遵守していくためにも導入しています。

### ktlint
https://ktlint.github.io/

必要最低限のKotlinの制約を担保するために導入していました。

### Danger
https://danger.systems/ruby/

上記のktlintとあわせてPR時に実行していました。

## リリース時(2020/11)

### Bitrise > deploy workflow

加速していくリリース作業をより簡略化するためにDeploy用のWorkflowを作成しました。
今でも大枠は変わらないのですがこのときはGoogle Play内部テスト版へのアップロードを行うだけのフローを作成していました。

ちなみにこのタイミングで**Google Play ConsoleのUIアップデートが入り、署名鍵・アップロード鍵を誤ってアップロードして1stリリースが延期する事態になりました** :fire: 
それまで割と順調に進んでいた開発だっただけに、最後の最後でつまづいてしまったのは今振り返るといい思い出です😇

### Slack > AWS Lambda > Bitrise起動コマンドを作成

Bitrise/Slackのスラッシュコマンドを使えば同じことはできるのですが
**iOS/AndroidともにdeployがCI上実現できてしまうこともあり、権限ユーザーを絞る仕組み**を作りました。

ざっくり説明すると、lambda functionではSlackからの特定コマンド時に送信されるAPI Keyを認証し、Slackの特定チャットルームからの起動に限定させ、
そのルームに属するメンバーのポストだけを受け付けるようにし、あとはBitriseのAPIを叩いて指定Workflowを動かすといった仕組みです。

今でも定常的に使われており、iOSでも**テスター用のデバイスUDID登録** や上述の **deployタスク** を起動したりとほぼ毎日稼働しています。

## コラム：リリースから半年

ここから半年間は基本的に機能実装や改善がメインとなり、開発体制のアップデートや技術負債の解消などにあまり時間を使えない状況が続いていました。
この記事を作成するにあたり、GithubReleasesを参照していたのですが、特にリリースしてから1~2ヶ月はバグFIXに取り組む時間が多かったようです笑
弊社ではリリースしてしまったユーザーに影響のある不具合のことを総じてdefectと呼称し、**defectの解消を最優先事項として取り組むというルール**を設けています。
そして解消したdefectはその後再発防止の為、ポストモーテムの場でチームに共有、具体的な再発防止策を講じて堅牢性を高めていくようなアクションをとっています。

このリリース初期時に特にdefectが多かったのですが、地道な解消と講じた再発防止策の成果あって、今は低い水準でキープしています

## リリースから半年〜

### UnitTest/instrumentation Testの導入
恥ずかしながら半年間ここまでテストがありませんでした… :scream: 
これまでは機能開発・dependabotのPRの確認として手動のリグレッションテストが欠かせず、1リリースのクローズにとても時間を要していました。

まずは**壊れたことがすぐに分かること**を目標にかんたんな画面遷移や主要機能のログイン・購入のUIテストの作成から努めました。

今はQAエンジニアの助けを借りながら、まずは実現すべき必要最低限のUIテストパターンを洗い出し、それらの実装率を高めていくような取り組みを行っています。

まだ導入して半年ですが今現在の**UnitTest+InstrumentationTestの実装率は33％**と少しずつではありますが「壊れたことがすぐわかる」から、「壊れないプロダクト」に変わりつつあるかなと感じています。

またこの同タイミングにてBitriseにtestを実行するWorkflowを追加し、日時で定時実行するように運用しております。

### ktlint+Danger >> pre-commit+ktlint

https://twitter.com/line6th/status/1432975339441950728

それまでktlint+Dangerである程度のKotlinのお約束を担保し続けていましたが、まだ少数である開発体制の中、PRごとにGithub Actionで稼働させるよりも、pre-commitでlintを実行するのはどうかと思い試してみています。

今のところはGithub Actionの稼働時間の減少とcommit前の検査でストレスなく検証できていますが
メンバーが増えたときの制約がゆるくなってしまうので、やはりDangerでの検証は必要かなと考えています。

### codeclimate >> detekt

https://github.com/detekt/detekt

https://twitter.com/line6th/status/1443225708872888332

Kotlinのlintをktlintに、コード制約をcodeclimateに担わせていましたが、
codeclimateのルール設定が少し難しく、import文なども指摘されることや非常に強力なDuplicateWarningなどで少しつらみがあったので
Kotlin純正でktlintを更に制約強くしたdetektの導入・移行をしています。こちらは21年11月末時点で現在進行系で行っています。

というのも最終的にはdetekt+Dangerの構成にしてチェックを行いたいのですが、試しにdetektを実行してみると**３桁を超えるWarningが…**

このままではActionでチェックさせることはできなかったため、一旦はローカル・CIで実行できるように調整しています。

CIでは日時実行するようにしており、**どのWarningがどれだけでているか・またその改善推移**をスプレッドシートに吐き出すスクリプトを作って管理しております。

![スクリーンショット 2021-11-28 16.49.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63740/1bd4989b-295f-8752-c850-7462341d08db.png)

毎日総数がSlackのbotチャンネルに通知され、チームメンバーに状況が晒されているので、改善のモチベーションにつながっています😇

![スクリーンショット 2021-11-28 16.53.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63740/33a4bdce-acc6-de9c-3f4b-65345c8401d3.png)

自分の中で善行と呼称して毎朝心を清めるための活動として継続しています。日々修行
![スクリーンショット 2021-11-28 16.52.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63740/1a631f80-2742-19bf-4b68-5453b811e135.png)

### Google Playストアへのdeployを半自動化

https://twitter.com/line6th/status/1439796180842541061

もともとdeploy workflowはBitriseから起動できるようにしていましたが、

- バージョン用issueのクローズ
- milestoneのクローズ
- バージョンPRのクローズ
- Releaseの作成…

などは手作業で行っていました。
申請提出作業からリリース後のクローズ作業、合わせて20分程度の作業となっていたところを、トータル5分（スクリプト投げて待つだけ）に短縮することに成功しました。

詳細はまた別の記事で紹介できればと思いますが、

- 次回リリースバージョンの準備
    - バージョン用milestoneの作成
    - バージョン用issueの作成・milestoneの紐付け
- deploy・審査提出
    - バージョン用branch >> mainへのPR
    - バージョン用issueへの`in:review`ラベルの付与
    - draft Releaseの作成
        - バージョン用milestoneのクローズURLを付与
    - Google Play inner testへのdeployタスク
- リリースクローズ
    - バージョンPRのマージ
    - バージョン用milestoneのクローズ
    - バージョン用issueのクローズ
    - ReleaseのPublish

上記をそれぞれ実行するスクリプトを作成し、Gradle/Bitriseからそれぞれ実行できるようにしています。

また半自動化としているのは、inner test版からproductionへのステージング処理、審査通過後のステータス通知などについてはそのまま手動となっているからです。

inner testからのステージングについては、inner test版での検証を踏んでから審査提出、という流れにしているため一旦は最適かと考えていますが、
審査ステータスの変更については、PublishAPIのtrackステータスに審査通過が無いことや、メール通知が無いことから自動化できず、
Androidアプリ版のGoogle Play Consoleでの通知を確認するだけに留まっています。
審査ステータスのよいオブザーブ方法をご存知のかたはコメントいただけると助かります :pray: 

## さいごに

食べチョクAndroidアプリの1年を軽く振り返ってみましたが、まだまだ改善できるようなところばかりだなーと改めて感じています。

もちろんdetektの改善は継続して続けていきますが、一層のテストコードの拡充・効率化、少数体制だからこそのより強いコード制約・自動化など
やれることはまだまだ山積みだと思っております。

そんな中ビビッドガーデンではより多くのAndroidエンジニアを求めています！
今回の記事では紹介できなかった話や一次産業の課題解決に取り組んでいる具体的な活動などについてもカジュアルにお話する場も用意しておりますので、
気になった方はこちらを覗いて見てください。

https://herp.careers/v1/vividgarden/Nuzi4TR-qXSa

また、趣味の家庭菜園についてもお話できたりするので、家庭菜園系フルリモートエンジニアについて興味のある方はぜひ一度おはなししてみませんか！！

https://meety.net/matches/SBXGpgdehWsT