From d027dd76dba57e609775879fca229d8baec4411b Mon Sep 17 00:00:00 2001 From: Roberto Perez Alcolea Date: Mon, 30 Oct 2023 17:54:31 -0700 Subject: [PATCH] DependencyLockExtension: Introduce lazy APIs --- build.gradle | 2 +- .../DependencyLockExtension.groovy | 45 +++++++--- .../DependencyLockTaskConfigurer.groovy | 38 ++++----- .../tasks/GenerateLockTask.groovy | 2 +- .../tasks/UpdateLockTask.groovy | 2 +- .../utils/CoreLockingHelper.groovy | 2 +- .../dependencylock/DependencyLockPlugin.kt | 16 ++-- .../validation/UpdateDependenciesValidator.kt | 6 +- .../UpdateDependenciesValidatorSpec.groovy | 3 +- .../DependencyResolutionVerifierTest.groovy | 85 ------------------- 10 files changed, 68 insertions(+), 133 deletions(-) diff --git a/build.gradle b/build.gradle index 3c535ce..f8eb49b 100644 --- a/build.gradle +++ b/build.gradle @@ -88,7 +88,7 @@ tasks.named('compileKotlin') { test.dependsOn jar -tasks.withType(Test) { +tasks.withType(Test).configureEach { testLogging { events "PASSED", "FAILED", "SKIPPED" afterSuite { desc, result -> diff --git a/src/main/groovy/nebula/plugin/dependencylock/DependencyLockExtension.groovy b/src/main/groovy/nebula/plugin/dependencylock/DependencyLockExtension.groovy index 72452e1..73ecae6 100644 --- a/src/main/groovy/nebula/plugin/dependencylock/DependencyLockExtension.groovy +++ b/src/main/groovy/nebula/plugin/dependencylock/DependencyLockExtension.groovy @@ -15,18 +15,37 @@ */ package nebula.plugin.dependencylock -class DependencyLockExtension { - String lockFile = 'dependencies.lock' - String globalLockFile = 'global.lock' - Set configurationNames = [] as Set - Set skippedConfigurationNamesPrefixes = [] as Set +import org.gradle.api.provider.Property +import org.gradle.api.provider.SetProperty + +abstract class DependencyLockExtension { + DependencyLockExtension() { + lockFile.convention('dependencies.lock') + globalLockFile.convention('global.lock') + configurationNames.convention([]) + skippedConfigurationNamesPrefixes.convention([]) + updateDependencies.convention([]) + skippedDependencies.convention([]) + includeTransitives.convention(false) + lockAfterEvaluating.convention(true) + updateDependenciesFailOnInvalidCoordinates.convention(true) + updateDependenciesFailOnSimultaneousTaskUsage.convention(true) + updateDependenciesFailOnNonSpecifiedDependenciesToUpdate.convention(true) + additionalConfigurationsToLock.convention([]) + } + + abstract Property getLockFile() + abstract Property getGlobalLockFile() + abstract SetProperty getConfigurationNames() + abstract SetProperty getSkippedConfigurationNamesPrefixes() + abstract SetProperty getUpdateDependencies() + abstract SetProperty getSkippedDependencies() + abstract Property getIncludeTransitives() + abstract Property getLockAfterEvaluating() + abstract Property getUpdateDependenciesFailOnInvalidCoordinates() + abstract Property getUpdateDependenciesFailOnSimultaneousTaskUsage() + abstract Property getUpdateDependenciesFailOnNonSpecifiedDependenciesToUpdate() + abstract SetProperty getAdditionalConfigurationsToLock() + Closure dependencyFilter = { String group, String name, String version -> true } - Set updateDependencies = [] as Set - Set skippedDependencies = [] as Set - boolean includeTransitives = false - boolean lockAfterEvaluating = true - boolean updateDependenciesFailOnInvalidCoordinates = true - boolean updateDependenciesFailOnSimultaneousTaskUsage = true - boolean updateDependenciesFailOnNonSpecifiedDependenciesToUpdate = true - Set additionalConfigurationsToLock = [] as Set } diff --git a/src/main/groovy/nebula/plugin/dependencylock/DependencyLockTaskConfigurer.groovy b/src/main/groovy/nebula/plugin/dependencylock/DependencyLockTaskConfigurer.groovy index a78ecf5..c8a0ef5 100644 --- a/src/main/groovy/nebula/plugin/dependencylock/DependencyLockTaskConfigurer.groovy +++ b/src/main/groovy/nebula/plugin/dependencylock/DependencyLockTaskConfigurer.groovy @@ -97,19 +97,19 @@ class DependencyLockTaskConfigurer { } private File getProjectDirLockFile(String lockFilename, DependencyLockExtension extension) { - new File(project.projectDir, lockFilename ?: extension.lockFile) + new File(project.projectDir, lockFilename ?: extension.lockFile.get()) } private File getBuildDirLockFile(String lockFilename, DependencyLockExtension extension) { - new File(project.layout.buildDirectory.getAsFile().get(), lockFilename ?: extension.lockFile) + new File(project.layout.buildDirectory.getAsFile().get(), lockFilename ?: extension.lockFile.get()) } private File getProjectDirGlobalLockFile(String lockFilename, DependencyLockExtension extension) { - new File(project.projectDir, lockFilename ?: extension.globalLockFile) + new File(project.projectDir, lockFilename ?: extension.globalLockFile.get()) } private File getBuildDirGlobalLockFile(String lockFilename, DependencyLockExtension extension) { - new File(project.layout.buildDirectory.getAsFile().get(), lockFilename ?: extension.globalLockFile) + new File(project.layout.buildDirectory.getAsFile().get(), lockFilename ?: extension.globalLockFile.get()) } private void configureCommitTask(String clLockFileName, String globalLockFileName, TaskProvider saveTask, DependencyLockExtension lockExtension, @@ -143,8 +143,8 @@ class DependencyLockTaskConfigurer { private List getPatternsToCommit(String clLockFileName, String globalLockFileName, DependencyLockExtension lockExtension ) { List patterns = [] - patterns.add(clLockFileName ?: lockExtension.lockFile) - patterns.add(globalLockFileName ?: lockExtension.globalLockFile) + patterns.add(clLockFileName ?: lockExtension.lockFile.get()) + patterns.add(globalLockFileName ?: lockExtension.globalLockFile.get()) return patterns } @@ -211,8 +211,8 @@ class DependencyLockTaskConfigurer { lockTask.configure { it.conventionMapping.with { dependenciesLock = { getBuildDirLockFile(lockFilename, extension) } - configurationNames = { extension.configurationNames } - skippedConfigurationNames = { extension.skippedConfigurationNamesPrefixes } + configurationNames = { extension.configurationNames.get() } + skippedConfigurationNames = { extension.skippedConfigurationNamesPrefixes.get() } } } @@ -222,9 +222,9 @@ class DependencyLockTaskConfigurer { private void setupLockConventionMapping(TaskProvider task, DependencyLockExtension extension, Map overrideMap) { task.configure { generateTask -> generateTask.conventionMapping.with { - skippedDependencies = { extension.skippedDependencies } + skippedDependencies = { extension.skippedDependencies.get() } includeTransitives = { - project.hasProperty('dependencyLock.includeTransitives') ? Boolean.parseBoolean(project['dependencyLock.includeTransitives'] as String) : extension.includeTransitives + project.hasProperty('dependencyLock.includeTransitives') ? Boolean.parseBoolean(project['dependencyLock.includeTransitives'] as String) : extension.includeTransitives.get() } filter = { extension.dependencyFilter } overrides = { overrideMap } @@ -245,15 +245,15 @@ class DependencyLockTaskConfigurer { def subprojects = project.subprojects.collect { subproject -> def ext = subproject.getExtensions().findByType(DependencyLockExtension) if (ext != null) { - Collection lockableConfigurations = lockableConfigurations(project, subproject, ext.configurationNames, extension.skippedConfigurationNamesPrefixes) - Collection configurations = filterNonLockableConfigurationsAndProvideWarningsForGlobalLockSubproject(subproject, ext.configurationNames, lockableConfigurations) + Collection lockableConfigurations = lockableConfigurations(project, subproject, ext.configurationNames.get(), extension.skippedConfigurationNamesPrefixes.get()) + Collection configurations = filterNonLockableConfigurationsAndProvideWarningsForGlobalLockSubproject(subproject, ext.configurationNames.get(), lockableConfigurations) Configuration aggregate = subproject.configurations.create("aggregateConfiguration") aggregate.setCanBeConsumed(true) aggregate.setCanBeResolved(true) configurations .findAll { configuration -> !configurationsToSkipForGlobalLockPrefixes.any { String prefix -> configuration.name.startsWith(prefix) } - && !extension.skippedConfigurationNamesPrefixes.any { String prefix -> configuration.name.startsWith(prefix) } + && !extension.skippedConfigurationNamesPrefixes.get().any { String prefix -> configuration.name.startsWith(prefix) } } .each { configuration -> aggregate.extendsFrom(configuration) @@ -267,7 +267,7 @@ class DependencyLockTaskConfigurer { def conf = project.configurations.detachedConfiguration(subprojectsArray) project.allprojects.each { it.configurations.add(conf) } - [conf] + lockableConfigurations(project, project, extension.configurationNames, extension.skippedConfigurationNamesPrefixes) + [conf] + lockableConfigurations(project, project, extension.configurationNames.get(), extension.skippedConfigurationNamesPrefixes.get()) } } } @@ -278,12 +278,12 @@ class DependencyLockTaskConfigurer { private TaskProvider configureMigrateToCoreLocksTask(DependencyLockExtension extension) { def migrateLockedDepsToCoreLocksTask = project.tasks.register(MIGRATE_LOCKED_DEPS_TO_CORE_LOCKS_TASK_NAME, MigrateLockedDepsToCoreLocksTask) def migrateToCoreLocksTask = project.tasks.register(MIGRATE_TO_CORE_LOCKS_TASK_NAME, MigrateToCoreLocksTask) - def lockFile = new File(project.projectDir, extension.lockFile) + def lockFile = new File(project.projectDir, extension.lockFile.get()) def dependencyLock = new File(project.projectDir, "gradle.lockfile") migrateLockedDepsToCoreLocksTask.configure { it.conventionMapping.with { - configurationNames = { extension.configurationNames } + configurationNames = { extension.configurationNames.get() } inputLockFile = { lockFile } outputLock = { dependencyLock } } @@ -291,7 +291,7 @@ class DependencyLockTaskConfigurer { migrateToCoreLocksTask.configure { it.conventionMapping.with { - configurationNames = { extension.configurationNames } + configurationNames = { extension.configurationNames.get() } outputLock = { dependencyLock } } it.dependsOn project.tasks.named(MIGRATE_LOCKED_DEPS_TO_CORE_LOCKS_TASK_NAME) @@ -331,11 +331,11 @@ class DependencyLockTaskConfigurer { diffLockTask.configure { diffTask -> diffTask.mustRunAfter(project.tasks.named(GENERATE_LOCK_TASK_NAME), project.tasks.named(UPDATE_LOCK_TASK_NAME)) - def existing = new File(project.projectDir, lockFileName ?: extension.lockFile) + def existing = new File(project.projectDir, lockFileName ?: extension.lockFile.get()) if (existing.exists()) { diffTask.existingLockFile = existing } - diffTask.updatedLockFile = new File(project.layout.buildDirectory.getAsFile().get(), lockFileName ?: extension.lockFile) + diffTask.updatedLockFile = new File(project.layout.buildDirectory.getAsFile().get(), lockFileName ?: extension.lockFile.get()) } project.tasks.named(SAVE_LOCK_TASK_NAME).configure { save -> diff --git a/src/main/groovy/nebula/plugin/dependencylock/tasks/GenerateLockTask.groovy b/src/main/groovy/nebula/plugin/dependencylock/tasks/GenerateLockTask.groovy index 22693c1..257b70f 100644 --- a/src/main/groovy/nebula/plugin/dependencylock/tasks/GenerateLockTask.groovy +++ b/src/main/groovy/nebula/plugin/dependencylock/tasks/GenerateLockTask.groovy @@ -74,7 +74,7 @@ class GenerateLockTask extends AbstractLockTask { void lock() { if (DependencyLockingFeatureFlags.isCoreLockingEnabled()) { def dependencyLockExtension = project.extensions.findByType(DependencyLockExtension) - def globalLockFile = new File(project.projectDir, dependencyLockExtension.globalLockFile) + def globalLockFile = new File(project.projectDir, dependencyLockExtension.globalLockFile.get()) if (globalLockFile.exists()) { throw new BuildCancelledException("Legacy global locks are not supported with core locking.\n" + "Please remove global locks.\n" + diff --git a/src/main/groovy/nebula/plugin/dependencylock/tasks/UpdateLockTask.groovy b/src/main/groovy/nebula/plugin/dependencylock/tasks/UpdateLockTask.groovy index 70326a3..c90fb0f 100644 --- a/src/main/groovy/nebula/plugin/dependencylock/tasks/UpdateLockTask.groovy +++ b/src/main/groovy/nebula/plugin/dependencylock/tasks/UpdateLockTask.groovy @@ -34,7 +34,7 @@ class UpdateLockTask extends GenerateLockTask { void lock() { if (DependencyLockingFeatureFlags.isCoreLockingEnabled()) { def dependencyLockExtension = project.extensions.findByType(DependencyLockExtension) - def globalLockFile = new File(project.projectDir, dependencyLockExtension.globalLockFile) + def globalLockFile = new File(project.projectDir, dependencyLockExtension.globalLockFile.get()) if (globalLockFile.exists()) { throw new BuildCancelledException("Legacy global locks are not supported with core locking.\n" + "Please remove global locks.\n" + diff --git a/src/main/groovy/nebula/plugin/dependencylock/utils/CoreLockingHelper.groovy b/src/main/groovy/nebula/plugin/dependencylock/utils/CoreLockingHelper.groovy index 70a1129..dbd4f83 100644 --- a/src/main/groovy/nebula/plugin/dependencylock/utils/CoreLockingHelper.groovy +++ b/src/main/groovy/nebula/plugin/dependencylock/utils/CoreLockingHelper.groovy @@ -131,7 +131,7 @@ class CoreLockingHelper { def additionalConfigurationsToLockViaProperty = project.hasProperty(ADDITIONAL_CONFIGS_TO_LOCK) ? (project[ADDITIONAL_CONFIGS_TO_LOCK] as String).split(",") as Set : [] - def additionalConfigurationsToLockViaExtension = dependencyLockExtension.additionalConfigurationsToLock as Set + def additionalConfigurationsToLockViaExtension = dependencyLockExtension.additionalConfigurationsToLock.get() as Set def additionalConfigNames = additionalConfigurationsToLockViaProperty + additionalConfigurationsToLockViaExtension additionalConfigNames } diff --git a/src/main/kotlin/nebula/plugin/dependencylock/DependencyLockPlugin.kt b/src/main/kotlin/nebula/plugin/dependencylock/DependencyLockPlugin.kt index b0bd064..a983707 100644 --- a/src/main/kotlin/nebula/plugin/dependencylock/DependencyLockPlugin.kt +++ b/src/main/kotlin/nebula/plugin/dependencylock/DependencyLockPlugin.kt @@ -113,12 +113,12 @@ class DependencyLockPlugin : Plugin { if (DependencyLockingFeatureFlags.isCoreLockingEnabled()) { LOGGER.info("${project.name}: coreLockingSupport feature enabled") val coreLockingHelper = CoreLockingHelper(project) - coreLockingHelper.lockSelectedConfigurations(extension.configurationNames) + coreLockingHelper.lockSelectedConfigurations(extension.configurationNames.get()) coreLockingHelper.disableCachingWhenUpdatingDependencies() coreLockingHelper.notifyWhenUsingOfflineMode() - val lockFile = File(project.projectDir, extension.lockFile) + val lockFile = File(project.projectDir, extension.lockFile.get()) if (lockFile.exists()) { if (startParameter.isWriteDependencyLocks) { @@ -138,7 +138,7 @@ class DependencyLockPlugin : Plugin { val taskNames = startParameter.taskNames val hasUpdateTask = hasUpdateTask(taskNames) val hasGenerationTask = hasGenerationTask(taskNames) - val globalLockFile = File(project.projectDir, extension.globalLockFile) + val globalLockFile = File(project.projectDir, extension.globalLockFile.get()) if (globalLockFile.exists() && !hasGenerationTask && !hasUpdateTask) { // do not fail for generation or update tasks here. It's more readable when the task itself fails. @@ -147,7 +147,7 @@ class DependencyLockPlugin : Plugin { " - Legacy global lock: ${globalLockFile.absolutePath}") } } else { - val lockAfterEvaluating = if (project.hasProperty(LOCK_AFTER_EVALUATING)) project.property(LOCK_AFTER_EVALUATING).toString().toBoolean() else extension.lockAfterEvaluating + val lockAfterEvaluating = if (project.hasProperty(LOCK_AFTER_EVALUATING)) project.property(LOCK_AFTER_EVALUATING).toString().toBoolean() else extension.lockAfterEvaluating.get() if (lockAfterEvaluating) { LOGGER.info("Delaying dependency lock apply until beforeResolve ($LOCK_AFTER_EVALUATING set to true)") } else { @@ -186,17 +186,17 @@ class DependencyLockPlugin : Plugin { } private fun maybeApplyLock(conf: Configuration, extension: DependencyLockExtension, overrides: Map<*, *>, globalLockFileName: String?, lockFilename: String?) { - val shouldIgnoreLock = (extension.skippedConfigurationNamesPrefixes + DependencyLockTaskConfigurer.configurationsToSkipForGlobalLockPrefixes).any { + val shouldIgnoreLock = (extension.skippedConfigurationNamesPrefixes.get() + DependencyLockTaskConfigurer.configurationsToSkipForGlobalLockPrefixes).any { prefix -> conf.name.startsWith(prefix) && !conf.name.contains("resolutionRules") } if(shouldIgnoreLock) { return } - val globalLock = File(project.rootProject.projectDir, globalLockFileName ?: extension.globalLockFile) + val globalLock = File(project.rootProject.projectDir, globalLockFileName ?: extension.globalLockFile.get()) val dependenciesLock = if (globalLock.exists()) { globalLock } else { - File(project.projectDir, lockFilename ?: extension.lockFile) + File(project.projectDir, lockFilename ?: extension.lockFile.get()) } lockUsed = dependenciesLock.name @@ -206,7 +206,7 @@ class DependencyLockPlugin : Plugin { val taskNames = project.gradle.startParameter.taskNames val hasUpdateTask = hasUpdateTask(taskNames) - val updates = if (project.hasProperty(UPDATE_DEPENDENCIES)) parseUpdates(project.property(UPDATE_DEPENDENCIES) as String) else extension.updateDependencies + val updates = if (project.hasProperty(UPDATE_DEPENDENCIES)) parseUpdates(project.property(UPDATE_DEPENDENCIES) as String) else extension.updateDependencies.get() UpdateDependenciesValidator.validate( updates, overrides, hasUpdateTask, hasTask(taskNames, GENERATION_TASK_NAMES - UPDATE_TASK_NAMES), diff --git a/src/main/kotlin/nebula/plugin/dependencylock/validation/UpdateDependenciesValidator.kt b/src/main/kotlin/nebula/plugin/dependencylock/validation/UpdateDependenciesValidator.kt index 4129b88..0e17975 100644 --- a/src/main/kotlin/nebula/plugin/dependencylock/validation/UpdateDependenciesValidator.kt +++ b/src/main/kotlin/nebula/plugin/dependencylock/validation/UpdateDependenciesValidator.kt @@ -24,15 +24,15 @@ class UpdateDependenciesValidator { val validateCoordinates = if (project.hasProperty(VALIDATE_DEPENDENCY_COORDINATES)) project.property( VALIDATE_DEPENDENCY_COORDINATES - ).toString().toBoolean() else extension.updateDependenciesFailOnInvalidCoordinates + ).toString().toBoolean() else extension.updateDependenciesFailOnInvalidCoordinates.get() val validateSimultaneousTasks = if (project.hasProperty(VALIDATE_SIMULTANEOUS_TASKS)) project.property( VALIDATE_SIMULTANEOUS_TASKS - ).toString().toBoolean() else extension.updateDependenciesFailOnSimultaneousTaskUsage + ).toString().toBoolean() else extension.updateDependenciesFailOnSimultaneousTaskUsage.get() val validateSpecifiedDependenciesToUpdate = if (project.hasProperty(VALIDATE_SPECIFIED_DEPENDENCIES_TO_UPDATE)) project.property( VALIDATE_SPECIFIED_DEPENDENCIES_TO_UPDATE - ).toString().toBoolean() else extension.updateDependenciesFailOnNonSpecifiedDependenciesToUpdate + ).toString().toBoolean() else extension.updateDependenciesFailOnNonSpecifiedDependenciesToUpdate.get() validateCoordinates(updateDependencies, validateCoordinates) validateSimultaneousTasks(hasUpdateTask, hasGenerateTask, validateSimultaneousTasks) diff --git a/src/test/groovy/nebula/plugin/dependencylock/validation/UpdateDependenciesValidatorSpec.groovy b/src/test/groovy/nebula/plugin/dependencylock/validation/UpdateDependenciesValidatorSpec.groovy index f3fdec1..5448b0d 100644 --- a/src/test/groovy/nebula/plugin/dependencylock/validation/UpdateDependenciesValidatorSpec.groovy +++ b/src/test/groovy/nebula/plugin/dependencylock/validation/UpdateDependenciesValidatorSpec.groovy @@ -6,11 +6,12 @@ import nebula.test.ProjectSpec class UpdateDependenciesValidatorSpec extends ProjectSpec { private static final HashMap emptyMap = new HashMap() - private static final DependencyLockExtension extension = DependencyLockExtension.newInstance() + private DependencyLockExtension extension private static final String pluginName = 'com.netflix.nebula.dependency-lock' def setup() { project.apply plugin: pluginName + extension = project.extensions.findByType(DependencyLockExtension) } def 'should not fail if valid coordinates'() { diff --git a/src/test/groovy/nebula/plugin/dependencyverifier/DependencyResolutionVerifierTest.groovy b/src/test/groovy/nebula/plugin/dependencyverifier/DependencyResolutionVerifierTest.groovy index a163376..7625ed4 100644 --- a/src/test/groovy/nebula/plugin/dependencyverifier/DependencyResolutionVerifierTest.groovy +++ b/src/test/groovy/nebula/plugin/dependencyverifier/DependencyResolutionVerifierTest.groovy @@ -391,42 +391,6 @@ class DependencyResolutionVerifierTest extends IntegrationTestKitSpec { tasks << [['build'], ['build', '--parallel']] } - @IgnoreIf({ jvm.isJava17Compatible() }) - @Unroll - def 'with Gradle version #gradleVersionToTest - expecting #expecting'() { - given: - gradleVersion = gradleVersionToTest - setupSingleProject() - - if (expecting == 'error') { - buildFile << """ - dependencies { - implementation 'not.available:a:1.0.0' // dependency is not found - } - """.stripIndent() - } - - when: - def results - def tasks = ['dependencies', '--configuration', 'compileClasspath'] - - if (expecting == 'error') { - results = runTasksAndFail(*tasks) - } else { - results = runTasks(*tasks) - } - - then: - results.output.contains('Task :dependencies') - - where: - gradleVersionToTest | expecting - '6.9' | 'error' - '6.9' | 'no error' - '6.0.1' | 'error' - '6.0.1' | 'no error' - } - @Unroll def 'handles task configuration issue due to #failureType'() { given: @@ -1167,55 +1131,6 @@ class DependencyResolutionVerifierTest extends IntegrationTestKitSpec { assert results.output.contains('FAIL') } - @IgnoreIf({ jvm.isJava17Compatible() }) - @Unroll - def 'with Gradle version #gradleVersionToTest - expecting #expecting - using task with configuration dependencies'() { - given: - gradleVersion = gradleVersionToTest - setupSingleProject() - - buildFile << taskThatRequiresConfigurationDependencies() - - if (expecting == 'error') { - buildFile << """ - dependencies { - implementation 'not.available:a:1.0.0' // dependency is not found - } - """.stripIndent() - } - - when: - def results - def tasks = ['dependencies', '--configuration', 'compileClasspath'] - - if (expecting == 'error') { - results = runTasksAndFail(*tasks) - } else { - results = runTasks(*tasks) - } - - then: - if (expecting == 'error') { - assert results.output.contains('Execution failed for task \':taskWithConfigurationDependencies\'') - assert results.output.contains("1. Failed to resolve 'not.available:a:1.0.0' for project") - } else { - assert results.output.contains('Task :dependencies') - } - - where: - gradleVersionToTest | expecting - '6.0.1' | 'error' - '6.0.1' | 'no error' - '5.6.4' | 'error' - '5.6.4' | 'no error' - '5.1' | 'error' - '5.1' | 'no error' - '4.10.3' | 'error' - '4.10.3' | 'no error' - '4.9' | 'error' - '4.9' | 'no error' - } - private static String taskThatRequiresConfigurationDependencies() { return """ task taskWithConfigurationDependencies {