Dependabot
がversion catalog
対応していたことを今更ながら知ったため、社内のマルチモジュールSpringBoot
プロジェクトをversion catalog
移行しました。
この記事では、移行に当たって意識したことや制定したルール、得られたメリットについて書きます。
移行で得られたメリット
当該プロジェクトでは基本的にSpring
等のBOM
に合わせたバージョンの依存を利用しており、移行で記述量が減らせる等のメリットはそれ程享受できなかった感が有ります。
ただ、バージョンを書く個所が一元化されたことによって、依存の更新作業を行う上で必要とされる前提知識を減らすことができ、作業ミスの発生確率もほぼ0にできました。
その意味で、完全な一元管理が可能というのはやはりメリットが大きいと感じます。
また、Dependabot
が同じ依存に対しても複数のPR
を送ってくる問題も解決されました1。
移行に当たって定めたルール
今後の運用において混乱が生じないよう定めた一応のルールに関しても書きます。
ただ、これに関しては走り出したばかりであるため、今後変動が有るかもしれません。
基本方針としては、以下を重視しました。
- 移行の労力を小さくする
- 追記が楽なようにする
- メンテナンスが楽なようにする
version catalog
への移行基準
少し触れましたが、この当該プロジェクトでは基本的にSpring
等のBOM
に合わせたバージョンの依存を利用しています。
このため、全ての依存をversion catalog
へ移行した場合、むしろ以下のようなデメリットが生じます。
- 移行に当たっての書き換え量が多くなる
- 依存を追加する場合
version catalog
とdependencies
両方の書き替えが生じる- これは移行前より記述量が多い
- 削除時も両方から削除のが必要になる
- ルートの
version catalog
にあらゆる依存を詰め込んで見通しを悪くするか、ファイル分割で状況を複雑化させるかの択が生じる
そこで、移行対象はバージョンを明示的に指定しているものだけとし、以下のようにバージョン指定が省略されていれば移行対象外としました。
implementation("org.springframework.boot:spring-boot-starter-web")
version catalog
の記述ルール
[versions]
セクション
複数の依存で利用するか、build.gradle
において定数的に利用したいような場合を除き、バージョンは直接書く方針としました。
これは日々の追記をコピペで済ませやすくするための方針です(後述)。
[plugins]
セクション
個々の定義は、基本的に以下の形式で書く方針としました。
[plugins]
spring-boot = { id = "org.springframework.boot", version = "3.3.2" }
これはGradle Pluginsからのコピペをやりやすくするための方針です。
細かいことを言うと、形が似ているため、Grooby
タブからコピペするのがお勧めです。
plugins {
id "org.springframework.boot" version "3.3.2"
}
試した限り以下のようなワンライナー形式でも書けるようでしたが、こちらは採用しませんでした。
[plugins]
spring-boot = "org.springframework.boot:3.3.2"
[libraries]
セクション
個々の定義は、基本的に以下の形式で書く方針としました。
この形式であってもDependabot
は正常稼働してくれることを確認しています。
[libraries]
spring-boot-starter-web = "org.springframework.boot:spring-boot-starter-web:3.3.2"
これはMaven Centralからのコピペをやりやすくするための方針です。
細かいことを言うと、形が似ているため、Gradle(Kotlin)
がコピペしやすかったです。
implementation("org.springframework.boot:spring-boot-starter-web:3.3.2")
以下の形式でも書けます(というかこちらの方が一般的?)が、こちらは採用しませんでした。
[libraries]
spring-boot-starter-web = { module = "org.springframework.boot:spring-boot-starter-web", version = "3.3.2" }
その他
移行対象となるような内容は特別な事情を持っている場合が多く、付随するコメントも有りました。
それらのコメントに関しては、分散している方が混乱を招きそうだったため、同時にversion catalog
側へ移行することとしました。
また、以下の理由から、記述ルールは必要に応じて無視してOKという方針にしました。
- 日常的に頻出する操作が楽な方針にするとどうしても例外が出る
- 特に
[libraries]
から[versions]
に定義されたバージョンを参照する場合
- 特に
- 方針的に
version catalog
はそれ程肥大せず、ロジックも無いため、多少のブレは許容できる
ハマったポイント
最後におまけとして、移行時ハマったポイントを幾つか紹介します。
subprojects
内でlibs
に定義された内容が参照できない
以下に報告されている問題です。
これは一旦トップレベル変数に取得しておくことで解決できました。
+ val foo = libs.foo.get()
subprojects {
dependencies {
- implementation(libs.foo)
+ implementation(foo)
}
}
社内GitHub Packages
の依存がDependabot
に検出されない
プロジェクトのrepositories
設定によって生じた問題です。
こちらは個別に記事にしています。
-
既にグループ化して
PR
発行できるようなので、これはDependabot
設定が悪かっただけ感は有りますが……。 ↩