diff --git a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardConfiguration.kt b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardConfiguration.kt index cabaaca..38dd080 100644 --- a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardConfiguration.kt +++ b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardConfiguration.kt @@ -1,6 +1,7 @@ package com.dropbox.gradle.plugins.dependencyguard import org.gradle.api.Named +import org.gradle.api.tasks.Input import javax.inject.Inject /** @@ -12,14 +13,18 @@ public open class DependencyGuardConfiguration @Inject constructor( * * See all possibilities by running Gradle's built in ./gradlew project:dependencies */ + @get:Input public val configurationName: String, ) : Named { + @Input public override fun getName(): String = configurationName /** Whether to include artifacts in the dependency list report */ + @get:Input public var artifacts: Boolean = true /** Whether to include modules in the dependency list report */ + @get:Input public var modules: Boolean = true /** @@ -27,8 +32,14 @@ public open class DependencyGuardConfiguration @Inject constructor( * * false by default because while valuable for debugging, get very noisy */ + @get:Input public var tree: Boolean = false - /** Whether or not to allow a dependency */ + /** + * Whether to allow a dependency. + * + * TODO: not sure how to model this as a task input. May not matter since the task that uses it + * can never be up-to-date. + */ public var isAllowed: (dependencyName: String) -> Boolean = { true } } diff --git a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardPlugin.kt b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardPlugin.kt index 3dd58f0..e4377d1 100644 --- a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardPlugin.kt +++ b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardPlugin.kt @@ -1,6 +1,5 @@ package com.dropbox.gradle.plugins.dependencyguard -import com.dropbox.gradle.plugins.dependencyguard.internal.ConfigurationValidators.requirePluginConfig import com.dropbox.gradle.plugins.dependencyguard.internal.DependencyTreeDiffTaskNames import com.dropbox.gradle.plugins.dependencyguard.internal.list.DependencyGuardListTask import com.dropbox.gradle.plugins.dependencyguard.internal.tree.BuildEnvironmentDependencyTreeDiffTask @@ -50,6 +49,7 @@ public class DependencyGuardPlugin : Plugin { ) { val task = this task.setParams( + project = target, extension = extension, shouldBaseline = true ) @@ -65,8 +65,9 @@ public class DependencyGuardPlugin : Plugin { DependencyGuardListTask::class.java ) { val task = this - requirePluginConfig(target, extension) + //requirePluginConfig(target, extension.configurations) task.setParams( + project = target, extension = extension, shouldBaseline = false ) @@ -79,7 +80,7 @@ public class DependencyGuardPlugin : Plugin { baselineTask: TaskProvider, guardTask: TaskProvider ) { - extension.container.all { + extension.configurations.all { val dependencyGuardConfiguration = this if (dependencyGuardConfiguration.tree) { val taskClass = if (target.isRootProject()) { diff --git a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardPluginExtension.kt b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardPluginExtension.kt index 2d066d8..1703795 100644 --- a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardPluginExtension.kt +++ b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/DependencyGuardPluginExtension.kt @@ -10,16 +10,10 @@ import javax.inject.Inject public open class DependencyGuardPluginExtension @Inject constructor( private val objects: ObjectFactory ) { - internal val configurations = mutableListOf() - internal val container = objects.domainObjectContainer(DependencyGuardConfiguration::class.java) + internal val configurations = objects.domainObjectContainer(DependencyGuardConfiguration::class.java) public fun configuration(name: String) { - // TODO old - val configuration = DependencyGuardConfiguration(name) - configurations.add(configuration) - - // TODO new - container.create(name) + configurations.add(newConfiguration(name)) } /** @@ -33,15 +27,15 @@ public open class DependencyGuardPluginExtension @Inject constructor( * } */ public fun configuration(name: String, config: Action) { - // TODO old - val configuration = DependencyGuardConfiguration(name) - config.execute(configuration) - configurations.add(configuration) + configurations.add(newConfiguration(name, config)) + } - // TODO new - val c = objects.newInstance(DependencyGuardConfiguration::class.java, name).apply { - config.execute(this) + private fun newConfiguration( + name: String, + config: Action? = null + ): DependencyGuardConfiguration { + return objects.newInstance(DependencyGuardConfiguration::class.java, name).apply { + config?.execute(this) } - container.add(c) } } diff --git a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/ConfigurationValidators.kt b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/ConfigurationValidators.kt index 794f9d5..6787ad4 100644 --- a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/ConfigurationValidators.kt +++ b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/ConfigurationValidators.kt @@ -1,17 +1,25 @@ package com.dropbox.gradle.plugins.dependencyguard.internal -import com.dropbox.gradle.plugins.dependencyguard.DependencyGuardPluginExtension +import com.dropbox.gradle.plugins.dependencyguard.DependencyGuardConfiguration +import com.dropbox.gradle.plugins.dependencyguard.DependencyGuardPlugin import org.gradle.api.GradleException import org.gradle.api.Project import org.gradle.api.initialization.dsl.ScriptHandler +import org.gradle.api.logging.Logging internal object ConfigurationValidators { - fun requirePluginConfig(project: Project, extension: DependencyGuardPluginExtension) { - if (project.isRootProject()) { - println("Configured for Root Project") - if (extension.configurations.isNotEmpty() && extension.configurations.first().configurationName != ScriptHandler.CLASSPATH_CONFIGURATION) { - println("If you wish to use dependency guard on your root project, use the following config:") + private val logger = Logging.getLogger(DependencyGuardPlugin::class.java) + + fun requirePluginConfig( + isForRootProject: Boolean, + availableConfigurations: List, + monitoredConfigurations: List + ) { + if (isForRootProject) { + logger.info("Configured for Root Project") + if (monitoredConfigurations.isNotEmpty() && monitoredConfigurations.first().configurationName != ScriptHandler.CLASSPATH_CONFIGURATION) { + logger.error("If you wish to use dependency guard on your root project, use the following config:") val message = StringBuilder().apply { appendLine("dependencyGuard {") appendLine(""" configuration("${ScriptHandler.CLASSPATH_CONFIGURATION}")""") @@ -21,16 +29,14 @@ internal object ConfigurationValidators { } return } - val configurationNames = extension.configurations.map { it.configurationName } + val configurationNames = monitoredConfigurations.map { it.configurationName } require(configurationNames.isNotEmpty() && configurationNames[0].isNotBlank()) { StringBuilder().apply { appendLine("Error: No configurations provided to Dependency Guard Plugin.") appendLine("Here are some valid configurations you could use.") appendLine("") - val availableConfigNames = project.configurations - .filter { - isClasspathConfig(it.name) - }.map { it.name } + val availableConfigNames = availableConfigurations + .filter { isClasspathConfig(it) } appendLine("dependencyGuard {") availableConfigNames.forEach { @@ -41,7 +47,7 @@ internal object ConfigurationValidators { } } - fun isClasspathConfig(configName: String): Boolean { + private fun isClasspathConfig(configName: String): Boolean { return configName.endsWith( suffix = "CompileClasspath", ignoreCase = true @@ -55,6 +61,8 @@ internal object ConfigurationValidators { target: Project, configurationNames: List ) { + val logger = target.logger + if (target.isRootProject()) { if (configurationNames != listOf(ScriptHandler.CLASSPATH_CONFIGURATION)) { val message = StringBuilder().apply { @@ -73,13 +81,13 @@ internal object ConfigurationValidators { target.configurations .firstOrNull { it.name == configurationName } ?: run { - println("Available Configurations:") + logger.quiet("Available Configurations:") target.configurations .filter { isClasspathConfig(it.name) } .forEach { - println("* " + it.name) + logger.quiet("* " + it.name) } throw GradleException( "Configuration with name $configurationName was not found for ${target.name}" diff --git a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/ProjectExt.kt b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/ProjectExt.kt index e6878b1..6c541ef 100644 --- a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/ProjectExt.kt +++ b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/ProjectExt.kt @@ -3,7 +3,7 @@ package com.dropbox.gradle.plugins.dependencyguard.internal import com.dropbox.gradle.plugins.dependencyguard.DependencyGuardPlugin import org.gradle.api.Project -internal fun Project.isRootProject(): Boolean = (path == rootProject.path) +internal fun Project.isRootProject(): Boolean = this == rootProject internal fun getQualifiedBaselineTaskForProjectPath(path: String): String { val separator = if (path == ":") "" else ":" diff --git a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/list/DependencyGuardListTask.kt b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/list/DependencyGuardListTask.kt index c2bc993..c20b7b1 100644 --- a/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/list/DependencyGuardListTask.kt +++ b/dependency-guard/src/main/kotlin/com/dropbox/gradle/plugins/dependencyguard/internal/list/DependencyGuardListTask.kt @@ -4,31 +4,31 @@ import com.dropbox.gradle.plugins.dependencyguard.DependencyGuardConfiguration import com.dropbox.gradle.plugins.dependencyguard.DependencyGuardPlugin import com.dropbox.gradle.plugins.dependencyguard.DependencyGuardPluginExtension import com.dropbox.gradle.plugins.dependencyguard.internal.ConfigurationValidators +import com.dropbox.gradle.plugins.dependencyguard.internal.ConfigurationValidators.requirePluginConfig import com.dropbox.gradle.plugins.dependencyguard.internal.DependencyGuardListReportWriter import com.dropbox.gradle.plugins.dependencyguard.internal.DependencyGuardReportData import com.dropbox.gradle.plugins.dependencyguard.internal.DependencyGuardReportType import com.dropbox.gradle.plugins.dependencyguard.internal.DependencyVisitor import com.dropbox.gradle.plugins.dependencyguard.internal.isRootProject import com.dropbox.gradle.plugins.dependencyguard.internal.qualifiedBaselineTaskName -import com.dropbox.gradle.plugins.dependencyguard.internal.utils.ColorTerminal import com.dropbox.gradle.plugins.dependencyguard.internal.utils.OutputFileUtils import org.gradle.api.DefaultTask import org.gradle.api.GradleException +import org.gradle.api.Project import org.gradle.api.initialization.dsl.ScriptHandler +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Nested import org.gradle.api.tasks.TaskAction +import org.gradle.util.GradleVersion -internal open class DependencyGuardListTask : DefaultTask() { +public abstract class DependencyGuardListTask : DefaultTask() { init { group = DependencyGuardPlugin.DEPENDENCY_GUARD_TASK_GROUP } - private lateinit var extension: DependencyGuardPluginExtension - - private var shouldBaseline: Boolean = false - - private val dependencyGuardConfigurations: MutableList get() = extension.configurations - private fun generateReport( dependencyGuardConfiguration: DependencyGuardConfiguration ): DependencyGuardReportData { @@ -37,7 +37,7 @@ internal open class DependencyGuardListTask : DefaultTask() { var config = project.configurations.firstOrNull { it.name == configurationName } if (config == null) { - if (project.isRootProject()) { + if (forRootProject.get()) { // Assuming this is the root project config = project.buildscript.configurations.findByName(ScriptHandler.CLASSPATH_CONFIGURATION) } @@ -56,9 +56,28 @@ internal open class DependencyGuardListTask : DefaultTask() { ) } + @get:Input + public abstract val shouldBaseline: Property + + @get:Input + public abstract val forRootProject: Property + + @get:Input + public abstract val availableConfigurations: ListProperty + + @get:Nested + public abstract val monitoredConfigurations: ListProperty + @Suppress("NestedBlockDepth") @TaskAction internal fun execute() { + requirePluginConfig( + isForRootProject = forRootProject.get(), + availableConfigurations = availableConfigurations.get(), + monitoredConfigurations = monitoredConfigurations.get() + ) + + val dependencyGuardConfigurations = monitoredConfigurations.get() ConfigurationValidators.validateConfigurationsAreAvailable( target = project, configurationNames = dependencyGuardConfigurations.map { it.configurationName } @@ -114,7 +133,7 @@ internal open class DependencyGuardListTask : DefaultTask() { reportType = reportType, ), report = report, - shouldBaseline = shouldBaseline, + shouldBaseline = shouldBaseline.get(), errorHandler = { } ) } @@ -154,8 +173,20 @@ internal open class DependencyGuardListTask : DefaultTask() { throw GradleException(errorMessage) } - internal fun setParams(extension: DependencyGuardPluginExtension, shouldBaseline: Boolean) { - this.extension = extension - this.shouldBaseline = shouldBaseline + internal fun setParams( + project: Project, + extension: DependencyGuardPluginExtension, + shouldBaseline: Boolean + ) { + this.forRootProject.set(project.isRootProject()) + this.availableConfigurations.set(project.configurations.map { it.name }) + this.monitoredConfigurations.set(extension.configurations) + this.shouldBaseline.set(shouldBaseline) + + if (GradleVersion.current() >= GradleVersion.version("7.3")) { + doNotTrackState("This task only outputs to console") + } else { + outputs.upToDateWhen { false } + } } }