JUnit 5のビルドシステムを探る(その2)

<img width="1240" height="112" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/6d8a7098-9aef-a19a-54fe-83a2d493e033.png" alt="YUMEMI New Grad Advent Calendar 2023">

前回はJUnit 5のリポジトリの構成を見ていきました。今回は各プロジェクトで共通に使用されているプラグインについてみていきます。

JUnit 5のライセンス Eclipse Public License - v 2.0

https://github.com/junit-team/junit5/blob/main/LICENSE.md

JUnit 5のリポジトリ

https://github.com/junit-team/junit5

この記事は [`f5b78f68c6a90dfa63611c7a10027581c5d913ba`](https://github.com/junit-team/junit5/tree/f5b78f68c6a90dfa63611c7a10027581c5d913ba) での内容をベースにしています。
記事の中に出てくるコードはすべて上記のリポジトリからの引用です。

# 概要

* [JUnit 5リポジトリの構成について](https://qiita.com/k-kojima-yumemi/items/f05aaf38b77abd45db41)
* 共通で使われている設定について <この記事>
* バージョンの記述について
* 個々のプロジェクトの設定について

前回の記事

https://qiita.com/k-kojima-yumemi/private/f05aaf38b77abd45db41

前回は `gradle` ディレクトリ以下にプロジェクト共通で使用されている設定やプラグインのファイルが置かれていることを確認しました。

今回は共通の設定を定義しているプラグインについてみていきます。

# 共通で使われている設定について

JUnit 5ではマルチプロジェクトの構成がとられています。
前回見た通り、 `settings.gradle.kts` ファイルで各サブプロジェクトの読み込みをしています。

公式のドキュメントはこちらです。

https://docs.gradle.org/current/userguide/multi_project_builds.html

JUnit 5では各サブプロジェクトに `<project name>.gradle.kts` ファイルが置かれそのファイルを読み込むよう設定されています。ドキュメントの例では `build.gradle.kts` が置かれている点が異なりますが同じように動作します。

サブプロジェクトを定義すると、共通な設定の記述をまとめたくなります。そこでGradleでは2種類の方法で設定を共有することができます。

https://docs.gradle.org/current/userguide/sharing_build_logic_between_subprojects.html

1. Convention Pluginsの定義
1. `subprojects {}` や `allprojects {}` を使う方法

JUnit 5では1つ目のConvention Pluginsの方法がとられています。
このプラグインたちは `gradle/plugins` 以下に置かれています。`settings.gradle.kts` ファイルで `includeBuild` されているディレクトリです。
このディレクトの中にbuild-parametersとcommonのサブプロジェクト(プラグイン)があり、`gradle/plugins/settings.gradle.kts` から読み込まれています。

```kotlin
pluginManagement {
	includeBuild("gradle/plugins")
	repositories {
		gradlePluginPortal()
	}
}
```

## build-parameters

https://github.com/junit-team/junit5/blob/main/gradle/plugins/build-parameters/build.gradle.kts

このプラグインではビルド時に使われる各種変数の管理をしています。
[`org.gradlex.build-parameters`](https://github.com/gradlex-org/build-parameters) のプラグインを利用し変数を定義しています。
CIで実行しているか、テスト時の設定、公開時の署名の設定などの変数がまとめられています。

```kotlin
bool("ci") {
    description = "Whether or not this build is running in a CI environment"
    defaultValue = false
    fromEnvironment()
}
```
このような記述で各プロジェクトで使える変数として設定しています。

## common

https://github.com/junit-team/junit5/tree/main/gradle/plugins/common/src/main/kotlin

このディレクトリの配下にある、`gradle.kts` のファイルが全てプラグインです。拡張子が `kt` のファイルはKotlinで記述されたデータ構造や拡張関数、タスクです。

### `gradle/plugins/common/build.gradle.kts`

まず `gradle/plugins/common/build.gradle.kts` のファイルを見てみます。

https://github.com/junit-team/junit5/blob/main/gradle/plugins/common/build.gradle.kts

このファイルではcommon配下のプラグインで参照されているプラグインのバージョンを定義しています。
`dependencies` のブロックの中の、`implementation` でバージョンを定義しています。

```kotlin
dependencies {
	implementation(projects.buildParameters)
	implementation(kotlin("gradle-plugin"))
	implementation(libs.gradle.bnd)
	implementation(libs.gradle.commonCustomUserData)
	implementation(libs.gradle.enterprise)
	implementation(libs.gradle.foojayResolver)
	implementation(libs.gradle.shadow)
	implementation(libs.gradle.spotless)
	implementation(libs.gradle.versions)
}
```

(`libs.gradle.*` のような表記になっていますが、これでバージョンごと定義したことになります。詳しくは次回見ていきます)

### `junitbuild.base-conventions.gradle.kts`

次にプラグインの例として `junitbuild.base-conventions.gradle.kts` のファイルを見てみます。

https://github.com/junit-team/junit5/blob/main/gradle/plugins/common/src/main/kotlin/junitbuild.base-conventions.gradle.kts

このファイルでは他のプラグイン(eclipe, idea, common配下のプラグイン)への依存関係が記述されています。

```kotlin
plugins {
	eclipse
	idea
	id("junitbuild.java-toolchain-conventions")
	id("junitbuild.spotless-conventions")
}
```

`junitbuild.base-conventions` のプラグインを使うだけで、他のプラグインへの依存関係を定義したことになります。

### `junitbuild.kotlin-library-conventions.gradle.kts`

もう少し複雑な定義の例として `junitbuild.kotlin-library-conventions.gradle.kts` のファイルを見ていきます。

https://github.com/junit-team/junit5/blob/main/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts

このファイルではKotlinのビルドに関する設定が記述されています。
バージョンを設定するプラグインを用意しておくことで、どのプロジェクトでも同じKotlinのライブラリを使用して開発やビルドができます。

```kotlin
tasks.withType<KotlinCompile>().configureEach {
	kotlinOptions {
		apiVersion = "1.6"
		languageVersion = "1.6"
		allWarningsAsErrors = false
	}
}
```

またビルド時のJavaのバージョンの指定も行っています。
```kotlin
tasks {
    withType<KotlinCompile>().configureEach {
        kotlinOptions.jvmTarget = extension.mainJavaVersion.toString()
    }
}
```

ここのプロジェクトで指定すると漏れが出てきてしまうような項目も、プラグインで共通化することで設定しやすくできます。

# おわりに

今回は各プロジェクトで共通に使用されているプラグインについてみていきました。
今回紹介していないファイルにも様々な設定が書かれていますので参考になります。
Build ScanのPluginsを参照するとどのプロジェクトにどのプラグインが設定されているかわかります。

次回はバージョンの記述についてみていきます。