こんにちは!開発現場の裏側を支えるインフラやビルドパイプラインの設計、ワクワクしますよね。
JavaやKotlinでの開発を進めていると、こんな悩みに出会ったことはありませんか?
「似たような依存関係の定義や、コード解析ツールの設定が、すべてのマイクロサービスの`build.gradle.kts`にコピペされている……」
「共通化したいけれど、`buildSrc`に入れるとプロジェクトのクリーンビルドが重くなるし、何より別プロジェクトで使い回せない……」
これを鮮やかに解決するのが、「スタンドアロンなGradleプラグインの開発と、プライベートMavenリポジトリ経由での配布」です。
今回は、単なるお決まりのプラグイン作成手順ではなく、なぜこのアーキテクチャが必要なのか、内部でどう動くのかという本質を交えながら、初心者の方にも優しく、かつ実務で即座に使えるレベルまで徹底的に解説していきます。これをマスターすれば、チーム全体のビルド管理が劇的に美しく、楽になりますよ!
—
1. なぜ「スタンドアロンなプラグイン」と「バイナリ配布」が必要なのか?
多くの現場で最初に試されるのが、`buildSrc`というディレクトリに共通ロジックを押し込む方法です。しかし、プロジェクトが巨大化したり、複数のリポジトリにまたがったりすると、`buildSrc`には決定的な弱点が見えてきます。
- `buildSrc`の罠: `buildSrc`内のコードが変更されると、関連するすべてのサブプロジェクトやモジュールでキャッシュが無効化され、フルビルドが強制されるため、ビルド時間が爆発的に延びます。
- 再利用性の欠如: `buildSrc`は「そのプロジェクトの中」でしか生きられません。別チームの新しいプロダクトで同じビルドロジックを使いたいとき、コードのコピペが再発します。
バイナリプラグインという正解
プラグインを「独立した(スタンドアロンな)Gradleプロジェクト」として切り出し、JARファイルというバイナリの形にしてMavenリポジトリ(社内NexusやArtifactory、あるいはローカルの`~/.m2/repository`)にpublish(公開)します。
これにより、利用側のプロジェクトは単にこう書くだけになります。
plugins {
id(“com.example.company-java-conventions”) version “1.0.0”
}
たったこれだけで、社内ニッチな標準化ルール、静的解析の設定、依存関係のバージョン管理がすべて一括で適用されます。依存関係がコンパイル済みJARとして降ってくるため、ビルドのパフォーマンスも圧倒的に保たれます。
—
2. プラグインプロジェクトの基礎セットアップ
それでは、実際にカスタムプラグインを開発するプロジェクトを作っていきましょう。今回はモダンな開発の標準である Kotlin DSL を用いて作成します。
プロジェクト構造
プラグイン用として、以下のようなディレクトリ構成を用意します。
my-gradle-plugin/
├── build.gradle.kts
├── settings.gradle.kts
- src/
- main/
- kotlin/
- com/
- example/
- CompanyJavaPlugin.kt
- test/
- kotlin/
- com/
- example/
- CompanyJavaPluginTest.kt
`settings.gradle.kts` の設定
まずはルートの設定ファイルです。プロジェクト名を適切に定義します。
// settings.gradle.kts
rootProject.name = “my-gradle-plugin”
`build.gradle.kts` の設定(ここが最重要!)
プラグインプロジェクト自身のビルド設定です。ここでは「Gradleプラグイン開発キット」を有効化し、Java/Kotlinプラグインとしての振る舞いを定義します。
// build.gradle.kts
// プラグイン開発に特化した公式プラグイン群を適用します
plugins {
`kotlin-dsl` // GradleプラグインをKotlinで書くための必須プラグイン
`java-gradle-plugin` // プラグインのメタデータを自動生成・管理するプラグイン
}
group = “com.example”
version = “1.0.0”
repositories {
mavenCentral() // 必要な依存関係をMavenCentralから取得
}
// Gradleプラグインとしてのメタデータ(IDと実装クラスの紐付け)を定義
gradlePlugin {
plugins {
create(“companyJavaPlugin”) {
// 利用側が `plugins { id(“com.example.company-java-conventions”) }` と指定する際のID
id = “com.example.company-java-conventions”
// プラグインのエントリーポイントとなるクラスを指定
implementationClass = “com.example.CompanyJavaPlugin”
}
}
}
// テスト実行時にJUnit 5を使用するための設定
tasks.withType
useJUnitPlatform()
}
—
3. 動作する HelloWorld:共通ビルドロジックの実装
それでは、実際に適用されたプロジェクトに対して「Javaプラグインの適用」「共通のリポジトリ設定」「カスタムタスクの追加」を行うプラグインコードを書いてみましょう。
// src/main/kotlin/com/example/CompanyJavaPlugin.kt
package com.example
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Jar
/
- 社内のすべてのJavaプロジェクトに共通の振る舞いを強制・提供するプラグインクラス
/
class CompanyJavaPlugin : Plugin
override fun apply(project: Project) {
// 1. 標準のJavaプラグインを自動的に適用する
project.plugins.apply(JavaPlugin::class.java)
// 2. コンパイラのバージョンをJava 17に統一する
project.extensions.configure(org.gradle.api.plugins.JavaPluginExtension::class.java) {
sourceCompatibility = org.gradle.api.JavaVersion.VERSION_17
targetCompatibility = org.gradle.api.JavaVersion.VERSION_17
}
// 3. すべてのプロジェクトで共通して参照するリポジトリ(Maven Central)を追加
project.repositories.mavenCentral()
// 4. 社内規約として必ず実行したいカスタムタスクを登録する
project.tasks.register(“printCompanyGreeting”) {
// タスクの説明(./gradlew tasks で表示されます)
description = “社内共通規約プラグインからの挨拶を表示します。”
group = “company-tools”
doLast {
println(“==================================================”)
println(” [Info] このプロジェクトは社内標準ビルド規約が適用されています。”)
println(“==================================================”)
}
}
}
}
このコードの何が素晴らしいかと言うと、利用側はたった1行プラグインを宣言するだけで、「Java 17への準拠」「Maven Centralリポジトリの標準設定」「社内カスタムタスクの付与」のすべてを一網打尽に自動化できる点です。
—
4. 信頼性を担保する:プラグインのテスト手法
「プラグインを修正するたびに、別のプロジェクトに組み込んで`gradle build`して動作確認する」――こんな非効率なことをしていては開発速度が落ちてしまいます。
Gradleプラグインには、`gradle-test-kit` という強力なテストユーティリティが標準で用意されており、仮想的な一時プロジェクトを作成してテストを実行できます。
以下のテストコードを書いてみましょう。
// src/test/kotlin/com/example/CompanyJavaPluginTest.kt
package com.example
import org.gradle.testkit.runner.GradleRunner
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.io.File
class CompanyJavaPluginTest {
// JUnit 5がテスト用にクリーンな一時ディレクトリを自動生成してくれます
@TempDir
lateinit var testProjectDir: File
@Test
fun `プラグインが正常に適用されカスタムタスクが実行できること`() {
// 1. テスト用の build.gradle.kts を動的に作成
val buildFile = File(testProjectDir, “build.gradle.kts”)
buildFile.writeText(“””
plugins {
id(“com.example.company-java-conventions”)
}
“””.trimIndent())
// 2. GradleRunnerを使って、作成した一時ディレクトリ上でタスクを実行する
val result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withPluginClasspath() // 現在開発中のプラグインのクラスパスを自動で読み込ませる
.withArguments(“printCompanyGreeting”, “–stacktrace”)
.build()
// 3. 実行結果の検証(タスクが成功したか、期待したログが出力されたか)
assertTrue(result.output.contains(“このプロジェクトは社内標準ビルド規約が適用されています。”))
}
}
テストの実行
ターミナルで以下のコマンドを叩くだけで、プラグインの単体テストが高速に走ります。
./gradlew test
このテスト手法を確立しておけば、プラグインの改修時にデグレ(不具合)を起こすリスクを極限までゼロに近づけることができます。
—
5. ローカルリポジトリへの公開(Publishing)と実際の使い方
テストが成功したら、このプラグインを自分のマシンのローカルMavenリポジトリ(`~/.m2/repository`)に配置して、他のプロジェクトから試してみましょう。
プラグインプロジェクトへのPublish設定の追加
`build.gradle.kts` に `maven-publish` プラグインの設定を追加します(通常は `gradle-plugin` がよしなにやってくれますが、明示的にローカル公開を試します)。
ルートの `build.gradle.kts` に以下を追記:
// ローカルリポジトリ(~/.m2/repository)へのパブリッシュを有効化
publishing {
repositories {
mavenLocal()
}
}
その後、以下のコマンドを実行します。
./gradlew publishToMavenLocal
これで、あなたの手元のマシン上に `com.example:my-gradle-plugin:1.0.0` というJARがデプロイされました!
別プロジェクト(利用側)での検証
まったく別の適当な空プロジェクトを新しく作り、その `build.gradle.kts` を以下のように書いてみてください。
plugins {
// ローカルの Maven Local からプラグインを読み込む設定が必要な場合があります
id(“com.example.company-java-conventions”) version “1.0.0”
}
// リポジトリに Maven Local を追加(検証用)
repositories {
mavenLocal()
}
そして、ターミナルでカスタムタスクを叩いてみます。
./gradlew printCompanyGreeting
実行結果:
> Task :printCompanyGreeting
==================================================
[Info] このプロジェクトは社内標準ビルド規約が適用されています。
==================================================
BUILD SUCCESSFUL in 1s
見事に、別プロジェクトから自作のカスタムプラグインのロジックが呼び出されました!
—
まとめ
今回は、Gradleのプラグイン開発をスタンドアロンなプロジェクトとして構築し、テストコードを書き、ローカル環境で再利用・検証するまでの全ステップを解説しました。
- `buildSrc`の呪縛からの解放: バイナリとして独立させることで、ビルドキャッシュを健全に保ちつつ、組織全体でビルドロジックを共有できる。
- 高い信頼性: `GradleRunner` を用いたテスト駆動開発(TDD)により、プラグイン自体の品質を担保できる。
これを社内のプライベートMavenリポジトリ(NexusやGitHub Packagesなど)に組み込めば、社内のすべてのJava/Kotlin開発チームに一瞬で最新のビルド標準を配信できるようになります。
毎日の「また同じ設定をコピペしてる……」というストレスから解放され、よりクリエイティブなコードを書く時間に没頭できるようになりますよ。ぜひ、あなたの現場でも試してみてください!