From 65df12752636f6071bcc866e8468b9cc82d6c020 Mon Sep 17 00:00:00 2001 From: Aubrey Chipman Date: Wed, 23 Sep 2020 15:15:57 -0700 Subject: [PATCH 1/4] Use com.netflix.nebula:gradle-dependency-lock-plugin:10.2.0-rc.1 which assists with core alignment This version of the lock plugin uses resolutionStrategy.dependencySubstitution.substitute instead of resolutionStrategy.eachDependency See: https://github.com/nebula-plugins/gradle-dependency-lock-plugin/releases/tag/v10.2.0-rc.1 --- build.gradle | 13 ++++++- gradle/dependency-locks/default.lockfile | 26 -------------- .../integTestRuntimeClasspath.lockfile | 35 ++++++++++--------- .../testRuntimeClasspath.lockfile | 35 ++++++++++--------- 4 files changed, 50 insertions(+), 59 deletions(-) delete mode 100644 gradle/dependency-locks/default.lockfile 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 From 43ba74d6bc9c7352261380a8c81a170981d973b1 Mon Sep 17 00:00:00 2001 From: Aubrey Chipman Date: Wed, 23 Sep 2020 17:26:18 -0700 Subject: [PATCH 2/4] Add a substitution and alignment test that uses resolutionStrategy.dependencySubstitution rather than details.useVersion Versions set with details.useVersion will add to conflict resolution for core aligment whereas versions set with resolutionStrategy.dependencySubstitution will have this constraint applied to aligned platforms when using core alignment. --- .../AlignAndSubstituteRulesSpec.groovy | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) 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: From 190f678f6f9fa978ffc744dee414770f2b758718 Mon Sep 17 00:00:00 2001 From: Aubrey Chipman Date: Wed, 23 Sep 2020 17:53:59 -0700 Subject: [PATCH 3/4] Align rules and locking plugin interaction tests --- ...gnRulesLockingPluginInteractionSpec.groovy | 490 ++++++++++++++++++ 1 file changed, 490 insertions(+) create mode 100644 src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesLockingPluginInteractionSpec.groovy diff --git a/src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesLockingPluginInteractionSpec.groovy b/src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesLockingPluginInteractionSpec.groovy new file mode 100644 index 0000000..81e8c16 --- /dev/null +++ b/src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesLockingPluginInteractionSpec.groovy @@ -0,0 +1,490 @@ +/* + * Copyright 2016 Netflix, Inc. + * + * 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 nebula.plugin.resolutionrules + +import nebula.test.IntegrationTestKitSpec +import nebula.test.dependencies.DependencyGraphBuilder +import nebula.test.dependencies.GradleDependencyGenerator +import spock.lang.Unroll + +import java.util.jar.Attributes +import java.util.jar.JarEntry +import java.util.jar.JarOutputStream +import java.util.jar.Manifest + +class AlignRulesLockingPluginInteractionSpec extends IntegrationTestKitSpec { + def setup() { + definePluginOutsideOfPluginBlock = true + debug = true + keepFiles = true + } + + @Unroll + 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:10.2.0-rc.1' + } + } + + apply plugin: 'nebula.dependency-lock' + apply plugin: 'nebula.resolution-rules' + apply plugin: 'java' + + repositories { + ${mavenrepo.mavenRepositoryBlock} + maven { url '${mavenForRules.absolutePath}' } + } + + dependencies { + resolutionRules 'test.rules:resolution-rules:1.+' + implementation 'test.nebula:a:1.41.5' + implementation 'test.nebula:b:1.42.2' + } + """.stripIndent() + + when: + def results = runTasks('dependencyInsight', '--dependency', 'test.nebula', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + def resultsForRules = runTasks('dependencyInsight', '--dependency', 'test.rules', '--configuration', 'resolutionRules', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + + then: + results.output.contains 'test.nebula:a locked to 1.41.5' + results.output.contains 'test.nebula:b locked to 1.42.2' + resultsForRules.output.contains 'Selected by rule : test.rules:resolution-rules locked to 1.0.0' + + // final results where locks win over new alignment rules + results.output.contains 'test.nebula:a:1.41.5\n' + 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") + + then: + // final results if we ignore locks + resultsIgnoringLocks.output.contains 'test.nebula:a:1.42.2\n' + 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 when applied after wins out over new locked alignment rules - coreAlignment #coreAlignment'() { + def (GradleDependencyGenerator mavenrepo, File mavenForRules, File jsonRuleFile) = dependencyLockAlignInteractionSetupWithLockedResolutionRulesConfiguration() + + 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} + maven { url '${mavenForRules.absolutePath}' } + } + + dependencies { + resolutionRules 'test.rules:resolution-rules:1.+' + implementation 'test.nebula:a:1.41.5' + implementation 'test.nebula:b:1.42.2' + } + """.stripIndent() + + when: + def results = runTasks('dependencyInsight', '--dependency', 'test.nebula', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + def resultsForRules = runTasks('dependencyInsight', '--dependency', 'test.rules', '--configuration', 'resolutionRules', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") + + then: + results.output.contains 'test.nebula:a locked to 1.41.5' + results.output.contains 'test.nebula:b locked to 1.42.2' + resultsForRules.output.contains 'Selected by rule : test.rules:resolution-rules locked to 1.0.0' + + // final results where locks win over new alignment rules + results.output.contains 'test.nebula:a:1.41.5\n' + 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") + + then: + // final results if we ignore locks + resultsIgnoringLocks.output.contains 'test.nebula:a:1.42.2\n' + 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 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 List dependencyLockAlignInteractionSetupWithLockedResolutionRulesConfiguration() { + 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 rulesFolder = new File(projectDir, 'rules') + rulesFolder.mkdirs() + def rulesJsonFile = new File(rulesFolder, 'rules.json') + + rulesJsonFile << '''\ + { + "deny": [], "reject": [], "substitute": [], "replace": [], "align": [] + } + '''.stripIndent() + + def mavenForRules = new File(projectDir, 'repo') + mavenForRules.mkdirs() + def locked = new File(mavenForRules, 'test/rules/resolution-rules/1.0.0') + locked.mkdirs() + createRulesJar([rulesFolder], projectDir, new File(locked, 'resolution-rules-1.0.0.jar')) + createPom('test.rules', 'resolution-rules', '1.0.0', locked) + + rulesJsonFile.text = '''\ + { + "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 newer = new File(mavenForRules, 'test/rules/resolution-rules/1.1.0') + newer.mkdirs() + createRulesJar([rulesFolder], projectDir, new File(newer, 'resolution-rules-1.1.0.jar')) + createPom('test.rules', 'resolution-rules', '1.1.0', newer) + + def mavenMetadataXml = new File(mavenForRules, 'test/rules/resolution-rules/maven-metadata.xml') + mavenMetadataXml.createNewFile() + mavenMetadataXml << ''' + + test.rules + resolution-rules + + 1.1.0 + 1.1.0 + + 1.0.0 + 1.1.0 + + 20200320014943 + + +''' + + def dependencyLock = new File(projectDir, 'dependencies.lock') + dependencyLock << '''\ + { + "compileClasspath": { + "test.nebula:a": { "locked": "1.41.5" }, + "test.nebula:b": { "locked": "1.42.2" } + }, + "resolutionRules": { + "test.rules:resolution-rules": { "locked": "1.0.0" } + } + } + '''.stripIndent() + [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] + } + + private createRulesJar(Collection files, File unneededRoot, File destination) { + Manifest manifest = new Manifest() + manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, '1.0') + JarOutputStream target = new JarOutputStream(new FileOutputStream(destination), manifest) + files.each { add(it, unneededRoot, target) } + target.close() + } + + private createPom(String group, String name, String version, File dir) { + def pom = new File(dir, "${name}-${version}.pom") + pom.text = """\ + + + 4.0.0 + ${group} + ${name} + ${version} + + """.stripIndent() + } + + private void add(File source, File unneededRoot, JarOutputStream target) throws IOException { + def prefix = "${unneededRoot.path}/" + if (source.isDirectory()) { + String dirName = source.path - prefix + if (!dirName.endsWith('/')) { + dirName += '/' + } + def entry = new JarEntry(dirName) + target.putNextEntry(entry) + target.closeEntry() + source.listFiles().each { nested -> + add(nested, unneededRoot, target) + } + } else { + def entry = new JarEntry(source.path - prefix) + target.putNextEntry(entry) + target << source.bytes + target.closeEntry() + } + } +} From 0f5a050c97c913c14c240d94160a0afc2f2ee6ce Mon Sep 17 00:00:00 2001 From: Aubrey Chipman Date: Wed, 23 Sep 2020 18:45:33 -0700 Subject: [PATCH 4/4] Align rules and locking plugin interaction tests --- ...gnRulesLockingPluginInteractionSpec.groovy | 490 ------------------ .../AlignRulesPluginInteractionSpec.groovy | 235 ++++++++- 2 files changed, 228 insertions(+), 497 deletions(-) delete mode 100644 src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesLockingPluginInteractionSpec.groovy diff --git a/src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesLockingPluginInteractionSpec.groovy b/src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesLockingPluginInteractionSpec.groovy deleted file mode 100644 index 81e8c16..0000000 --- a/src/integTest/groovy/nebula/plugin/resolutionrules/AlignRulesLockingPluginInteractionSpec.groovy +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright 2016 Netflix, Inc. - * - * 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 nebula.plugin.resolutionrules - -import nebula.test.IntegrationTestKitSpec -import nebula.test.dependencies.DependencyGraphBuilder -import nebula.test.dependencies.GradleDependencyGenerator -import spock.lang.Unroll - -import java.util.jar.Attributes -import java.util.jar.JarEntry -import java.util.jar.JarOutputStream -import java.util.jar.Manifest - -class AlignRulesLockingPluginInteractionSpec extends IntegrationTestKitSpec { - def setup() { - definePluginOutsideOfPluginBlock = true - debug = true - keepFiles = true - } - - @Unroll - 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:10.2.0-rc.1' - } - } - - apply plugin: 'nebula.dependency-lock' - apply plugin: 'nebula.resolution-rules' - apply plugin: 'java' - - repositories { - ${mavenrepo.mavenRepositoryBlock} - maven { url '${mavenForRules.absolutePath}' } - } - - dependencies { - resolutionRules 'test.rules:resolution-rules:1.+' - implementation 'test.nebula:a:1.41.5' - implementation 'test.nebula:b:1.42.2' - } - """.stripIndent() - - when: - def results = runTasks('dependencyInsight', '--dependency', 'test.nebula', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") - def resultsForRules = runTasks('dependencyInsight', '--dependency', 'test.rules', '--configuration', 'resolutionRules', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") - - then: - results.output.contains 'test.nebula:a locked to 1.41.5' - results.output.contains 'test.nebula:b locked to 1.42.2' - resultsForRules.output.contains 'Selected by rule : test.rules:resolution-rules locked to 1.0.0' - - // final results where locks win over new alignment rules - results.output.contains 'test.nebula:a:1.41.5\n' - 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") - - then: - // final results if we ignore locks - resultsIgnoringLocks.output.contains 'test.nebula:a:1.42.2\n' - 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 when applied after wins out over new locked alignment rules - coreAlignment #coreAlignment'() { - def (GradleDependencyGenerator mavenrepo, File mavenForRules, File jsonRuleFile) = dependencyLockAlignInteractionSetupWithLockedResolutionRulesConfiguration() - - 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} - maven { url '${mavenForRules.absolutePath}' } - } - - dependencies { - resolutionRules 'test.rules:resolution-rules:1.+' - implementation 'test.nebula:a:1.41.5' - implementation 'test.nebula:b:1.42.2' - } - """.stripIndent() - - when: - def results = runTasks('dependencyInsight', '--dependency', 'test.nebula', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") - def resultsForRules = runTasks('dependencyInsight', '--dependency', 'test.rules', '--configuration', 'resolutionRules', "-Dnebula.features.coreAlignmentSupport=$coreAlignment") - - then: - results.output.contains 'test.nebula:a locked to 1.41.5' - results.output.contains 'test.nebula:b locked to 1.42.2' - resultsForRules.output.contains 'Selected by rule : test.rules:resolution-rules locked to 1.0.0' - - // final results where locks win over new alignment rules - results.output.contains 'test.nebula:a:1.41.5\n' - 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") - - then: - // final results if we ignore locks - resultsIgnoringLocks.output.contains 'test.nebula:a:1.42.2\n' - 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 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 List dependencyLockAlignInteractionSetupWithLockedResolutionRulesConfiguration() { - 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 rulesFolder = new File(projectDir, 'rules') - rulesFolder.mkdirs() - def rulesJsonFile = new File(rulesFolder, 'rules.json') - - rulesJsonFile << '''\ - { - "deny": [], "reject": [], "substitute": [], "replace": [], "align": [] - } - '''.stripIndent() - - def mavenForRules = new File(projectDir, 'repo') - mavenForRules.mkdirs() - def locked = new File(mavenForRules, 'test/rules/resolution-rules/1.0.0') - locked.mkdirs() - createRulesJar([rulesFolder], projectDir, new File(locked, 'resolution-rules-1.0.0.jar')) - createPom('test.rules', 'resolution-rules', '1.0.0', locked) - - rulesJsonFile.text = '''\ - { - "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 newer = new File(mavenForRules, 'test/rules/resolution-rules/1.1.0') - newer.mkdirs() - createRulesJar([rulesFolder], projectDir, new File(newer, 'resolution-rules-1.1.0.jar')) - createPom('test.rules', 'resolution-rules', '1.1.0', newer) - - def mavenMetadataXml = new File(mavenForRules, 'test/rules/resolution-rules/maven-metadata.xml') - mavenMetadataXml.createNewFile() - mavenMetadataXml << ''' - - test.rules - resolution-rules - - 1.1.0 - 1.1.0 - - 1.0.0 - 1.1.0 - - 20200320014943 - - -''' - - def dependencyLock = new File(projectDir, 'dependencies.lock') - dependencyLock << '''\ - { - "compileClasspath": { - "test.nebula:a": { "locked": "1.41.5" }, - "test.nebula:b": { "locked": "1.42.2" } - }, - "resolutionRules": { - "test.rules:resolution-rules": { "locked": "1.0.0" } - } - } - '''.stripIndent() - [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] - } - - private createRulesJar(Collection files, File unneededRoot, File destination) { - Manifest manifest = new Manifest() - manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, '1.0') - JarOutputStream target = new JarOutputStream(new FileOutputStream(destination), manifest) - files.each { add(it, unneededRoot, target) } - target.close() - } - - private createPom(String group, String name, String version, File dir) { - def pom = new File(dir, "${name}-${version}.pom") - pom.text = """\ - - - 4.0.0 - ${group} - ${name} - ${version} - - """.stripIndent() - } - - private void add(File source, File unneededRoot, JarOutputStream target) throws IOException { - def prefix = "${unneededRoot.path}/" - if (source.isDirectory()) { - String dirName = source.path - prefix - if (!dirName.endsWith('/')) { - dirName += '/' - } - def entry = new JarEntry(dirName) - target.putNextEntry(entry) - target.closeEntry() - source.listFiles().each { nested -> - add(nested, unneededRoot, target) - } - } else { - def entry = new JarEntry(source.path - prefix) - target.putNextEntry(entry) - target << source.bytes - target.closeEntry() - } - } -} 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')