Now in REALITY Tech #45 REALITY Androidのコードベースの話
REALITYでAndroidチームのエンジニアリングマネージャーをしています。メタルおじさんです。
REALITYで使っているライブラリの話は以前の記事に書きましたが、今回はコードベース周りの話をしようと思います。
REALITY AndroidのGradleビルドスクリプト
入社して初めてREALITY Androidのコードベースを見ると、もしかすると「いつも見ているGradleのスクリプトと違う」と感じるかもしれません(お見せすることはできないですが…)。
どういう感じになっているかを紹介します。
Version Catalogsを使った外部依存管理
REALITYでは、GradleのVersion Catalogsを導入して外部依存関係のバージョン管理をしています。AndroidXのリポジトリなどでもVersion Catalogsが導入されているため、おそらく今後はVersion CatalogsがGradleプロジェクトにおける標準的な外部依存関係のバージョン管理方法になるだろうと考えています。
REALITYのlibs.versions.tomlをちょっとだけお見せします(とても長いので全部は載せられませんが)
[versions]
android-gradle = "7.2.1"
kotlin = "1.7.0"
min-sdk-version = "26"
compile-sdk-version = "32"
target-sdk-version = "32"
activityktx = "1.5.1"
adjust = "4.31.0"
appcompat = "1.4.2"
browser = "1.4.0"
cardview = "1.0.0"
coil = "2.1.0"
compose = "1.2.0"
composeCompiler = "1.2.0"
...
### For Build Script
firebase-crashlytics-gradle = "2.9.1"
firebase-perf-plugin = "1.4.1"
googleservices = "4.3.13"
gradleprotobuf = "0.8.19"
ksp = "1.7.0-1.0.6"
ktlint-gradle = "10.3.0"
onesignal-plugin = "0.14.0"
### For Test
androidx-test = "1.4.0"
junit = "4.13.2"
junit-ext = "1.1.3"
mockk = "1.12.5"
robolectric = "4.8.1"
[libraries]
activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityktx" }
adjust = { module = "com.adjust.sdk:adjust-android", version.ref = "adjust" }
androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "activityktx" }
androidx-browser = { module = "androidx.browser:browser", version.ref = "browser" }
androidx-cardview = { module = "androidx.cardview:cardview", version.ref = "cardview" }
...
### For Build Script
android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "android-gradle" }
firebase-crashlytics-gradle = { module = "com.google.firebase:firebase-crashlytics-gradle", version.ref = "firebase-crashlytics-gradle" }
firebase-perf-plugin = { module = "com.google.firebase:perf-plugin", version.ref = "firebase-perf-plugin" }
...
### For Test
androidx-test-junit = { module = "androidx.test.ext:junit", version.ref = "junit-ext" }
androidx-test-junit-ktx = { module = "androidx.test.ext:junit-ktx", version.ref = "junit-ext" }
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidx-test" }
archcore-testing = { module = "androidx.arch.core:core-testing", version.ref = "archcore" }
coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutine" }
...
[bundles]
compose = [
"compose-ui",
"compose-ui-preview",
"compose-material",
"compose-livedata",
"compose-coil",
"compose-animation",
]
firebase-all = [
"firebase-analytics",
"firebase-dynamic-links",
"firebase-config",
"firebase-crashlytics",
"firebase-messaging",
"firebase-perf",
"firebase-inappmessaging",
]
flipper = ["flipper", "flipper-network-plugin"]
koin = ["koin-core", "koin-android"]
...
[plugins]
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
...
依存の種類ごとにコメントを書いたりして、なんのための依存関係なのかがわかりやすくなるようにしています。
ちなみに、Version Catalogsを使っていると、dependenciesの宣言はこんな感じになります。
dependencies {
implementation(libs.bundles.koin)
implementation(libs.bundles.room)
implementation(libs.appcompat)
implementation(libs.constraintlayout)
...
}
[libraries]で指定した独自のエイリアスを使って短い記述でライブラリを指定できる他、[bundles]を使って複数の依存関係をまとめて記述することができたりするので、Version Catalogsは便利だなと思います。
Kotlin DSL
Gradleのビルドスクリプトは普通はGroovy言語で記述します。Groovyは動的言語であるため柔軟な記述ができて良いのですが、柔軟であるが故に実行時に決定される要素が多く、IDEによるコード補完が行いづらかったり、静的解析が難しいというデメリットがあります。
そこで、Groovyより静的に型を決めやすいKotlinを使ってビルドスクリプトの記述をできるようにするKotlin DSLという機能があります。
Androidのドキュメントにもビルド構成を Groovy から KTS に移行するというページがあることからもわかるように、今後はKotlin DSLを使用した.ktsによるビルドスクリプトの記述の方が使われるようになっていくと思われます。
REALITYではビルドスクリプトの記述を全面的にKTSにリファクタリングしました。KTSで書いているとGradle APIについての理解が深まります。IDEでの入力補完もできるので、調べやすくなります。今までなんとなく見様見真似でコピペしていたビルドスクリプトが、理解しやすくなったと思います。
それから、ビルドスクリプト中にロジックが必要になった場合も普段から慣れ親しんでいるKotlinで表現できるようになり、安心して書けるようになりました。
REALITY Androidの自動化の取り組み
Renovate
REALITY Androidのコードベースに最近Renovateを導入しました。Renovateは、外部依存関係のバージョン更新を自動化してくれるツールです。
GitHubアプリとして導入するだけで、自動的にリポジトリ内で使用している外部依存関係のバージョンをチェックし、定期的にPull Requestを上げてくれます。
(GitHub以外のホスティングサービスを使っていても使用可能です。CLIツールとしてローカルにインストールして使うことも可能です。)
今までは2〜3ヶ月に一度くらいのペースで、人力で全ライブラリの更新チェックとリリース内容の把握、Pull Request作成と動作確認を行っていたのですが…正直これはとても大変な作業です。
Renovateを導入したことでライブラリの更新チェックとPull Requestの作成が自動化されたため、今はPull Requestをチェックアウトして動作確認をするだけになりました。ビルドが通らなくなるような破壊的な変更は自動テストで検知してくれますし、すごく楽になったなと思います。
GitHub Actions
REALITYでは今までもJenkinsやBitriseを使ってワークフローの自動化を行ってきていましたが、今年になってからコードベースのリポジトリをgithub.com (GitHub Enterprise Cloud)に移管したことで、GitHub Actionsを利用できるようになりました。
REALITYでGitHub Actionsを活用した自動化の一部を紹介します。
Pull Requestに特定のラベルを付けるとapkがビルドされてApp Centerにデプロイされる
その際、インストールURLがPull Requestのコメントに通知される
mainブランチに変更が入るとaabがビルドされてGoogle Playにデプロイされる
Google Playの本番アプリのバージョンが新しくなったらSlackに通知する
明らかにコードベースを壊さないだろうとわかっているPull Requestに関しては自動でApproveをつけたりAuto Mergeしたりする
他にも、「この作業自動化できたらいいのにな」と思うことがあったら積極的に自動化を検討しています。
まとめ
REALITY Androidのコードベースについてチラっとご紹介しました。プロダクトコードそのものだけでなくコードベースそのものやCI/CD環境についても、便利そうなものはどんどん使ってみよう!という環境です。
まだまだ気になることがある方は、カジュアル面談しましょう。