diff options
-rw-r--r-- | build-logic/src/main/kotlin/org/jetbrains/conventions/maven-cli-setup.gradle.kts | 103 | ||||
-rw-r--r-- | gradle.properties | 3 | ||||
-rw-r--r-- | integration-tests/maven/build.gradle.kts | 13 | ||||
-rw-r--r-- | runners/maven-plugin/build.gradle.kts | 117 | ||||
-rw-r--r-- | runners/maven-plugin/pom.template.xml (renamed from runners/maven-plugin/pom.tpl.xml) | 6 |
5 files changed, 182 insertions, 60 deletions
diff --git a/build-logic/src/main/kotlin/org/jetbrains/conventions/maven-cli-setup.gradle.kts b/build-logic/src/main/kotlin/org/jetbrains/conventions/maven-cli-setup.gradle.kts new file mode 100644 index 00000000..ec59da7b --- /dev/null +++ b/build-logic/src/main/kotlin/org/jetbrains/conventions/maven-cli-setup.gradle.kts @@ -0,0 +1,103 @@ +package org.jetbrains.conventions + +import org.gradle.kotlin.dsl.support.serviceOf + +/** + * Utility for downloading and installing a Maven binary. + * + * Provides the `setupMavenProperties` extension that contains the default versions and locations + * of the Maven binary. + * + * The task [installMavenBinary] will download and unzip the Maven bianry. + */ + +plugins { + base +} + +abstract class SetupMavenProperties { + abstract val mavenVersion: Property<String> + abstract val mavenPluginToolsVersion: Property<String> + abstract val mavenBuildDir: DirectoryProperty + + /** Directory that will contain the unpacked Apache Maven dependency */ + abstract val mavenInstallDir: DirectoryProperty + + /** + * Path to the Maven executable. + * + * This should be different per OS: + * + * * Windows: `$mavenInstallDir/bin/mvn.cmd` + * * Unix: `$mavenInstallDir/bin/mvn` + */ + abstract val mvn: RegularFileProperty +} + +val setupMavenProperties = + extensions.create("setupMavenProperties", SetupMavenProperties::class).apply { + mavenVersion.convention(providers.gradleProperty("mavenVersion")) + mavenPluginToolsVersion.convention(providers.gradleProperty("mavenPluginToolsVersion")) + + mavenBuildDir.convention(layout.buildDirectory.dir("maven")) + mavenInstallDir.convention(layout.buildDirectory.dir("apache-maven")) + + val isWindowsProvider = + providers.systemProperty("os.name").map { "win" in it.toLowerCase() } + + mvn.convention( + providers.zip(mavenInstallDir, isWindowsProvider) { mavenInstallDir, isWindows -> + mavenInstallDir.file( + when { + isWindows -> "bin/mvn.cmd" + else -> "bin/mvn" + } + ) + } + ) + } + +val mavenBinary by configurations.registering { + description = "used to download the Maven binary" + isCanBeResolved = true + isCanBeConsumed = false + isVisible = false + + defaultDependencies { + addLater(setupMavenProperties.mavenVersion.map { mavenVersion -> + project.dependencies.create( + group = "org.apache.maven", + name = "apache-maven", + version = mavenVersion, + classifier = "bin", + ext = "zip" + ) + }) + } +} + +tasks.clean { + delete(setupMavenProperties.mavenBuildDir) + delete(setupMavenProperties.mavenInstallDir) +} + +val installMavenBinary by tasks.registering(Sync::class) { + val archives = serviceOf<ArchiveOperations>() + from( + mavenBinary.flatMap { conf -> + @Suppress("UnstableApiUsage") + val resolvedArtifacts = conf.incoming.artifacts.resolvedArtifacts + + resolvedArtifacts.map { artifacts -> + artifacts.map { archives.zipTree(it.file) } + } + } + ) { + eachFile { + // drop the first directory inside the zipped Maven bin (apache-maven-$version) + relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray()) + } + includeEmptyDirs = false + } + into(setupMavenProperties.mavenInstallDir) +} diff --git a/gradle.properties b/gradle.properties index a8eb1eff..d68155d7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,6 +14,9 @@ jackson_version=2.12.7 # fixes CVE-2022-42003 jackson_databind_version=2.12.7.1 freemarker_version=2.3.31 +# Dokka Maven Plugin versions +mavenVersion=3.5.0 +mavenPluginToolsVersion=3.5.2 # Code style kotlin.code.style=official # Gradle settings diff --git a/integration-tests/maven/build.gradle.kts b/integration-tests/maven/build.gradle.kts index 4b8b6011..a2e7c440 100644 --- a/integration-tests/maven/build.gradle.kts +++ b/integration-tests/maven/build.gradle.kts @@ -1,12 +1,10 @@ -import org.jetbrains.SetupMaven import org.jetbrains.dependsOnMavenLocalPublication plugins { id("org.jetbrains.conventions.dokka-integration-test") + id("org.jetbrains.conventions.maven-cli-setup") } -evaluationDependsOn(":runners:maven-plugin") - dependencies { implementation(project(":integration-tests")) implementation(kotlin("stdlib")) @@ -16,10 +14,13 @@ dependencies { tasks.integrationTest { dependsOnMavenLocalPublication() - val setupMavenTask = project(":runners:maven-plugin").tasks.withType<SetupMaven>().single() - dependsOn(setupMavenTask) + dependsOn(tasks.installMavenBinary) + val mvn = setupMavenProperties.mvn + inputs.file(mvn) val dokka_version: String by project environment("DOKKA_VERSION", dokka_version) - environment("MVN_BINARY_PATH", setupMavenTask.mvn.absolutePath) + doFirst("workaround for https://github.com/gradle/gradle/issues/24267") { + environment("MVN_BINARY_PATH", mvn.get().asFile.invariantSeparatorsPath) + } } diff --git a/runners/maven-plugin/build.gradle.kts b/runners/maven-plugin/build.gradle.kts index f8badf8e..90f2ffef 100644 --- a/runners/maven-plugin/build.gradle.kts +++ b/runners/maven-plugin/build.gradle.kts @@ -1,82 +1,97 @@ -import org.jetbrains.CrossPlatformExec -import org.jetbrains.SetupMaven +import org.gradle.kotlin.dsl.support.appendReproducibleNewLine import org.jetbrains.registerDokkaArtifactPublication plugins { id("org.jetbrains.conventions.kotlin-jvm") id("org.jetbrains.conventions.maven-publish") + id("org.jetbrains.conventions.maven-cli-setup") } -val setupMaven by tasks.register<SetupMaven>("setupMaven") - dependencies { implementation(project(":core")) - implementation("org.apache.maven:maven-core:${setupMaven.mavenVersion}") - implementation("org.apache.maven:maven-plugin-api:${setupMaven.mavenVersion}") - implementation("org.apache.maven.plugin-tools:maven-plugin-annotations:${setupMaven.mavenPluginToolsVersion}") + implementation("org.apache.maven:maven-core:${setupMavenProperties.mavenVersion.get()}") + implementation("org.apache.maven:maven-plugin-api:${setupMavenProperties.mavenVersion.get()}") + implementation("org.apache.maven.plugin-tools:maven-plugin-annotations:${setupMavenProperties.mavenPluginToolsVersion.get()}") implementation("org.apache.maven:maven-archiver:2.5") implementation(kotlin("stdlib-jdk8")) } -val mavenBuildDir = setupMaven.mavenBuildDir -val mavenBinDir = setupMaven.mavenBinDir - -tasks.clean { - delete(mavenBuildDir) - delete(mavenBinDir) -} +val mavenPluginTaskGroup = "maven plugin" -val generatePom by tasks.registering(Copy::class) { +val generatePom by tasks.registering(Sync::class) { description = "Generate pom.xml for Maven Plugin Plugin" + group = mavenPluginTaskGroup val dokka_version: String by project inputs.property("dokka_version", dokka_version) - from("$projectDir/pom.tpl.xml") { - rename("(.*).tpl.xml", "$1.xml") - } - into(setupMaven.mavenBuildDir) - - eachFile { - filter { line -> - line.replace("<maven.version></maven.version>", "<maven.version>${setupMaven.mavenVersion}</maven.version>") - } - filter { line -> - line.replace("<version>dokka_version</version>", "<version>$dokka_version</version>") - } - filter { line -> - line.replace( - "<version>maven-plugin-plugin</version>", - "<version>${setupMaven.mavenPluginToolsVersion}</version>" - ) - } + val pomTemplateFile = layout.projectDirectory.file("pom.template.xml") + + val mavenVersion = setupMavenProperties.mavenVersion.get() + val mavenPluginToolsVersion = setupMavenProperties.mavenPluginToolsVersion.get() + + from(pomTemplateFile) { + rename { it.replace(".template.xml", ".xml") } + + expand( + "mavenVersion" to mavenVersion, + "dokka_version" to dokka_version, + "mavenPluginToolsVersion" to mavenPluginToolsVersion, + ) } + + into(temporaryDir) } -val syncClasses by tasks.registering(Sync::class) { - description = "Copy compiled classes to the Maven build dir, for Maven Plugin task execution" +val prepareMavenPluginBuildDir by tasks.registering(Sync::class) { + description = "Prepares all files for Maven Plugin task execution" + group = mavenPluginTaskGroup + + from(tasks.compileKotlin.flatMap { it.destinationDirectory }) { into("classes/java/main") } + from(tasks.compileJava.flatMap { it.destinationDirectory }) { into("classes/java/main") } - dependsOn(tasks.compileKotlin, tasks.compileJava) - from("$buildDir/classes/kotlin", "$buildDir/classes/java") - into("${setupMaven.mavenBuildDir}/classes/java") + from(generatePom) - preserve { - include("**/*.class") + into(setupMavenProperties.mavenBuildDir) +} + +val helpMojo by tasks.registering(Exec::class) { + group = mavenPluginTaskGroup + + dependsOn(tasks.installMavenBinary, prepareMavenPluginBuildDir) + + workingDir(setupMavenProperties.mavenBuildDir) + executable(setupMavenProperties.mvn.get()) + args("-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:helpmojo") + + outputs.dir(setupMavenProperties.mavenBuildDir) + + doLast("normalize maven-plugin-help.properties") { + // The maven-plugin-help.properties file contains a timestamp by default. + // It should be removed as it is not reproducible and impacts Gradle caching + val pluginHelpProperties = workingDir.resolve("maven-plugin-help.properties") + pluginHelpProperties.writeText( + buildString { + val lines = pluginHelpProperties.readText().lines().iterator() + // the first line is a descriptive comment + appendReproducibleNewLine(lines.next()) + // the second line is the timestamp, which should be ignored + lines.next() + // the remaining lines are properties + lines.forEach { appendReproducibleNewLine(it) } + } + ) } } -val helpMojo by tasks.registering(CrossPlatformExec::class) { - dependsOn(setupMaven, generatePom, syncClasses) - workingDir(setupMaven.mavenBuildDir) - commandLine(setupMaven.mvn, "-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:helpmojo") +val pluginDescriptor by tasks.registering(Exec::class) { + group = mavenPluginTaskGroup - outputs.dir(layout.buildDirectory.dir("maven")) -} + dependsOn(tasks.installMavenBinary, prepareMavenPluginBuildDir) -val pluginDescriptor by tasks.registering(CrossPlatformExec::class) { - dependsOn(setupMaven, generatePom, syncClasses) - workingDir(setupMaven.mavenBuildDir) - commandLine(setupMaven.mvn, "-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:descriptor") + workingDir(setupMavenProperties.mavenBuildDir) + executable(setupMavenProperties.mvn.get()) + args("-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:descriptor") outputs.dir(layout.buildDirectory.dir("maven/classes/java/main/META-INF/maven")) } @@ -84,7 +99,7 @@ val pluginDescriptor by tasks.registering(CrossPlatformExec::class) { tasks.jar { dependsOn(pluginDescriptor, helpMojo) metaInf { - from("${setupMaven.mavenBuildDir}/classes/java/main/META-INF") + from(setupMavenProperties.mavenBuildDir.map { it.dir("classes/java/main/META-INF") }) } manifest { attributes("Class-Path" to configurations.runtimeClasspath.map { configuration -> diff --git a/runners/maven-plugin/pom.tpl.xml b/runners/maven-plugin/pom.template.xml index c5883c6a..97db90ee 100644 --- a/runners/maven-plugin/pom.tpl.xml +++ b/runners/maven-plugin/pom.template.xml @@ -4,17 +4,17 @@ <modelVersion>4.0.0</modelVersion> <groupId>org.jetbrains.dokka</groupId> <artifactId>dokka-maven-plugin</artifactId> - <version>dokka_version</version> + <version>${dokka_version}</version> <packaging>maven-plugin</packaging> <properties> - <maven.version></maven.version> + <maven.version>${mavenVersion}</maven.version> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-plugin-plugin</artifactId> - <version>maven-plugin-plugin</version> + <version>${mavenPluginToolsVersion}</version> <configuration> <helpPackageName>org.jetbrains.dokka.maven</helpPackageName> </configuration> |