您可以使用 IntelliJ 原生导入器 或 Eclipse Buildship 在 IDE 中打开此示例。 |
此示例展示了如何将构建逻辑组织成可重用的部分,并发布到存储库中,以便在其他项目中重复使用,用于多仓库设置。
此示例展示了如何采用 现有示例 用于测试套件。 |
测试套件是一个 孵化 功能,此处描述的详细信息可能会更改。 |
用例
例如,假设一个组织生产两种类型的 Java 软件 - 服务和库。我们希望对这两种类型的项目应用一组代码质量检查规则,并配置特定于每种类型的某些方面。
组织构建逻辑
该用例可以通过分层三个独立的插件来建模
├── convention-plugins
│ ├── build.gradle.kts
│ ├── settings.gradle.kts
│ ├── src
│ │ ├── main
│ │ │ └── kotlin
│ │ │ ├── com.myorg.java-conventions.gradle.kts
│ │ │ ├── com.myorg.library-conventions.gradle.kts
│ │ │ └── com.myorg.service-conventions.gradle.kts
...
├── convention-plugins
│ ├── build.gradle
│ ├── settings.gradle
│ ├── src
│ │ ├── main
│ │ │ └── groovy
│ │ │ ├── com.myorg.java-conventions.gradle
│ │ │ ├── com.myorg.library-conventions.gradle
│ │ │ └── com.myorg.service-conventions.gradle
...
-
com.myorg.java-conventions
- 配置适用于组织中任何 Java 项目的通用约定。这适用于之前识别的两种类型的软件,因此该插件将在后续的两个插件中应用。 -
com.myorg.library-conventions
- 添加发布配置以发布到组织的存储库,并配置强制文档检查。 -
com.myorg.service-conventions
- 配置集成测试并检查 README 中的强制内容。由于服务不同于库,因此在这种情况下会配置不同的文档要求。
在本示例中创建的所有插件都包含使用 TestKit 验证其行为的功能测试。
编译约定插件
在本示例中,约定插件被实现为 预编译脚本插件 - 这是最简单的入门方式,因为您可以直接使用 Gradle 的 DSL 之一来实现构建逻辑,就像插件是常规构建脚本一样。
为了使预编译脚本插件能够被发现,convention-plugins
项目需要在其 build.gradle.kts
文件中应用 kotlin-dsl
插件
为了使预编译脚本插件能够被发现,convention-plugins
项目需要在其 build.gradle
文件中应用 groovy-gradle-plugin
插件
plugins {
`kotlin-dsl`
}
plugins {
id 'groovy-gradle-plugin'
}
发布约定插件
在本示例中,我们针对的是多仓库设置。为了将上述插件应用于单独的项目,它们必须发布到公司的工件仓库。约定插件是常规的 Gradle 插件 - 因此它们可以 发布到像任何其他 Gradle 插件一样的外部仓库。
在这里,我们使用 maven-publish 插件 配置项目以发布插件。出于演示目的,我们发布到本地文件系统目录。您可以在 maven-publish 插件的仓库部分 中找到有关如何发布到远程仓库的信息。
plugins {
`kotlin-dsl`
`maven-publish`
}
group = "com.myorg.conventions"
version = "1.0"
publishing {
repositories {
maven {
// change to point to your repo, e.g. http://my.org/repo
url = uri(layout.buildDirectory.dir("repo"))
}
}
}
tasks.publish {
dependsOn("check")
}
plugins {
id 'groovy-gradle-plugin'
id 'maven-publish'
id 'java'
}
group = 'com.myorg.conventions'
version = '1.0'
publishing {
repositories {
maven {
// change to point to your repo, e.g. http://my.org/repo
url = layout.buildDirectory.dir("repo")
}
}
}
tasks.named('publish') {
dependsOn('check')
}
可以使用以下方法发布插件
./gradlew publish
为了在另一个项目中使用它们,请在 settings 文件中配置插件仓库并应用插件
pluginManagement {
repositories {
gradlePluginPortal()
maven {
// replace the path with the actual path to the repository
url = uri("<path-to>/convention-plugins/build/repo")
}
}
}
plugins {
id("com.myorg.service-conventions") version "1.0"
}
pluginManagement {
repositories {
gradlePluginPortal()
maven {
// replace the path with the actual path to the repository
url = uri('<path-to>/convention-plugins/build/repo')
}
}
}
plugins {
id 'com.myorg.service-conventions' version '1.0'
}
注意事项
在约定插件中应用外部插件
com.myorg.java-conventions
插件使用 SpotBugs 插件执行静态代码分析。
SpotBugs 是一个外部插件 - 外部插件 需要作为实现依赖项添加 才能在约定插件中应用。
repositories {
gradlePluginPortal() // so that external plugins can be resolved in dependencies section
}
dependencies {
implementation("com.github.spotbugs.snom:spotbugs-gradle-plugin:5.2.1")
}
repositories {
gradlePluginPortal() // so that external plugins can be resolved in dependencies section
}
dependencies {
implementation 'com.github.spotbugs.snom:spotbugs-gradle-plugin:5.2.1'
}
-
插件的依赖项工件坐标 (GAV) 可能与插件 ID 不同。
-
Gradle 插件门户 (
gradlePluginPortal()
) 被添加为插件依赖项的仓库。 -
插件版本由依赖项版本确定。
添加依赖项后,可以通过 ID 在约定插件中应用外部插件。
plugins {
java
checkstyle
// NOTE: external plugin version is specified in implementation dependency artifact of the project's build file
id("com.github.spotbugs")
}
plugins {
id 'java'
id 'checkstyle'
// NOTE: external plugin version is specified in implementation dependency artifact of the project's build file
id 'com.github.spotbugs'
}
应用其他约定插件
约定插件可以应用其他约定插件。
com.myorg.library-conventions
和 com.myorg.service-conventions
插件都应用了 com.myorg.java-conventions
插件。
plugins {
`java-library`
`maven-publish`
id("com.myorg.java-conventions")
}
plugins {
id("com.myorg.java-conventions")
}
plugins {
id 'java-library'
id 'maven-publish'
id 'com.myorg.java-conventions'
}
plugins {
id 'com.myorg.java-conventions'
}
使用主源集中的类
约定插件可以使用插件项目主源集中定义的类。
在本示例中,com.myorg.service-conventions
插件使用来自 src/main/java
的自定义任务类来配置服务 README 检查。
val readmeCheck by tasks.registering(com.example.ReadmeVerificationTask::class) {
readme = layout.projectDirectory.file("README.md")
readmePatterns = listOf("^## Service API$")
}
def readmeCheck = tasks.register('readmeCheck', com.example.ReadmeVerificationTask) {
// Expect the README in the project directory
readme = layout.projectDirectory.file("README.md")
// README must contain a Service API header
readmePatterns = ['^## Service API$']
}
有关编写自定义 Gradle 插件的更多详细信息,请参阅 用户手册。