Skip to content

Commit

Permalink
Update Maven tasks config to improve caching (#3480)
Browse files Browse the repository at this point in the history
- implement custom MvnExec task, so it's easier to define inputs/outputs and path sensitivity, rather than having a load of Exec tasks with `outputs.cacheIf { true }`.
- Manually remove timestamps from generated properties files.
- Refactor Maven tasks to use new MvnExec task.
- Add constant `project.build.outputTimestamp` to POM
  • Loading branch information
adam-enko committed Feb 12, 2024
1 parent 96fce04 commit 1877ec4
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 33 deletions.
25 changes: 20 additions & 5 deletions build-logic/src/main/kotlin/dokkabuild.setup-maven-cli.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

import dokkabuild.tasks.MvnExec
import org.gradle.kotlin.dsl.support.serviceOf

/**
Expand Down Expand Up @@ -33,6 +34,10 @@ abstract class MavenCliSetupExtension {
* * Unix: `$mavenInstallDir/bin/mvn`
*/
abstract val mvn: RegularFileProperty

companion object {
const val MAVEN_PLUGIN_GROUP = "maven plugin"
}
}

val mavenCliSetupExtension =
Expand Down Expand Up @@ -84,11 +89,12 @@ val installMavenBinary by tasks.registering(Sync::class) {
val archives = serviceOf<ArchiveOperations>()
from(
mavenBinary.flatMap { conf ->
val resolvedArtifacts = conf.incoming.artifacts.resolvedArtifacts

resolvedArtifacts.map { artifacts ->
artifacts.map { archives.zipTree(it.file) }
}
conf.incoming
.artifacts
.resolvedArtifacts
.map { artifacts ->
artifacts.map { archives.zipTree(it.file) }
}
}
) {
eachFile {
Expand All @@ -99,3 +105,12 @@ val installMavenBinary by tasks.registering(Sync::class) {
}
into(mavenCliSetupExtension.mavenInstallDir)
}

tasks.withType<MvnExec>().configureEach {
group = MavenCliSetupExtension.MAVEN_PLUGIN_GROUP
dependsOn(installMavenBinary)
mvnCli.convention(mavenCliSetupExtension.mvn)
workDirectory.convention(layout.dir(provider { temporaryDir }))
showErrors.convention(true)
batchMode.convention(true)
}
107 changes: 107 additions & 0 deletions build-logic/src/main/kotlin/dokkabuild/tasks/MvnExec.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package dokkabuild.tasks

import org.gradle.api.DefaultTask
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.PathSensitivity.NONE
import org.gradle.api.tasks.PathSensitivity.RELATIVE
import org.gradle.process.ExecOperations
import org.gradle.work.NormalizeLineEndings
import java.util.*
import javax.inject.Inject

/**
* Runs a Maven task.
*
* See `dokkabuild.setup-maven-cli.gradle.kts` for details on the Maven CLI installation.
*/
@CacheableTask
abstract class MvnExec
@Inject
constructor(
private val exec: ExecOperations,
private val fs: FileSystemOperations,
) : DefaultTask() {

/**
* Work directory.
*
* Be aware that any existing content will be replaced by [inputFiles].
*/
@get:OutputDirectory
abstract val workDirectory: DirectoryProperty

/** Input files - will be synced to [workDirectory]. */
@get:InputFiles
@get:PathSensitive(RELATIVE)
@get:NormalizeLineEndings
abstract val inputFiles: ConfigurableFileCollection

@get:InputFile
@get:PathSensitive(NONE)
abstract val mvnCli: RegularFileProperty

@get:Input
abstract val arguments: ListProperty<String>

/** `-e` - Produce execution error messages. */
@get:Input
@get:Optional
abstract val showErrors: Property<Boolean>

/** `-B` - Run in non-interactive (batch) mode. */
@get:Input
@get:Optional
abstract val batchMode: Property<Boolean>

@TaskAction
fun exec() {
fs.sync {
from(inputFiles)
into(workDirectory)
}

val arguments = buildList {
addAll(arguments.get())
if (showErrors.orNull == true) add("--errors")
if (batchMode.orNull == true) add("--batch-mode")
}

exec.exec {
workingDir(workDirectory)
executable(mvnCli.get())
args(arguments)
}

makePropertiesFilesReproducible()
}

/**
* Remove non-reproducible timestamps from any generated [Properties] files.
*/
private fun makePropertiesFilesReproducible() {
workDirectory.get().asFile.walk()
.filter { it.isFile && it.extension == "properties" }
.forEach { file ->
logger.info("[MvnExec $path] removing timestamp from $file")
// drop the last comment - java.util.Properties always adds a timestamp, which is not-reproducible.
val comments = file.readLines()
.takeWhile { it.startsWith('#') }
.dropLast(1)

val properties = file.readLines().dropWhile { it.startsWith('#') }

val updatedProperties = (comments + properties).joinToString("\n")
file.writeText(updatedProperties)
}
}
}
55 changes: 27 additions & 28 deletions dokka-runners/runner-maven-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

import dokkabuild.overridePublicationArtifactId
import dokkabuild.tasks.MvnExec

plugins {
id("dokkabuild.kotlin-jvm")
Expand Down Expand Up @@ -49,46 +50,41 @@ val generatePom by tasks.registering(Sync::class) {
into(temporaryDir)
}

val prepareHelpMojoDir by tasks.registering(Sync::class) {
description = "Prepare files for generating the Maven Plugin HelpMojo"
group = mavenPluginTaskGroup

into(layout.buildDirectory.dir("maven-help-mojo"))
from(generatePom)
}

val helpMojo by tasks.registering(Exec::class) {
val generateHelpMojo by tasks.registering(MvnExec::class) {
description = "Generate the Maven Plugin HelpMojo"
group = mavenPluginTaskGroup

dependsOn(tasks.installMavenBinary, prepareHelpMojoDir)

workingDir(prepareHelpMojoDir.map { it.destinationDir })
executable(mavenCliSetup.mvn.get())
args("-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:helpmojo")

outputs.dir(workingDir)
inputFiles.from(generatePom)
arguments.addAll(
"org.apache.maven.plugins:maven-plugin-plugin:helpmojo"
)
}

val helpMojoSources by tasks.registering(Sync::class) {
description = "Sync the HelpMojo source files into a SourceSet SrcDir"
group = mavenPluginTaskGroup
from(helpMojo) {

from(generateHelpMojo) {
eachFile {
// drop 2 leading directories
relativePath = RelativePath(true, *relativePath.segments.drop(2).toTypedArray())
}
}
includeEmptyDirs = false

into(temporaryDir)

include("**/*.java")
}

val helpMojoResources by tasks.registering(Sync::class) {
description = "Sync the HelpMojo resource files into a SourceSet SrcDir"
group = mavenPluginTaskGroup
from(helpMojo)

from(generateHelpMojo)

into(temporaryDir)

include("**/**")
exclude("**/*.java")
}
Expand All @@ -103,29 +99,32 @@ val preparePluginDescriptorDir by tasks.registering(Sync::class) {
description = "Prepare files for generating the Maven Plugin descriptor"
group = mavenPluginTaskGroup

into(layout.buildDirectory.dir("maven-plugin-descriptor"))

from(tasks.compileKotlin) { into("classes/java/main") }
from(tasks.compileJava) { into("classes/java/main") }
from(helpMojoResources)

into(temporaryDir)
}

val pluginDescriptor by tasks.registering(Exec::class) {
val generatePluginDescriptor by tasks.registering(MvnExec::class) {
description = "Generate the Maven Plugin descriptor"
group = mavenPluginTaskGroup

dependsOn(tasks.installMavenBinary, preparePluginDescriptorDir)

workingDir(preparePluginDescriptorDir.map { it.destinationDir })
executable(mavenCliSetup.mvn.get())
args("-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:descriptor")
inputFiles.from(preparePluginDescriptorDir)

outputs.dir("$workingDir/classes/java/main/META-INF/maven")
arguments.addAll(
"org.apache.maven.plugins:maven-plugin-plugin:descriptor"
)
}

val pluginDescriptorMetaInf: Provider<RegularFile> =
generatePluginDescriptor.flatMap {
it.workDirectory.file("classes/java/main/META-INF/maven")
}

tasks.jar {
metaInf {
from(pluginDescriptor) {
from(pluginDescriptorMetaInf) {
into("maven")
}
}
Expand Down
1 change: 1 addition & 0 deletions dokka-runners/runner-maven-plugin/pom.template.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<version>${dokka_version}</version>
<packaging>maven-plugin</packaging>
<properties>
<project.build.outputTimestamp>2024-01-01T00:00:00Z</project.build.outputTimestamp>
<maven.version>${mavenVersion}</maven.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Expand Down

0 comments on commit 1877ec4

Please sign in to comment.