Gradleでビルドを構成し、Renovate(依存パッケージの更新PRを自動作成するツール)を導入した直後にビルドが失敗する事例があります。原因の多くは依存関係の検証機能とメタデータの扱いにあります。マルチモジュールの業務システムでGradleを運用している方や、これからRenovate導入を検討しているチームの参考になれば幸いです。
RenovateはDependabot(GitHubが提供する同種の自動更新ツール)と似た仕組みで、依存ライブラリの新バージョンを検知してPull Requestを自動生成します。便利な反面、Gradleプロジェクトでは新バージョンへの更新が原因でビルドが落ちるケースが報告されています。この現象は偶然のバグではなく、サプライチェーン攻撃対策として組み込まれた検証機構が正しく機能した結果であることが多いです。
なぜ依存関係の検証が必要になったのか
ソフトウェア開発は他者の成果物に依存する構造を前提にしています。OSS(オープンソースソフトウェア)は巨大な基盤ライブラリから小さな専用ライブラリまで幅広く提供され、多くのプロジェクトがその上に成り立っています。
この構造は効率的な反面、攻撃者にとって都合の良い経路にもなります。攻撃者が公開リポジトリ上の特定バージョンのライブラリを、同じ座標(グループID・アーティファクトID・バージョン)を持つ改ざん版に差し替えられれば、利用者は気づかずに悪意あるコードを取り込んでしまいます。これがサプライチェーン攻撃と呼ばれる手口です。
直接依存しているライブラリだけでなく、そのライブラリがさらに依存する推移的依存関係まで含めて正当性を確認する必要があります。業務システムでは数百に及ぶ依存関係を抱えることも珍しくなく、目視でのチェックは現実的ではありません。
検証の仕組み:署名からハッシュ値へ
Javaプラットフォームには古くからJARファイルの署名機能があります。JDK 1.2の時点で既に存在していた仕組みで、META-INFフォルダに署名情報を格納する形式です。
ただしこの署名の仕組みは広く普及しませんでした。証明書の取得コストが高かったこと、運用プロセスが煩雑だったこと、当時はDevOpsという概念自体が一般的でなかったことなどが理由として挙げられます。
代わりに広まったのが、ファイルのハッシュ値(フィンガープリント)による整合性検証です。ダウンロードしたファイルに対してハッシュ関数を計算し、公開されている正規のハッシュ値と一致するかを比較します。一致すれば改ざんされていないファイルだと判断できます。
Maven Central(Javaエコシステムの標準的な公開リポジトリ)では、各アーティファクトに対して.md5や.sha1といった拡張子のハッシュファイルが併せて提供されています。たとえばLog4j2のSLF4jブリッジライブラリでは、本体の.jarファイルに加えて.jar.sha1や.jar.md5が並んでダウンロードページに掲載されています。ビルドツールはこれらを突き合わせて整合性を確認します。
Gradleのモジュールメタデータと検証の関係
Gradleには.pomファイル(Mavenの依存情報記述形式)に加えて、.moduleという独自のメタデータファイルがあります。これはGradle Module Metadataと呼ばれ、バリアント(プラットフォームやビルド種別ごとの成果物の出し分け)情報などPOMより豊富な情報を持ちます。
Gradleは依存関係検証機能を有効にすると、ダウンロードした各ファイルのハッシュ値を検証します。この設定はgradle/verification-metadata.xmlというファイルに、各アーティファクトの期待されるハッシュ値を記録する形で管理します。
Renovateが依存関係のバージョンを更新すると、当然ながら新しいバージョンのファイル・新しいハッシュ値がダウンロード対象になります。しかしverification-metadata.xml側が古いバージョンのハッシュ値しか登録していなければ、検証は失敗し、ビルドがエラーで止まります。これがRenovateのPRをマージした際にビルドが落ちる典型的な原因です。
既存の検証設定を確認する手順
自分のプロジェクトがこの問題に該当するかどうかは、以下の手順で確認できます。
# 依存関係検証が有効かどうかを確認
ls gradle/verification-metadata.xml
# ビルドファイル内で verification 関連の設定を検索
grep -r "verification" gradle.properties settings.gradle.kts 2>/dev/nullgradle/verification-metadata.xmlが存在する場合、そのプロジェクトはハッシュ検証を有効化しています。Renovateでバージョンを上げるたびに、このファイルへ新しいハッシュ値の追記が必要になる構成です。
Gradle公式には、このファイルを自動更新するための仕組みも用意されています。
# 依存関係検証メタデータを自動生成・更新する
./gradlew --write-verification-metadata sha256 buildこのコマンドを実行すると、現在のビルドで使用している依存関係のハッシュ値を再計算し、verification-metadata.xmlに反映します。Renovate導入時は、この更新コマンドをCI上で自動実行するステップに組み込むか、Renovateの設定ファイルでGradleの検証ファイル更新を伴うポストアップグレードタスクを指定する運用が現実的な対処になります。
Renovate側の設定については、公式ドキュメントのpostUpgradeTasks(依存関係更新後に任意コマンドを実行する機能)の項目を確認するとよいでしょう。プロジェクトのCI環境でGradleコマンドを実行できる権限があるかどうかも合わせて確認が必要です。
関連する仕組みとの比較
Node.jsエコシステムのpackage-lock.jsonやGoのgo.sumも、依存関係のハッシュ値を固定して改ざんを検知する仕組みを持ちます。Gradleのverification-metadata.xmlは考え方としてはこれらに近く、ロックファイル更新とハッシュ検証更新を一体で扱う必要がある点も共通しています。
一方でMavenプロジェクトの場合、標準では同等の厳格な検証機能を持たず、.sha1ファイルとの照合はビルドツール側の設定次第です。Gradleを採用している現場では、この検証機能があることを前提に、依存関係更新の運用フローを設計しておく必要があります。
導入前後で確認しておきたいポイント
業務システムでGradleとRenovateを組み合わせる場合、次の点を事前に確認しておくと想定外のビルド失敗を避けやすくなります。
- プロジェクトに
gradle/verification-metadata.xmlが存在するか、lsコマンドで確認する - 存在する場合、CIパイプラインに
--write-verification-metadataの自動実行ステップがあるかを確認する - Renovateの
postUpgradeTasks設定でGradleコマンド実行が許可されているかを確認する - 複数モジュール構成の場合、ルートプロジェクトだけでなく各サブモジュールの依存関係も検証対象に含まれているかを確認する
まとめ
GradleとRenovateを組み合わせた際のビルド失敗は、サプライチェーン攻撃対策として組み込まれた依存関係検証の副作用であるケースが目立ちます。JARの署名からハッシュ値による整合性検証へと主流が移り、GradleはModule Metadataとverification-metadata.xmlでこれを実現しています。
自分のプロジェクトがこの構成に該当するかは、gradle/verification-metadata.xmlの有無を確認するところから始められます。該当する場合は--write-verification-metadataコマンドをCIの更新フローに組み込み、RenovateのpostUpgradeTasks設定と合わせて運用を整えておくと安心です。既存の大規模Gradleプロジェクトほど依存関係の数は多くなるため、検証の自動化を早めに仕組み化しておく価値があります。