diff --git a/build.gradle b/build.gradle index 8d8e060..7b0b850 100644 --- a/build.gradle +++ b/build.gradle @@ -15,6 +15,17 @@ * */ +buildscript { + repositories { + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath "com.netflix.nebula:gradle-dependency-lock-plugin:10.2.0-rc.1" + } +} + plugins { id 'nebula.plugin-plugin' version '14.5.0' id 'nebula.kotlin' version '1.3.61' @@ -30,7 +41,7 @@ dependencies { implementation 'com.netflix.nebula:nebula-dependency-recommender:9.0.1' testImplementation gradleTestKit() - testRuntimeOnly 'com.netflix.nebula:gradle-dependency-lock-plugin:7.+' + testRuntimeOnly 'com.netflix.nebula:gradle-dependency-lock-plugin:10.+' } apply from: 'gradle/idea.gradle' diff --git a/gradle/dependency-locks/default.lockfile b/gradle/dependency-locks/default.lockfile deleted file mode 100644 index 80c0e77..0000000 --- a/gradle/dependency-locks/default.lockfile +++ /dev/null @@ -1,26 +0,0 @@ -# This is a Gradle generated file for dependency locking. -# Manual edits can break the build and are not advised. -# This file is expected to be part of source control. -com.fasterxml.jackson.core:jackson-annotations:2.9.0 -com.fasterxml.jackson.core:jackson-core:2.9.9 -com.fasterxml.jackson.core:jackson-databind:2.9.9.3 -com.fasterxml.jackson.module:jackson-module-kotlin:2.9.9 -com.fasterxml.jackson:jackson-bom:2.9.9.20190807 -com.google.guava:guava:20.0 -com.netflix.nebula:nebula-dependency-recommender:9.0.1 -com.netflix.nebula:nebula-gradle-interop:1.0.11 -javax.inject:javax.inject:1 -org.apache.commons:commons-lang3:3.8.1 -org.apache.maven:maven-artifact:3.6.2 -org.apache.maven:maven-builder-support:3.6.2 -org.apache.maven:maven-model-builder:3.6.2 -org.apache.maven:maven-model:3.6.2 -org.codehaus.plexus:plexus-interpolation:1.25 -org.codehaus.plexus:plexus-utils:3.2.1 -org.eclipse.sisu:org.eclipse.sisu.inject:0.3.3 -org.jetbrains.kotlin:kotlin-reflect:1.3.61 -org.jetbrains.kotlin:kotlin-stdlib-common:1.3.61 -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61 -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.61 -org.jetbrains.kotlin:kotlin-stdlib:1.3.61 -org.jetbrains:annotations:13.0 diff --git a/gradle/dependency-locks/integTestRuntimeClasspath.lockfile b/gradle/dependency-locks/integTestRuntimeClasspath.lockfile index db78101..bf1ed22 100644 --- a/gradle/dependency-locks/integTestRuntimeClasspath.lockfile +++ b/gradle/dependency-locks/integTestRuntimeClasspath.lockfile @@ -2,39 +2,43 @@ # Manual edits can break the build and are not advised. # This file is expected to be part of source control. cglib:cglib-nodep:3.2.2 +ch.qos.logback:logback-core:1.1.3 com.fasterxml.jackson.core:jackson-annotations:2.9.0 com.fasterxml.jackson.core:jackson-core:2.9.9 com.fasterxml.jackson.core:jackson-databind:2.9.9.3 +com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.9 com.fasterxml.jackson.module:jackson-module-kotlin:2.9.9 com.fasterxml.jackson:jackson-bom:2.9.9.20190807 +com.google.code.gson:gson:2.3.1 com.google.guava:guava:20.0 -com.netflix.nebula:gradle-dependency-lock-plugin:7.8.0 -com.netflix.nebula:gradle-scm-plugin:5.0.3 +com.netflix.nebula:gradle-dependency-lock-plugin:10.2.0-rc.1 +com.netflix.nebula:gradle-metrics-plugin:8.4.1 +com.netflix.nebula:gradle-scm-plugin:5.1.0 +com.netflix.nebula:nebula-dependencies-comparison:0.1.8 com.netflix.nebula:nebula-dependency-recommender:9.0.1 com.netflix.nebula:nebula-gradle-interop:1.0.11 com.netflix.nebula:nebula-test:7.6.0 -com.squareup.moshi:moshi:1.8.0 +com.squareup.moshi:moshi:1.9.2 com.squareup.okio:okio:1.16.0 -commons-beanutils:commons-beanutils:1.8.0 -commons-codec:commons-codec:1.6 -commons-collections:commons-collections:3.2.1 +commons-codec:commons-codec:1.9 commons-io:commons-io:2.5 -commons-lang:commons-lang:2.4 -commons-logging:commons-logging:1.1.1 +commons-logging:commons-logging:1.2 +io.searchbox:jest-common:0.1.7 +io.searchbox:jest:0.1.7 javax.inject:javax.inject:1 joda-time:joda-time:2.10 junit:junit:4.12 -net.sf.ezmorph:ezmorph:1.0.6 -net.sf.json-lib:json-lib:2.3 -net.sourceforge.nekohtml:nekohtml:1.9.16 +net.logstash.logback:logstash-logback-encoder:4.5.1 org.apache.commons:commons-lang3:3.8.1 -org.apache.httpcomponents:httpclient:4.2.1 -org.apache.httpcomponents:httpcore:4.2.1 +org.apache.httpcomponents:fluent-hc:4.5.1 +org.apache.httpcomponents:httpasyncclient:4.1 +org.apache.httpcomponents:httpclient:4.5.1 +org.apache.httpcomponents:httpcore-nio:4.4.1 +org.apache.httpcomponents:httpcore:4.4.3 org.apache.maven:maven-artifact:3.6.2 org.apache.maven:maven-builder-support:3.6.2 org.apache.maven:maven-model-builder:3.6.2 org.apache.maven:maven-model:3.6.2 -org.codehaus.groovy.modules.http-builder:http-builder:0.7.1 org.codehaus.plexus:plexus-interpolation:1.25 org.codehaus.plexus:plexus-utils:3.2.1 org.eclipse.sisu:org.eclipse.sisu.inject:0.3.3 @@ -46,6 +50,5 @@ org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.61 org.jetbrains.kotlin:kotlin-stdlib:1.3.61 org.jetbrains:annotations:13.0 org.objenesis:objenesis:2.4 +org.slf4j:slf4j-api:1.7.12 org.spockframework:spock-core:1.3-groovy-2.4 -xerces:xercesImpl:2.9.1 -xml-resolver:xml-resolver:1.2 diff --git a/gradle/dependency-locks/testRuntimeClasspath.lockfile b/gradle/dependency-locks/testRuntimeClasspath.lockfile index db78101..bf1ed22 100644 --- a/gradle/dependency-locks/testRuntimeClasspath.lockfile +++ b/gradle/dependency-locks/testRuntimeClasspath.lockfile @@ -2,39 +2,43 @@ # Manual edits can break the build and are not advised. # This file is expected to be part of source control. cglib:cglib-nodep:3.2.2 +ch.qos.logback:logback-core:1.1.3 com.fasterxml.jackson.core:jackson-annotations:2.9.0 com.fasterxml.jackson.core:jackson-core:2.9.9 com.fasterxml.jackson.core:jackson-databind:2.9.9.3 +com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.9 com.fasterxml.jackson.module:jackson-module-kotlin:2.9.9 com.fasterxml.jackson:jackson-bom:2.9.9.20190807 +com.google.code.gson:gson:2.3.1 com.google.guava:guava:20.0 -com.netflix.nebula:gradle-dependency-lock-plugin:7.8.0 -com.netflix.nebula:gradle-scm-plugin:5.0.3 +com.netflix.nebula:gradle-dependency-lock-plugin:10.2.0-rc.1 +com.netflix.nebula:gradle-metrics-plugin:8.4.1 +com.netflix.nebula:gradle-scm-plugin:5.1.0 +com.netflix.nebula:nebula-dependencies-comparison:0.1.8 com.netflix.nebula:nebula-dependency-recommender:9.0.1 com.netflix.nebula:nebula-gradle-interop:1.0.11 com.netflix.nebula:nebula-test:7.6.0 -com.squareup.moshi:moshi:1.8.0 +com.squareup.moshi:moshi:1.9.2 com.squareup.okio:okio:1.16.0 -commons-beanutils:commons-beanutils:1.8.0 -commons-codec:commons-codec:1.6 -commons-collections:commons-collections:3.2.1 +commons-codec:commons-codec:1.9 commons-io:commons-io:2.5 -commons-lang:commons-lang:2.4 -commons-logging:commons-logging:1.1.1 +commons-logging:commons-logging:1.2 +io.searchbox:jest-common:0.1.7 +io.searchbox:jest:0.1.7 javax.inject:javax.inject:1 joda-time:joda-time:2.10 junit:junit:4.12 -net.sf.ezmorph:ezmorph:1.0.6 -net.sf.json-lib:json-lib:2.3 -net.sourceforge.nekohtml:nekohtml:1.9.16 +net.logstash.logback:logstash-logback-encoder:4.5.1 org.apache.commons:commons-lang3:3.8.1 -org.apache.httpcomponents:httpclient:4.2.1 -org.apache.httpcomponents:httpcore:4.2.1 +org.apache.httpcomponents:fluent-hc:4.5.1 +org.apache.httpcomponents:httpasyncclient:4.1 +org.apache.httpcomponents:httpclient:4.5.1 +org.apache.httpcomponents:httpcore-nio:4.4.1 +org.apache.httpcomponents:httpcore:4.4.3 org.apache.maven:maven-artifact:3.6.2 org.apache.maven:maven-builder-support:3.6.2 org.apache.maven:maven-model-builder:3.6.2 org.apache.maven:maven-model:3.6.2 -org.codehaus.groovy.modules.http-builder:http-builder:0.7.1 org.codehaus.plexus:plexus-interpolation:1.25 org.codehaus.plexus:plexus-utils:3.2.1 org.eclipse.sisu:org.eclipse.sisu.inject:0.3.3 @@ -46,6 +50,5 @@ org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.61 org.jetbrains.kotlin:kotlin-stdlib:1.3.61 org.jetbrains:annotations:13.0 org.objenesis:objenesis:2.4 +org.slf4j:slf4j-api:1.7.12 org.spockframework:spock-core:1.3-groovy-2.4 -xerces:xercesImpl:2.9.1 -xml-resolver:xml-resolver:1.2 diff --git a/src/integTest/groovy/nebula/plugin/resolutionrules/AlignAndSubstituteRulesSpec.groovy b/src/integTest/groovy/nebula/plugin/resolutionrules/AlignAndSubstituteRulesSpec.groovy index 8902235..62cf1cf 100644 --- a/src/integTest/groovy/nebula/plugin/resolutionrules/AlignAndSubstituteRulesSpec.groovy +++ b/src/integTest/groovy/nebula/plugin/resolutionrules/AlignAndSubstituteRulesSpec.groovy @@ -1017,6 +1017,64 @@ class AlignAndSubstituteRulesSpec extends IntegrationTestKitSpec { coreAlignment << [false, true] } + @Issue("Based on https://github.com/nebula-plugins/gradle-nebula-integration/issues/11") + @Unroll + def 'apply a static version via dependencySubstitution for 1 direct dep and align results | core alignment #coreAlignment'() { + // this uses the same mechanism as the dependency lock plugin with resolutionStrategy.dependencySubstitution + given: + def graph = new DependencyGraphBuilder() + .addModule('test.nebula:c:0.5.0') + .build() + mavenrepo = new GradleDependencyGenerator(graph, "${projectDir}/testrepogen").generateTestMavenRepo() + + rulesJsonFile << """ + { + "align": [ + $alignRuleForTestNebula + ] + } + """.stripIndent() + + buildFile << """ + dependencies { + implementation 'test.nebula:a:1.0.0' + implementation 'test.nebula:b:0.5.0' + implementation 'test.nebula:c:1.0.0' + } + configurations.all { conf -> + def resolutionStrategySubstitution = conf.resolutionStrategy.dependencySubstitution + def substitutedModule = resolutionStrategySubstitution.module("test.nebula:a") + def withModule = resolutionStrategySubstitution.module("test.nebula:a:0.5.0") + resolutionStrategySubstitution.substitute(substitutedModule) + .because("$reason") + .with(withModule) + } + """.stripIndent() + + when: + def result = runTasks(*tasks(coreAlignment)) + + then: + writeOutputToProjectDir(result.output) + + if (coreAlignment) { + def substitutedVersion = '0.5.0' + dependencyInsightContains(result.output, "test.nebula:a", substitutedVersion) + dependencyInsightContains(result.output, "test.nebula:b", substitutedVersion) + dependencyInsightContains(result.output, "test.nebula:c", substitutedVersion) + + assert result.output.contains("belongs to platform aligned-platform:rules-0-for-test.nebula-or-test.nebula.ext:$substitutedVersion") + } else { + dependencyInsightContains(result.output, "test.nebula:a", resultingVersion) + dependencyInsightContains(result.output, "test.nebula:b", resultingVersion) + dependencyInsightContains(result.output, "test.nebula:c", resultingVersion) + } + + where: + resultingVersion = "1.0.0" + coreAlignment << [false, true] + } + @Issue("Based on https://github.com/nebula-plugins/gradle-nebula-integration/issues/11") @Unroll def 'apply a static version via details.useVersion for each dependency and align results | core alignment #coreAlignment'() { @@ -1176,6 +1234,66 @@ class AlignAndSubstituteRulesSpec extends IntegrationTestKitSpec { coreAlignment << [false, true] } + @Issue("Based on https://github.com/nebula-plugins/gradle-nebula-integration/issues/11") + @Unroll + def 'apply a static version via dependencySubstitution for 1 direct dep and align results without conflict resolution involved | core alignment #coreAlignment'() { + // this uses the same mechanism as the dependency lock plugin with resolutionStrategy.dependencySubstitution + given: + def graph = new DependencyGraphBuilder() + .addModule('test.nebula:c:0.5.0') + .addModule(new ModuleBuilder('test.other:brings-a:1.0.0').addDependency('test.nebula:a:1.0.0').build()) + .build() + mavenrepo = new GradleDependencyGenerator(graph, "${projectDir}/testrepogen").generateTestMavenRepo() + + rulesJsonFile << """ + { + "align": [ + $alignRuleForTestNebula + ] + } + """.stripIndent() + + buildFile << """ + dependencies { + implementation 'test.other:brings-a:1.0.0' + implementation 'test.nebula:b:0.5.0' + implementation 'test.nebula:c:1.0.0' + } + configurations.all { conf -> + def resolutionStrategySubstitution = conf.resolutionStrategy.dependencySubstitution + def substitutedModule = resolutionStrategySubstitution.module("test.nebula:c") + def withModule = resolutionStrategySubstitution.module("test.nebula:c:0.5.0") + resolutionStrategySubstitution.substitute(substitutedModule) + .because("$reason") + .with(withModule) + } + """.stripIndent() + + when: + + def result = runTasks(*tasks(coreAlignment)) + + then: + writeOutputToProjectDir(result.output) + + if (coreAlignment) { + def substitutedVersion = '0.5.0' + dependencyInsightContains(result.output, "test.nebula:a", substitutedVersion) + dependencyInsightContains(result.output, "test.nebula:b", substitutedVersion) + dependencyInsightContains(result.output, "test.nebula:c", substitutedVersion) + + assert result.output.contains("belongs to platform aligned-platform:rules-0-for-test.nebula-or-test.nebula.ext:$substitutedVersion") + } else { + dependencyInsightContains(result.output, "test.nebula:a", resultingVersion) + dependencyInsightContains(result.output, "test.nebula:b", resultingVersion) + dependencyInsightContains(result.output, "test.nebula:c", resultingVersion) + } + + where: + resultingVersion = "1.0.0" + coreAlignment << [false, true] + } + @Unroll def 'statically defined dependency: sub & align all versions higher than x and align | core alignment #coreAlignment'() { given: diff --git a/src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesPluginInteractionSpec.groovy b/src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesPluginInteractionSpec.groovy index 7ef7514..16029d6 100644 --- a/src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesPluginInteractionSpec.groovy +++ b/src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesPluginInteractionSpec.groovy @@ -713,13 +713,13 @@ class AlignRulesPluginInteractionSpec extends IntegrationTestKitSpec { @Unroll def 'dependency-lock when applied after wins out over new locked alignment rules - coreAlignment #coreAlignment'() { - def (GradleDependencyGenerator mavenrepo, File mavenForRules, File jsonRuleFile) = dependencyLockAlignInteractionSetup() + def (GradleDependencyGenerator mavenrepo, File mavenForRules, File jsonRuleFile) = dependencyLockAlignInteractionSetupWithLockedResolutionRulesConfiguration() buildFile << """\ buildscript { repositories { jcenter() } dependencies { - classpath 'com.netflix.nebula:gradle-dependency-lock-plugin:9.0.0' + classpath 'com.netflix.nebula:gradle-dependency-lock-plugin:10.2.0-rc.1' } } @@ -753,6 +753,11 @@ class AlignRulesPluginInteractionSpec extends IntegrationTestKitSpec { results.output.contains 'test.nebula:b:1.42.2\n' resultsForRules.output.contains 'test.rules:resolution-rules:1.+ -> 1.0.0\n' + !results.output.contains('belongs to platform') + !results.output.contains('- Forced') + !resultsForRules.output.contains('belongs to platform') + !resultsForRules.output.contains('- Forced') + when: def resultsIgnoringLocks = runTasks('-PdependencyLock.ignore=true', 'dependencyInsight', '--dependency', 'test.nebula', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") def resultsForRulesIgnoringLocks = runTasks('-PdependencyLock.ignore=true', 'dependencyInsight', '--dependency', 'test.rules', '--configuration', 'resolutionRules', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") @@ -763,13 +768,97 @@ class AlignRulesPluginInteractionSpec extends IntegrationTestKitSpec { resultsIgnoringLocks.output.contains 'test.nebula:b:1.42.2\n' resultsForRulesIgnoringLocks.output.contains 'test.rules:resolution-rules:1.1.0\n' + if (coreAlignment) { + assert resultsIgnoringLocks.output.contains('- By constraint : belongs to platform aligned-platform:rules-0-for-test.nebula:1.42.2\n') + assert resultsIgnoringLocks.output.contains('- By conflict resolution : between versions 1.42.2 and 1.41.5') + } + + !resultsIgnoringLocks.output.contains('- Forced') + !resultsForRulesIgnoringLocks.output.contains('- Forced') + where: coreAlignment << [false, true] } + @Unroll + def 'dependency-lock plugin applied after resolution-rules plugin with non-locked resolution rules - #description - core alignment #coreAlignment'() { + // note: this is a more unusual case. Typically resolution rules are distributed like a library, version controlled, and locked like other dependencies + def (GradleDependencyGenerator mavenrepo, File rulesJsonFile) = dependencyLockAlignInteractionSetupWithUnlockedResolutionRulesConfiguration() + buildFile << """\ + buildscript { + repositories { jcenter() } + dependencies { + classpath 'com.netflix.nebula:gradle-dependency-lock-plugin:10.2.0-rc.1' + } + } + apply plugin: 'nebula.resolution-rules' + apply plugin: 'nebula.dependency-lock' + apply plugin: 'java' + repositories { + ${mavenrepo.mavenRepositoryBlock} + } + dependencies { + resolutionRules files('$rulesJsonFile') + implementation 'test.nebula:a:1.41.5' + implementation 'test.nebula:b:1.42.2' + } + """.stripIndent() + + when: + def insightResults = runTasks('dependencyInsight', '--dependency', 'test.nebula', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + def results = runTasks('dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + + then: + if (coreAlignment) { + assert insightResults.output.contains('Selected by rule : test.nebula:a locked to 1.41.5') + assert insightResults.output.contains('Selected by rule : test.nebula:b locked to 1.42.2') + + assert insightResults.output.contains('Multiple forces on different versions for virtual platform') + + assert results.output.contains('test.nebula:a:1.41.5 FAILED\n') + assert results.output.contains('test.nebula:b:1.42.2 FAILED\n') + } else { + assert results.output.contains('+--- test.nebula:a:1.41.5\n') + assert results.output.contains('\\--- test.nebula:b:1.42.2\n') + } + + when: + def ignoreLocksResults = runTasks('dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment", '-PdependencyLock.ignore=true') + + then: + ignoreLocksResults.output.contains '+--- test.nebula:a:1.41.5 -> 1.42.2\n' + ignoreLocksResults.output.contains '\\--- test.nebula:b:1.42.2\n' + !ignoreLocksResults.output.contains('FAILED') + + when: + runTasks('generateLock', 'saveLock', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + def locksUpdatedInsightResults = runTasks('dependencyInsight', '--dependency', 'test.nebula', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + def locksUpdatedResults = runTasks('dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + + then: + locksUpdatedResults.output.contains '+--- test.nebula:a:1.41.5 -> 1.42.2\n' + locksUpdatedResults.output.contains '\\--- test.nebula:b:1.42.2\n' + locksUpdatedInsightResults.output.contains('Selected by rule : test.nebula:a locked to 1.42.2') + locksUpdatedInsightResults.output.contains('Selected by rule : test.nebula:b locked to 1.42.2') + + if (coreAlignment) { + assert locksUpdatedInsightResults.output.contains('belongs to platform') + assert locksUpdatedInsightResults.output.contains('- Forced') + // this is a little weird, but now it's documented in this test + } else { + assert !locksUpdatedInsightResults.output.contains('belongs to platform') + assert !locksUpdatedInsightResults.output.contains('- Forced') + } + + where: + coreAlignment | description + false | 'locks win out over new alignment rules' + true | 'fail due to multiple forces' + } + @Unroll def 'dependency-lock causes alignment to short circuit if dependencies are aligned by the lock file'() { - def (GradleDependencyGenerator mavenrepo, File mavenForRules, File jsonRuleFile) = dependencyLockAlignInteractionSetup() + def (GradleDependencyGenerator mavenrepo, File jsonRuleFile) = dependencyLockAlignInteractionSetupWithUnlockedResolutionRulesConfiguration() assert jsonRuleFile.exists() assert jsonRuleFile.text.contains('"group": "test.nebula"') @@ -820,7 +909,7 @@ class AlignRulesPluginInteractionSpec extends IntegrationTestKitSpec { coreAlignment << [false, true] } - private List dependencyLockAlignInteractionSetup() { + private List dependencyLockAlignInteractionSetupWithLockedResolutionRulesConfiguration() { def graph = new DependencyGraphBuilder() .addModule('test.nebula:a:1.41.5') .addModule('test.nebula:a:1.42.2') @@ -899,6 +988,46 @@ class AlignRulesPluginInteractionSpec extends IntegrationTestKitSpec { [mavenrepo, mavenForRules, rulesJsonFile] } + private List dependencyLockAlignInteractionSetupWithUnlockedResolutionRulesConfiguration() { + def graph = new DependencyGraphBuilder() + .addModule('test.nebula:a:1.41.5') + .addModule('test.nebula:a:1.42.2') + .addModule('test.nebula:b:1.41.5') + .addModule('test.nebula:b:1.42.2') + .build() + def mavenrepo = new GradleDependencyGenerator(graph, "$projectDir/testrepogen") + mavenrepo.generateTestMavenRepo() + + def rulesJsonFile = new File(projectDir, 'rules.json') + + rulesJsonFile << '''\ + { + "deny": [], "reject": [], "substitute": [], "replace": [], + "align": [ + { + "name": "testNebula", + "group": "test.nebula", + "reason": "Align test.nebula dependencies", + "author": "Example Person ", + "date": "2016-03-17T20:21:20.368Z" + } + ] + } + '''.stripIndent() + + def dependencyLock = new File(projectDir, 'dependencies.lock') + + dependencyLock << '''\ + { + "compileClasspath": { + "test.nebula:a": { "locked": "1.41.5" }, + "test.nebula:b": { "locked": "1.42.2" } + } + } + '''.stripIndent() + [mavenrepo, rulesJsonFile] + } + @Unroll @Issue('#55') def 'alignment does not infinite loop on force to non existent version'() { @@ -1090,14 +1219,14 @@ class AlignRulesPluginInteractionSpec extends IntegrationTestKitSpec { } @Unroll - def 'dependency-lock when applied before wins out over new locked alignment rules'() { - def (GradleDependencyGenerator mavenrepo, File mavenForRules, File jsonRuleFile) = dependencyLockAlignInteractionSetup() + def 'dependency-lock when applied before wins out over new locked alignment rules - core alignment #coreAlignment'() { + def (GradleDependencyGenerator mavenrepo, File mavenForRules, File jsonRuleFile) = dependencyLockAlignInteractionSetupWithLockedResolutionRulesConfiguration() buildFile << """\ buildscript { repositories { jcenter() } dependencies { - classpath 'com.netflix.nebula:gradle-dependency-lock-plugin:9.0.0' + classpath 'com.netflix.nebula:gradle-dependency-lock-plugin:10.2.0-rc.1' } } @@ -1131,6 +1260,11 @@ class AlignRulesPluginInteractionSpec extends IntegrationTestKitSpec { results.output.contains 'test.nebula:b:1.42.2\n' resultsForRules.output.contains 'test.rules:resolution-rules:1.+ -> 1.0.0\n' + !results.output.contains('belongs to platform') + !results.output.contains('- Forced') + !resultsForRules.output.contains('belongs to platform') + !resultsForRules.output.contains('- Forced') + when: def resultsIgnoringLocks = runTasks('-PdependencyLock.ignore=true', 'dependencyInsight', '--dependency', 'test.nebula', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") def resultsForRulesIgnoringLocks = runTasks('-PdependencyLock.ignore=true', 'dependencyInsight', '--dependency', 'test.rules', '--configuration', 'resolutionRules', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") @@ -1141,10 +1275,97 @@ class AlignRulesPluginInteractionSpec extends IntegrationTestKitSpec { resultsIgnoringLocks.output.contains 'test.nebula:b:1.42.2\n' resultsForRulesIgnoringLocks.output.contains 'test.rules:resolution-rules:1.1.0\n' + if (coreAlignment) { + assert resultsIgnoringLocks.output.contains('- By constraint : belongs to platform aligned-platform:rules-0-for-test.nebula:1.42.2\n') + assert resultsIgnoringLocks.output.contains('- By conflict resolution : between versions 1.42.2 and 1.41.5') + } + + !resultsIgnoringLocks.output.contains('- Forced') + !resultsForRulesIgnoringLocks.output.contains('- Forced') + where: coreAlignment << [false, true] } + @Unroll + def 'dependency-lock plugin applied before resolution-rules plugin with non-locked resolution rules - #description - core alignment #coreAlignment'() { + // note: this is a more unusual case. Typically resolution rules are distributed like a library, version controlled, and locked like other dependencies + def (GradleDependencyGenerator mavenrepo, File rulesJsonFile) = dependencyLockAlignInteractionSetupWithUnlockedResolutionRulesConfiguration() + buildFile << """\ + buildscript { + repositories { jcenter() } + dependencies { + classpath 'com.netflix.nebula:gradle-dependency-lock-plugin:10.2.0-rc.1' + } + } + apply plugin: 'nebula.dependency-lock' + apply plugin: 'nebula.resolution-rules' + apply plugin: 'java' + repositories { + ${mavenrepo.mavenRepositoryBlock} + } + dependencies { + resolutionRules files('$rulesJsonFile') + implementation 'test.nebula:a:1.41.5' + implementation 'test.nebula:b:1.42.2' + } + """.stripIndent() + + when: + def insightResults = runTasks('dependencyInsight', '--dependency', 'test.nebula', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + def results = runTasks('dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + + then: + if (coreAlignment) { + assert insightResults.output.contains('Selected by rule : test.nebula:a locked to 1.41.5') + assert insightResults.output.contains('Selected by rule : test.nebula:b locked to 1.42.2') + + assert insightResults.output.contains('Multiple forces on different versions for virtual platform') + + assert results.output.contains('test.nebula:a:1.41.5 FAILED\n') + assert results.output.contains('test.nebula:b:1.42.2 FAILED\n') + } else { + // plugin ordering is important. Dependency lock plugin must be applied after the resolution rules plugin. + // This test case is simply showcasing the current behavior. + assert results.output.contains('+--- test.nebula:a:1.41.5 -> 1.42.2\n') + // this does not honor the locked versions + assert results.output.contains('\\--- test.nebula:b:1.42.2\n') + } + + when: + def ignoreLocksResults = runTasks('dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment", '-PdependencyLock.ignore=true') + + then: + ignoreLocksResults.output.contains '+--- test.nebula:a:1.41.5 -> 1.42.2\n' + ignoreLocksResults.output.contains '\\--- test.nebula:b:1.42.2\n' + !ignoreLocksResults.output.contains('FAILED') + + when: + runTasks('generateLock', 'saveLock', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + def locksUpdatedInsightResults = runTasks('dependencyInsight', '--dependency', 'test.nebula', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + def locksUpdatedResults = runTasks('dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + + then: + locksUpdatedResults.output.contains '+--- test.nebula:a:1.41.5 -> 1.42.2\n' + locksUpdatedResults.output.contains '\\--- test.nebula:b:1.42.2\n' + locksUpdatedInsightResults.output.contains('Selected by rule : test.nebula:a locked to 1.42.2') + locksUpdatedInsightResults.output.contains('Selected by rule : test.nebula:b locked to 1.42.2') + + if (coreAlignment) { + assert locksUpdatedInsightResults.output.contains('belongs to platform') + assert locksUpdatedInsightResults.output.contains('- Forced') + // this is a little weird, but now it's documented in this test + } else { + assert !locksUpdatedInsightResults.output.contains('belongs to platform') + assert !locksUpdatedInsightResults.output.contains('- Forced') + } + + where: + coreAlignment | description + false | 'locks do not win. Plugin ordering is important.' + true | 'fail due to multiple forces' + } + private createRulesJar(Collection files, File unneededRoot, File destination) { Manifest manifest = new Manifest() manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, '1.0')