Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make plugin configuration cache compatible #148

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2020 Benedikt Ritter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package de.benediktritter.maven.plugin.development

import groovy.transform.Memoized
import org.gradle.testkit.runner.TaskOutcome
import spock.lang.Issue
import spock.lang.Requires

@Requires(value = { configurationSupported() }, reason = "Configuration Cache was added in Gradle 6.6")
class ConfigurationCacheFuncTest extends AbstractPluginFuncTest {

@Issue("https://github.com/britter/maven-plugin-development/issues/8")
def "tasks are configuration cache compatible"() {
given:
javaMojo()

when:
def result = run("build", "--configuration-cache")

then:
Exception e = thrown()
result.task(":generateMavenPluginHelpMojoSources").outcome == TaskOutcome.SUCCESS
result.task(":generateMavenPluginDescriptor").outcome == TaskOutcome.SUCCESS
}

@Memoized
static boolean configurationSupported() {
def gradleVersion = (System.getProperty("compat.gradle.version") =~ /^(?<major>\d+)\.(?<minor>\d+)/)
if (gradleVersion.find()) {
def major = gradleVersion.group("major") as int
def minor = gradleVersion.group("minor") as int

// Configuration cache was introduced in 6.6
return major > 7 || (major == 6 && minor >= 6)
}
return false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
package de.benediktritter.maven.plugin.development

import de.benediktritter.maven.plugin.development.internal.DefaultMavenPluginDevelopmentExtension
import de.benediktritter.maven.plugin.development.internal.Gavt
import de.benediktritter.maven.plugin.development.internal.MavenPluginDescriptor
import de.benediktritter.maven.plugin.development.task.GenerateHelpMojoSourcesTask
import de.benediktritter.maven.plugin.development.task.GenerateMavenPluginDescriptorTask
import de.benediktritter.maven.plugin.development.task.UpstreamProjectDescriptor
import de.benediktritter.maven.plugin.development.task.*
import org.codehaus.plexus.component.repository.ComponentDependency
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.SourceSetContainer
Expand All @@ -32,6 +33,8 @@ import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.the
import java.io.File
import java.nio.file.Path

class MavenPluginDevelopmentPlugin : Plugin<Project> {

Expand Down Expand Up @@ -72,7 +75,15 @@ class MavenPluginDevelopmentPlugin : Plugin<Project> {
extension.goalPrefix.orNull
)
})
runtimeDependencies.set(extension.dependencies)
runtimeDependenciesFiles.from(extension.dependencies.map { toDependenciesFiles(it) })
runtimeDependenciesMetadata.set(extension.dependencies.map { toComponentDependencies(it) })
projectInfo.set(
ProjectInfo(
project.group.toString(),
project.name,
project.version.toString()
)
)
}

val generateTask = tasks.register<GenerateMavenPluginDescriptorTask>("generateMavenPluginDescriptor") {
Expand Down Expand Up @@ -110,7 +121,8 @@ class MavenPluginDevelopmentPlugin : Plugin<Project> {
)
})
additionalMojos.set(extension.mojos)
runtimeDependencies.set(extension.dependencies)
runtimeDependenciesFiles.from(extension.dependencies.map { toDependenciesFiles(it) })
runtimeDependenciesMetadata.set(extension.dependencies.map { toComponentDependencies(it) })

dependsOn(extension.pluginSourceSet.map { it.output }, generateHelpMojoTask)
}
Expand All @@ -120,6 +132,14 @@ class MavenPluginDevelopmentPlugin : Plugin<Project> {
val jarTask: Jar? = tasks.findByName(sourceSet.jarTaskName) as Jar?
jarTask?.from(generateTask)
sourceSet.java.srcDir(generateHelpMojoTask.map { it.outputDirectory })
val pInfo = ProjectInfo(
project.group.toString(),
project.name,
project.version.toString()
)
tasks.withType(AbstractMavenPluginDevelopmentTask::class.java).configureEach {
projectInfo.set(pInfo)
}
}
}

Expand All @@ -129,4 +149,20 @@ class MavenPluginDevelopmentPlugin : Plugin<Project> {
MavenPluginDevelopmentExtension.NAME,
DefaultMavenPluginDevelopmentExtension::class,
this)

private fun toComponentDependencies(configuration: Configuration): List<Gavt> {
return configuration.resolvedConfiguration.resolvedArtifacts.map { artifact ->
Gavt(
artifact.moduleVersion.id.group,
artifact.moduleVersion.id.name,
artifact.moduleVersion.id.version,
artifact.extension ?: "jar"
)
}
}
private fun toDependenciesFiles(configuration: Configuration): List<File> {
return configuration.resolvedConfiguration.resolvedArtifacts.map { artifact ->
artifact.file
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package de.benediktritter.maven.plugin.development.internal

import java.io.Serializable

data class Gavt(val groupId: String, val artifactId: String, val version: String, val type: String = "jar") : Serializable
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@

package de.benediktritter.maven.plugin.development.task

import de.benediktritter.maven.plugin.development.internal.Gavt
import de.benediktritter.maven.plugin.development.internal.MavenPluginDescriptor
import org.apache.maven.plugin.descriptor.PluginDescriptor
import org.apache.maven.project.MavenProject
import org.apache.maven.tools.plugin.DefaultPluginToolsRequest
import org.apache.maven.tools.plugin.PluginToolsRequest
import org.codehaus.plexus.component.repository.ComponentDependency
import org.gradle.api.DefaultTask
import org.gradle.api.artifacts.Configuration
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Classpath
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Nested

Expand All @@ -35,7 +38,13 @@ abstract class AbstractMavenPluginDevelopmentTask : DefaultTask() {
abstract val pluginDescriptor: Property<MavenPluginDescriptor>

@get:[InputFiles Classpath]
abstract val runtimeDependencies: Property<Configuration>
abstract val runtimeDependenciesFiles: ConfigurableFileCollection

@get:Input
abstract val runtimeDependenciesMetadata: ListProperty<Gavt>

@get:Nested
abstract val projectInfo:Property<ProjectInfo>

protected fun createPluginDescriptor(): PluginDescriptor {
val pluginDescriptor = pluginDescriptor.get()
Expand All @@ -47,24 +56,25 @@ abstract class AbstractMavenPluginDevelopmentTask : DefaultTask() {
it.goalPrefix = pluginDescriptor.goalPrefix ?: PluginDescriptor.getGoalPrefixFromArtifactId(artifactId)
it.name = pluginDescriptor.name
it.description = pluginDescriptor.description
it.dependencies = getComponentDependencies()
it.dependencies = toComponentDependencies(runtimeDependenciesMetadata.get())
}
}

private fun getComponentDependencies(): List<ComponentDependency> {
return runtimeDependencies.get().resolvedConfiguration.resolvedArtifacts.map { artifact ->
ComponentDependency().also {
it.groupId = artifact.moduleVersion.id.group
it.artifactId = artifact.moduleVersion.id.name
it.version = artifact.moduleVersion.id.version
it.type = artifact.extension
}
}
}

protected fun createPluginToolsRequest(mavenProject: MavenProject, pluginDescriptor: PluginDescriptor): PluginToolsRequest {
return DefaultPluginToolsRequest(mavenProject, pluginDescriptor).also {
it.isSkipErrorNoDescriptorsFound = true
}
}

private fun toComponentDependencies(list: List<Gavt>): List<ComponentDependency> {
return list.map { artifact ->
ComponentDependency().also {
it.groupId = artifact.groupId
it.artifactId = artifact.artifactId
it.version = artifact.version
it.type = artifact.type
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,32 +42,38 @@ abstract class GenerateHelpMojoSourcesTask : AbstractMavenPluginDevelopmentTask(
@get:Input
abstract val helpMojoPackage: Property<String>

private val loggerAdapter = MavenLoggerAdapter(logger)

private val generator = PluginHelpGenerator().also { gen ->
gen.enableLogging(loggerAdapter)
gen.velocityComponent = createVelocityComponent()
}

@TaskAction
fun generateHelpMojo() {
val loggerAdapter = MavenLoggerAdapter(logger)

val generator = PluginHelpGenerator().also { gen ->
gen.enableLogging(loggerAdapter)
gen.velocityComponent = createVelocityComponent(loggerAdapter)
}
generator.setHelpPackageName(helpMojoPackage.get())
generator.execute(outputDirectory.get().asFile, createPluginToolsRequest(mavenProject(), createPluginDescriptor()))
generator.execute(
outputDirectory.get().asFile,
createPluginToolsRequest(mavenProject(), createPluginDescriptor())
)
}

private fun mavenProject(): MavenProject {
val propertiesDirectory = helpPropertiesFile.get().asFile.parentFile
propertiesDirectory.mkdirs()
return MavenProject().also {
it.groupId = project.group.toString()
it.artifactId = project.name
it.version = project.version.toString()
it.artifact = ProjectArtifact(it)
it.build = Build().also { b -> b.directory = propertiesDirectory.absolutePath }
}
return projectInfo.map { project ->
MavenProject().also {
it.groupId = project.group
it.artifactId = project.name
it.version = project.version
it.artifact = ProjectArtifact(it)
it.build = Build().also { b -> b.directory = propertiesDirectory.absolutePath }
}
}.get()
}

private fun createVelocityComponent(): VelocityComponent {
private fun createVelocityComponent(loggerAdapter: MavenLoggerAdapter): VelocityComponent {
val velocityComponent = DefaultVelocityComponent()
velocityComponent.enableLogging(loggerAdapter)
// initialization as defined by org.codehaus.plexus:plexus-velocity:1.1.8:META-INF/plexus/components.xml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import org.apache.maven.project.MavenProject
import org.apache.maven.project.artifact.ProjectArtifact
import org.apache.maven.tools.plugin.ExtendedMojoDescriptor
import org.apache.maven.tools.plugin.generator.PluginDescriptorGenerator
import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection
import org.gradle.api.provider.ListProperty
Expand Down Expand Up @@ -60,18 +59,12 @@ abstract class GenerateMavenPluginDescriptorTask : AbstractMavenPluginDevelopmen
@get:OutputDirectory
abstract val outputDirectory: DirectoryProperty

private val loggerAdapter = MavenLoggerAdapter(logger)

private val scanner = MavenServiceFactory.createMojoScanner(loggerAdapter)

private val generator = PluginDescriptorGenerator(loggerAdapter)

@TaskAction
fun generateDescriptor() {
checkArtifactId()

val pluginDescriptor = extractPluginDescriptor()
writeDescriptor(pluginDescriptor)
val loggerAdapter = MavenLoggerAdapter(logger)
val pluginDescriptor = extractPluginDescriptor(loggerAdapter)
writeDescriptor(pluginDescriptor, loggerAdapter)
}

private fun checkArtifactId() {
Expand All @@ -81,15 +74,17 @@ abstract class GenerateMavenPluginDescriptorTask : AbstractMavenPluginDevelopmen
}
}

private fun writeDescriptor(pluginDescriptor: PluginDescriptor) {
val mavenProject = mavenProject(project, sourcesDirs.get(), outputDirectory.asFile.get())
private fun writeDescriptor(pluginDescriptor: PluginDescriptor, loggerAdapter: MavenLoggerAdapter) {
val mavenProject = mavenProject(sourcesDirs.get(), outputDirectory.asFile.get())
val generator = PluginDescriptorGenerator(loggerAdapter)
generator.execute(outputDirectory.dir("META-INF/maven").get().asFile, createPluginToolsRequest(mavenProject, pluginDescriptor))
}

private fun extractPluginDescriptor(): PluginDescriptor {
private fun extractPluginDescriptor(loggerAdapter: MavenLoggerAdapter): PluginDescriptor {
val scanner = MavenServiceFactory.createMojoScanner(loggerAdapter)
return createPluginDescriptor().also { pluginDescriptor ->
classesDirs.get().forEach { classesDir ->
val mavenProject = mavenProject(project, sourcesDirs.get(), classesDir)
val mavenProject = mavenProject(sourcesDirs.get(), classesDir)
val pluginToolsRequest = createPluginToolsRequest(mavenProject, pluginDescriptor)
// process upstream projects in order to scan base classes
upstreamProjects.get().forEach {
Expand Down Expand Up @@ -156,8 +151,9 @@ abstract class GenerateMavenPluginDescriptorTask : AbstractMavenPluginDevelopmen
}
}

private fun mavenProject(project: Project, sourcesDirs: FileCollection, outputDirectory: File): MavenProject =
mavenProject(project.group.toString(), project.name, project.version.toString(), sourcesDirs, outputDirectory)
private fun mavenProject(sourcesDirs: FileCollection, outputDirectory: File): MavenProject = projectInfo.map {
mavenProject(it.group, it.name, it.version, sourcesDirs, outputDirectory)
}.get()

private fun mavenProject(
groupId: String,
Expand All @@ -180,4 +176,3 @@ abstract class GenerateMavenPluginDescriptorTask : AbstractMavenPluginDevelopmen
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package de.benediktritter.maven.plugin.development.task

import org.gradle.api.tasks.Input

data class ProjectInfo(@Input val group: String, @Input val name: String, @Input val version: String)