Version Catalog と Renovateを組み合わせて、Androidのライブラリ更新作業を自動化する

# この記事でやること
`Version Catalog` + `Renovate`で、
Androidのライブラリ更新作業を、かなり楽にできたので、
その方法を紹介したいと思います。

Androidのライブラリの更新作業って大変ですよね。
Android開発だと、一つのプロジェクトで、だいたい10~20くらいのライブラリを使用すると思いますが、
（場合はよってはもっと、Spotifyだと数百とかのレベルらしいです）
使っているライブラリ一つ一つの最新バージョンを、目視で確認するのはしんどいです。:frowning2:

build.gradleに依存関係を直書きしていれば、
Android Studioが、最新バージョンをsuggestしてくれますが、それだと管理が煩雑ですし、

buildSrcのように、依存関係の記述を外だしする方法だと、
管理はしやすいですが、最新バージョンをsuggestしてくれないので、更新が大変です。

`Version Catalog` + `Renovate` なら、管理しやすく、なおかつライブラリの最新バージョンをRenovateがsuggestしてくれます。

次から、それぞれの設定方法について、説明していきます。

# Version Catalogって何？
Version Catalogというのは、Gradle7.0から追加されたライブラリの管理方法です。
（Gradle7.2では、さらに`[plugins]`セクションが使えるようになりました）

`gradle/libs.versions.toml`というファイルを作って、ライブラリを管理します。
あくまで個人の感想ですが、buildSrc方式より導入が楽な気がしました。

buildSrcはフォルダ作って、build.gradle.ktsを作成して、ビルドを通して、依存関係を記述するクラスを作って、、、と最初にやること多いですが、

Version Catalogは一個ファイル用意するだけで済みますからね。

# Version Catalogの設定方法
まず、settings.gradleに、`enableFeaturePreview("VERSION_CATALOGS")`の記述を追加します。
これをしないと、Version Catalogが利用できません。

```diff_gradle:settings.gradle
pluginManagement {
    repositories {
        gradlePluginPortal()
        google()
        mavenCentral()
    }
}
+ enableFeaturePreview("VERSION_CATALOGS")
dependencyResolutionManagement {
    repogsitoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}
```

次にgradle配下に、`libs.versions.toml`ファイルを作成します。

`libs.versions.toml`の構成は、以下のようになります。

```toml:libs.versions.toml
[versions]
kotlin = "1.6.21"
android-gradle = "7.1.1"
compose-core = "1.2.0-beta01"

androidx-core = "1.7.0"

[plugins]
kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
android-application = { id = "com.android.application", version.ref = "android-gradle" }
android-library = { id = "com.android.library", version.ref = "android-gradle" }

[libraries]
# Androidx Core
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }

# Compose Core
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose-core" }
compose-material = { module = "androidx.compose.material:material", version.ref = "compose-core" }
compose-uiToolingPreview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose-core" }
compose-livedata = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "compose-core" }

[bundles]
compose-core = [
    "compose-ui",
    "compose-material",
    "compose-uiToolingPreview",
    "compose-livedata",
]
```

一つずつ、説明していきます

## [version] セクション
versionセクションでは、ライブラリのバージョン情報を管理します。

このセクションでバージョンを定義しておくと、
```toml
[versions]
android-gradle = "7.1.1"
```

後のセクションで、`version.ref`を使って参照できます。
```toml
[plugins]
android-application = { id = "com.android.application", version.ref = "android-gradle" }
android-library = { id = "com.android.library", version.ref = "android-gradle" }
```

また`build.gradle`で直接バージョン情報を参照することもできます。
その場合、-(ハイフン)は.(ドット)に置き換えて、get()を呼び出します。

```diff_gradle:build.gradle(app)
    composeOptions {
-        kotlinCompilerExtensionVersion "1.2.0-beta1"
+        kotlinCompilerExtensionVersion libs.versions.compose.core.get()
    }
```

## [plugins]セクション
pluginsセクションでは、build.gradleのpluginsブロックの依存関係を記述できます。

```toml:libs.versions.toml
[plugins]
kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
android-application = { id = "com.android.application", version.ref = "android-gradle" }
android-library = { id = "com.android.library", version.ref = "android-gradle" }
```
使用するときは、alias()で囲みます。
```diff_gradle:build.gradle(Project)
plugins {
-    id 'com.android.application' version '7.1.1' apply false
-    id 'com.android.library' version '7.1.1' apply false
-    id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
+    alias(libs.plugins.android.application) apply false
+    alias(libs.plugins.android.library) apply false
+    alias(libs.plugins.kotlin) apply false
}
```

## [libraries]セクション
librariesセクションでは、build.gradleの`dependencies`の依存関係を記述できます。

```toml:libs.versions.toml
[libraries]
# Androidx Core
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
```

また、`version.ref`で参照するのではなく、`version`で直接バージョンを指定することもできます。

```toml:libs.versions.toml
[libraries]
# Androidx Core
androidx-core = { module = "androidx.core:core-ktx", version = "1.7.0" }
```

build.gradleでは、以下のように記述します。
```gradle:build.gradle(app)
dependencies {
    implementation libs.androidx.core
}
```

## [bundles]セクション
個人的に一番便利だな～と思う機能です。
librariesセクションで定義した複数の依存関係をまとめて、一つのように扱えます。

例えば、librariesセクションで、下記のような記述をしておいて、
```toml:libs.versions.toml
[libraries]
# Compose Core
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose-core" }
compose-material = { module = "androidx.compose.material:material", version.ref = "compose-core" }
compose-uiToolingPreview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose-core" }
compose-livedata = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "compose-core" }
```

bundlesセクションで一つにまとめることができます。
```toml:libs.versions.toml
[bundles]
compose-core = [
    "compose-ui",
    "compose-material",
    "compose-uiToolingPreview",
    "compose-livedata",
]
```

そして、build.gradleで一つのライブラリのように扱うことができます。

```gradle:build.gradle(app)
dependencies {
    ...
    implementation libs.bundles.compose.core
}
```

bundlesを利用すると、build.gradleの記述が結構すっきりしますよ:blush:

Version Catalogの説明は以上です。

# Renovateって何？
Renovateというのは、依存関係の自動更新用のツールです。
下記のプラットフォームに対応しています。

- GitHub
- GitLab
- Bitbucket Cloud
- Bitbucket Server
- Azure DevOps
- Gitea

詳しくは、下記のURLのご覧ください
https://github.com/renovatebot/renovate

Renovateと似たツールに、Dependabotがありますが、
DependabotはVersion Catalogに対応していません（2022/8/28 現在）

# Renovateの設定方法

Renovateの設定方法は簡単です。

まず、Renovateの[インストールページ](https://github.com/apps/renovate)にいきます。
Installというボタンを押します。

![スクリーンショット (26).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320402/828caebb-d7b3-5e6b-975a-fec08d8a3940.png)


アカウントのすべてのレポジトリにRenovateを導入するか、
選択したレポジトリだけにRenovateを導入するか選べますが、

選択したレポジトリだけの導入にしておいたほうがいいでしょう。

Renovateのインストールが済むと、初期設定用のPRが自動で作成されます。

![スクリーンショット (27).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320402/c853951d-79d6-be87-8e06-0a4f6b09f3b2.png)

renovate.jsonというファイルを追加するPRです。

```json:renovate.json
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:base"
  ]
}
```

上記のPRをマージすると、Renovateが動作しはじめます。
（画像ではすでにMergeしてしまっていますが）
extendsに設定を追加すると、自動マージや、スケジュールの設定ができるんで、調べてみてください。

Renovateが動作すると、プロジェクト内の依存関係を読み取って、
更新できるライブラリがないか探します。

ある場合は、PRが自動で生成されます。

Renovateが生成するPRの例です。

![スクリーンショット (28).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320402/4a022ae4-1aaf-a492-1d06-57b614f22ba9.png)
![スクリーンショット (30).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320402/ec47c471-231e-904e-c309-cdb8d107a1f7.png)

更新前と、更新後のバージョンが分かるようになっています。
PRのブランチをチェックアウトしてきて、動作確認して問題なければ、
PRをマージすれば、ライブラリ更新ができます。

目視で確認するより、ずっと楽ですね！

# 終わりに

Version Catalog + Renovateについてご紹介しました。

Androidのライブラリ更新って、地味につらい作業で、
面倒くさがって、古いバージョンのまま放置されているプロジェクトとか割とありますが、
この方法なら、更新作業もだいぶ楽になりますね。

一つ注意なのが、
新しいバージョンはバグや脆弱性が存在する可能性があるので、
RenovateがPR作ってきたからといって、あせってマージしてはいけないということです。

きちんと動作確認して、安全性を確かめてからマージするようにしましょう。