Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

Gradleプラグインのメジャーアップデートにおいて、古いGradleへのサポートをいかにして切るか

spotbugs-gradle-plugin v5をリリースしました。beta1のリリースから約3ヶ月間かかっています。

github.com

Gradleプラグイン開発はややマイナーな取り組みだと思うので、Gradleプラグイン開発のメジャーアップデートがどういうものだったのかをちょっと紹介します。

なぜ後方互換を壊す必要があったのか

spotbugsプラグイン固有の理由はもちろんあります。デフォルトの設定がうまくなかった、リソースリークの解消にはデフォルトの動作モードを変える必要があった、などです。これに加えてGradleプラグインならではの理由があります。

古いGradleへのサポートを切るため

Gradle 7をサポートするには、Gradle 7で削除されたGradle APIへの依存を切る必要があります。この場合、移行先Gradle APIが存在するGradleのバージョンが最低限サポートできるバージョンになります。例えば今回削除された compile configurationの代替となるimplementation, api configurationsはGradle 3.4で導入されているので、プラグインがこれらのconfigurationに依存する場合は3.4が最低限サポートできるバージョンになります。

新しいGradleで導入された機能を使うため

Gradleは新しい機能を継続的に取り入れており、中にはJavaプロジェクト開発の体験を大きく変えるものも存在します。依存管理やキャッシュの改善、差分コンパイルの実現によるビルド時間の短縮が良い例ですね。Gradle社としてはこうした改善に命運を賭けているようで、Developer Productivity Engineering (DPE)という造語を作って強く押し出しています。

gradle.com

そしてこうした機能を前提にプラグイン開発を行う場合、自然と古いGradleに対するサポートを切る必要が出てきます。 例えば今回入れたJava toolchain対応はGradle 6.7で導入され、7.0以降で安定しています。これがv5とv6のサポートを切る主な動機となっています。

コードを簡潔に保つため

とはいえ動的にGradleVersionを調べるなどしてプラグインの動作を切り替えることで、古いGradleをサポートしつつ新しい機能を使うことも可能です。例えば今回のリリースでもGradle 7.1で取り入れられた JavaPluginExtension を使いつつGradle 7.0もサポートしています。

github.com

しかしこの方法はコードが複雑化する上、概念レベルでの変更への対応が難しいため、そこまでコストを掛けて互換を保つ判断はあまりしないのではと思います。 むしろこうした変更をパッチアップデートで行うspotlessのようなプラグインも存在します。

ユーザのスムーズな移行のため、Gradleのメジャーバージョンを複数サポートするバージョンを提供することは重要ですが、同様に新しいGradleメジャーバージョンに集中して管理しやすいリポジトリを保つこともまた必要です。Gradleの場合コミュニティの進歩が速く、ユーザもそれを前提に頻繁なアップデートをある程度覚悟していますので、プラグイン側が過度に古いGradleのサポートに固執する必要はないとも思われます。

まとめ

Gradleプラグインのメジャーアップデートにおいて、古いGradleへのサポートはコードを簡潔に保つためにも早めに切ってしまうべきです。マイナーアップデートやパッチアップデートで古いGradleへのサポートを切るプラグインもあり、それがコミュニティに受け入れられているくらいですので、古いGradleをサポートすることよりも新しいGradleをサポートするための素早い継続的デプロイを実現することにコストを割いたほうが良いでしょう。

なおGradleプロジェクトにおける素早い継続的デプロイには、semantic-releaseの活用がおすすめです。私が実装しメンテナンスしているgradle-semantic-releaseについては以下の記事で紹介しています。

blog.kengo-toda.jp