Open melix opened 2 years ago
Thanks for the report.
To start, here's what you'd do to have full control over how the plugin gets applied to individual projects:
# gradle.properties
dependency.analysis.autoapply=false
// root build.gradle
plugins {
id 'com.autonomousapps.dependency-analysis' version '1.0.0-rc06'
}
// every/other/build.gradle
plugins {
id 'com.autonomousapps.dependency-analysis' version '1.0.0-rc06'
}
As you can see, it's the same plugin in both cases. The plugin takes care of determining if it's in the root project or not, and does the right thing. Note that the plugin must be applied to the root, or it will fail. Here's the check it does:
/** Plugin _must_ be applied to the root for it to work. */
private fun Project.checkPluginWasAppliedToRoot() {
// "test" is the name of the dummy project that Kotlin DSL applies a plugin to when generating
// script accessors
if (getExtensionOrNull() == null && rootProject.name != "test") {
throw GradleException("You must apply the plugin to the root project. Current project is $path")
}
}
/** Used for validity check. */
internal fun Project.getExtensionOrNull(): DependencyAnalysisExtension? = rootProject.extensions.findByType()
I am not certain how the above requirement will work out in the presence of your requirement that subprojects be evaluated before the root project.
You asked
Would it make sense to expose a plugin which can be individually applied to a single project instead?
I have considered this but haven't taken any steps to investigate this yet; in fact, that idea was one of the reasons I split up the enormous DependencyAnalysisPlugin.kt
into sub-classes that are pseudo-plugins. I've also wondered about publishing a settings plugin that might be able to safely apply plugins to subprojects, but I haven't looked at that either.
Happy to continue this discussion and see what kinds of solutions we can come up with. Let me know how far you get with the advice at the top of this comment.
hey @melix just curious if you've had a chance to try this out again? No rush of course, just triaging my issues.
I still plan to do it, just didn't have time!
I'm still having troubles even applying what you described. The build fails with:
An exception occurred applying plugin request [id: 'io.micronaut.build.internal.convention-core-library']
> Failed to apply plugin 'io.micronaut.build.internal.convention-core-library'.
> Failed to apply plugin 'io.micronaut.build.internal.convention-library'.
> Failed to apply plugin 'io.micronaut.build.internal.convention-base'.
> Failed to apply plugin 'com.autonomousapps.dependency-analysis'.
> You must apply the plugin to the root project. Current project is :aop
Which I'm pretty sure is the same underlying cause, an evaluation order issue (because of evaluationDependsOn
).
I'm not saying that this is what we should do, but I made progress:https://ge.micronaut.io/s/z5lzhxadcje5m
with this diff:
diff --git a/build-logic/convention/src/main/kotlin/com/autonomousapps/convention/ConventionExtension.kt b/build-logic/convention/src/main/kotlin/com/autonomousapps/convention/ConventionExtension.kt
index fd4872a4..7a53627e 100644
--- a/build-logic/convention/src/main/kotlin/com/autonomousapps/convention/ConventionExtension.kt
+++ b/build-logic/convention/src/main/kotlin/com/autonomousapps/convention/ConventionExtension.kt
@@ -24,7 +24,7 @@ abstract class ConventionExtension(
internal var pomConfiguration: Action<MavenPom>? = null
internal val publishedVersion: Property<String> = project.objects.property(String::class.java)
internal val isSnapshot: Provider<Boolean> = publishedVersion.map {
- it.endsWith("SNAPSHOT")
+ true
}
fun version(version: Any?) {
diff --git a/src/main/kotlin/com/autonomousapps/DependencyAnalysisPlugin.kt b/src/main/kotlin/com/autonomousapps/DependencyAnalysisPlugin.kt
index 5026158c..6ba803a6 100644
--- a/src/main/kotlin/com/autonomousapps/DependencyAnalysisPlugin.kt
+++ b/src/main/kotlin/com/autonomousapps/DependencyAnalysisPlugin.kt
@@ -53,7 +53,7 @@ class DependencyAnalysisPlugin : Plugin<Project> {
// "test" is the name of the dummy project that Kotlin DSL applies a plugin to when generating
// script accessors
if (getExtensionOrNull() == null && rootProject.name != "test") {
- throw GradleException("You must apply the plugin to the root project. Current project is $path")
+ rootProject.pluginManager.apply(DependencyAnalysisPlugin::class.java)
}
}
diff --git a/src/main/kotlin/com/autonomousapps/subplugin/ProjectPlugin.kt b/src/main/kotlin/com/autonomousapps/subplugin/ProjectPlugin.kt
index 686ea071..356ca1f9 100644
--- a/src/main/kotlin/com/autonomousapps/subplugin/ProjectPlugin.kt
+++ b/src/main/kotlin/com/autonomousapps/subplugin/ProjectPlugin.kt
@@ -103,7 +103,7 @@ internal class ProjectPlugin(private val project: Project) {
}
pluginManager.withPlugin(KOTLIN_JVM_PLUGIN) {
logger.log("Adding Kotlin-JVM tasks to ${project.path}")
- configureKotlinJvmProject()
+// configureKotlinJvmProject()
}
pluginManager.withPlugin(JAVA_PLUGIN) {
configureJavaAppProject(maybeAppProject = true)
This is exactly the kind of thing I thought would trip you up when I thought about how your root project depends on your subprojects:
- throw GradleException("You must apply the plugin to the root project. Current project is $path")
+ rootProject.pluginManager.apply(DependencyAnalysisPlugin::class.java)
The whole deal with the root extension and subproject extensions and how they communicate needs to be cleaned up. I am very open to improvements in this area.
I wonder if you could use a BuildService
instead for communication. But this bug may be annoying.
I faced the same issue in my project; the workaround to add the plugin to every/other/build.gradle
worked for me now.
Same as Himanshu, I added the flag and included the plugin in every module, and it started working.
@melix you might be lucky:
This means that doing System.setProperty("dependency.analysis.autoapply", false)
at any point before the plugin is applied might be a viable alternative to changing all your gradle.properties
files. If you have a settings plugin in for micronaut I think that would be the place, because otherwise it's quite tricky to do something before a root plugin is applied. Although it looks like you wrap every plugin, which means you set this before calling project.plugins.apply()
.
PRs welcome!
Build scan link
https://ge.micronaut.io/s/slhg65invj4t2
Plugin version
1.0.0-rc-06
Gradle version
7.4.1
Describe the bug
Applying the plugin to the root project fails with:
Steps to reproduce the behavior:
git clone https://github.com/micronaut-projects/micronaut-core.git
cd micronaut-core
build.gradle
to add the plugin:./gradlew buildHealth
Expected behavior
Build shouldn't fail.
Additional context
I'm investigating the use of this plugin (which I wish was a core feature of Gradle, I wanted this for a looooooong time) for integration in our Micronaut Build Plugin. This project provides convention plugins which are applied on more than 40 distinct Micronaut projects (including Micronaut Core which I used in this bug report). Our convention plugins require the use of
evaluationDependsOn
, which triggers evaluation of subprojects before the root project is evaluated.I am aware that there's a
dependency.analysis.autoapply=false
flag that I can use which would not apply the plugin to subprojects automatically. However, there are a number of issues:java-library
)gradle.properties
file, which, in a multi-repo context like ours, is a bit cumbersomeI looked into the sources and I've found that internally it does
ProjectPlugin(this).apply()
, but theProjectPlugin
type is internal. Would it make sense to expose a plugin which can be indidivually applied to a single project instead? That's basically whatProjectPlugin
does, it seems. In general I'm not super fond of plugins which automagically apply plugins on subprojects. Like here, it can easily break if the expectations aren't met. In a typical Micronaut project we have a root plugin which performs some aggregation (javadocs, code quality, ...), different module types plugins (a Micronaut Library, a Micronaut Component) and a BOM type which requiresevaluationDependsOn
so that we can automatically determine dependencies based on the application of a plugin or not.I'm happy to discuss options and/or provide PRs, I just need a bit more guidance on how I can individually run the plugin on a project to make progress: unfortunately I couldn't find answers in the wiki.
Thanks!