diff --git a/build.gradle b/build.gradle index 1b408ed..31e487e 100644 --- a/build.gradle +++ b/build.gradle @@ -26,17 +26,11 @@ contacts { } } -repositories { - jcenter() - maven { url 'https://jitpack.io' } // for xmlunit2 - maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } // for xmlunit2 -} - dependencies { compile 'com.netflix.nebula:nebula-gradle-interop:latest.release' compile 'org.apache.maven:maven-model-builder:3.+' testCompile('com.netflix.nebula:nebula-test:latest.release') - testCompile('com.github.xmlunit:xmlunit:7ed02fb294') { + testCompile ('org.xmlunit:xmlunit-core:2.6.0') { exclude module: 'hamcrest-core' } } diff --git a/dependencies.lock b/dependencies.lock index 0499341..4a80dac 100644 --- a/dependencies.lock +++ b/dependencies.lock @@ -5,7 +5,7 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" } }, @@ -15,7 +15,7 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" } }, @@ -25,15 +25,11 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" } }, "integTestCompile": { - "com.github.xmlunit:xmlunit": { - "locked": "7ed02fb294", - "requested": "7ed02fb294" - }, "com.netflix.nebula:nebula-gradle-interop": { "locked": "0.5.0", "requested": "latest.release" @@ -43,15 +39,15 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" + }, + "org.xmlunit:xmlunit-core": { + "locked": "2.6.0", + "requested": "2.6.0" } }, "integTestCompileClasspath": { - "com.github.xmlunit:xmlunit": { - "locked": "7ed02fb294", - "requested": "7ed02fb294" - }, "com.netflix.nebula:nebula-gradle-interop": { "locked": "0.5.0", "requested": "latest.release" @@ -61,15 +57,15 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" + }, + "org.xmlunit:xmlunit-core": { + "locked": "2.6.0", + "requested": "2.6.0" } }, "integTestRuntime": { - "com.github.xmlunit:xmlunit": { - "locked": "7ed02fb294", - "requested": "7ed02fb294" - }, "com.netflix.nebula:nebula-gradle-interop": { "locked": "0.5.0", "requested": "latest.release" @@ -79,15 +75,15 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" + }, + "org.xmlunit:xmlunit-core": { + "locked": "2.6.0", + "requested": "2.6.0" } }, "integTestRuntimeClasspath": { - "com.github.xmlunit:xmlunit": { - "locked": "7ed02fb294", - "requested": "7ed02fb294" - }, "com.netflix.nebula:nebula-gradle-interop": { "locked": "0.5.0", "requested": "latest.release" @@ -97,8 +93,12 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" + }, + "org.xmlunit:xmlunit-core": { + "locked": "2.6.0", + "requested": "2.6.0" } }, "jacocoAgent": { @@ -117,7 +117,7 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" } }, @@ -127,15 +127,11 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" } }, "testCompile": { - "com.github.xmlunit:xmlunit": { - "locked": "7ed02fb294", - "requested": "7ed02fb294" - }, "com.netflix.nebula:nebula-gradle-interop": { "locked": "0.5.0", "requested": "latest.release" @@ -145,15 +141,15 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" + }, + "org.xmlunit:xmlunit-core": { + "locked": "2.6.0", + "requested": "2.6.0" } }, "testCompileClasspath": { - "com.github.xmlunit:xmlunit": { - "locked": "7ed02fb294", - "requested": "7ed02fb294" - }, "com.netflix.nebula:nebula-gradle-interop": { "locked": "0.5.0", "requested": "latest.release" @@ -163,15 +159,15 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" + }, + "org.xmlunit:xmlunit-core": { + "locked": "2.6.0", + "requested": "2.6.0" } }, "testRuntime": { - "com.github.xmlunit:xmlunit": { - "locked": "7ed02fb294", - "requested": "7ed02fb294" - }, "com.netflix.nebula:nebula-gradle-interop": { "locked": "0.5.0", "requested": "latest.release" @@ -181,15 +177,15 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" + }, + "org.xmlunit:xmlunit-core": { + "locked": "2.6.0", + "requested": "2.6.0" } }, "testRuntimeClasspath": { - "com.github.xmlunit:xmlunit": { - "locked": "7ed02fb294", - "requested": "7ed02fb294" - }, "com.netflix.nebula:nebula-gradle-interop": { "locked": "0.5.0", "requested": "latest.release" @@ -199,8 +195,12 @@ "requested": "latest.release" }, "org.apache.maven:maven-model-builder": { - "locked": "3.5.2", + "locked": "3.5.4", "requested": "3.+" + }, + "org.xmlunit:xmlunit-core": { + "locked": "2.6.0", + "requested": "2.6.0" } } } \ No newline at end of file diff --git a/src/main/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPlugin.java b/src/main/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPlugin.java index fd59f8c..69a7d43 100644 --- a/src/main/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPlugin.java +++ b/src/main/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPlugin.java @@ -42,19 +42,39 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import java.util.Set; public class DependencyRecommendationsPlugin implements Plugin { public static final String NEBULA_RECOMMENDER_BOM = "nebulaRecommenderBom"; + public static final boolean CORE_BOM_SUPPORT_ENABLED = Boolean.getBoolean("nebula.features.coreBomSupport"); private Logger logger = Logging.getLogger(DependencyRecommendationsPlugin.class); private RecommendationProviderContainer recommendationProviderContainer; @Override public void apply(final Project project) { - project.getConfigurations().create(NEBULA_RECOMMENDER_BOM); + Configuration bomConfiguration = project.getConfigurations().create(NEBULA_RECOMMENDER_BOM); recommendationProviderContainer = project.getExtensions().create("dependencyRecommendations", RecommendationProviderContainer.class, project); - applyRecommendations(project); - enhanceDependenciesWithRecommender(project); - enhancePublicationsWithBomProducer(project); + + if (CORE_BOM_SUPPORT_ENABLED) { + logger.warn("coreBomSupport feature enabled"); + recommendationProviderContainer.excludeConfigurations("archives", NEBULA_RECOMMENDER_BOM, "provided"); + applyRecommendationsDirectly(project, bomConfiguration); + } else { + applyRecommendations(project); + enhanceDependenciesWithRecommender(project); + enhancePublicationsWithBomProducer(project); + } + } + + private void applyRecommendationsDirectly(final Project project, final Configuration bomConfiguration) { + final Set excluded = recommendationProviderContainer.getExcludedConfigurations(); + project.getConfigurations().all(new ExtendRecommenderConfigurationAction(bomConfiguration, excluded, project)); + project.subprojects(new Action() { + @Override + public void execute(Project sub) { + sub.getConfigurations().all(new ExtendRecommenderConfigurationAction(bomConfiguration, excluded, sub)); + } + }); } private void applyRecommendations(final Project project) { @@ -66,7 +86,7 @@ public void execute(final Configuration conf) { ConfigurationsKt.onResolve(conf, new Function1() { @Override public Unit invoke(ResolvableDependencies resolvableDependencies) { - if(recommendationProviderContainer.getExcludedConfigurations().contains(conf.getName())) { + if (recommendationProviderContainer.getExcludedConfigurations().contains(conf.getName())) { return Unit.INSTANCE; } @@ -167,7 +187,7 @@ protected void enhancePublicationsWithBomProducer(Project project) { /** * Look for recommended versions in a project and each of its ancestors in order until one is found or the root is reached * - * @param project the gradle Project + * @param project the gradle Project * @param mvSelector the module to lookup * @return the recommended version or null */ diff --git a/src/main/groovy/netflix/nebula/dependency/recommender/ExtendRecommenderConfigurationAction.java b/src/main/groovy/netflix/nebula/dependency/recommender/ExtendRecommenderConfigurationAction.java new file mode 100644 index 0000000..509f42e --- /dev/null +++ b/src/main/groovy/netflix/nebula/dependency/recommender/ExtendRecommenderConfigurationAction.java @@ -0,0 +1,33 @@ +package netflix.nebula.dependency.recommender; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; + +import java.util.Set; + +public class ExtendRecommenderConfigurationAction implements Action { + private final Configuration bom; + private final Set excludedConfigurationNames; + private final Project project; + + public ExtendRecommenderConfigurationAction(Configuration bom, Set excludedConfigurationNames, Project project) { + this.bom = bom; + this.excludedConfigurationNames = excludedConfigurationNames; + this.project = project; + } + + @Override + public void execute(Configuration files) { + if (excludedConfigurationNames.contains(files.getName())) { + return; + } + Configuration toExtend = bom; + if (!project.getRootProject().equals(project)) { + toExtend = bom.copy(); + toExtend.setVisible(false); + project.getConfigurations().add(toExtend); + } + files.extendsFrom(toExtend); + } +} diff --git a/src/main/groovy/netflix/nebula/dependency/recommender/provider/RecommendationProviderContainer.java b/src/main/groovy/netflix/nebula/dependency/recommender/provider/RecommendationProviderContainer.java index 8a642d0..c5bb692 100644 --- a/src/main/groovy/netflix/nebula/dependency/recommender/provider/RecommendationProviderContainer.java +++ b/src/main/groovy/netflix/nebula/dependency/recommender/provider/RecommendationProviderContainer.java @@ -19,6 +19,7 @@ import netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin; import netflix.nebula.dependency.recommender.RecommendationStrategies; import org.gradle.api.Action; +import org.gradle.api.GradleException; import org.gradle.api.Namer; import org.gradle.api.Project; import org.gradle.api.internal.ClosureBackedAction; @@ -31,6 +32,8 @@ import java.util.Map; import java.util.Set; +import static netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.CORE_BOM_SUPPORT_ENABLED; + public class RecommendationProviderContainer extends DefaultNamedDomainObjectList { private Project project; @@ -77,6 +80,7 @@ public T addFirst(T provider) { } public PropertyFileRecommendationProvider propertiesFile(Map args) { + ensureCoreBomSupportNotEnabled("propertiesFile"); String message = "nebula.dependency-recommender uses a properties file: " + args.get("file"); reasons.add(message); Map modifiedArgs = new HashMap(args); @@ -84,6 +88,7 @@ public PropertyFileRecommendationProvider propertiesFile(Map args) { } public PropertyFileRecommendationProvider propertiesFile(Closure closure) { + ensureCoreBomSupportNotEnabled("propertiesFile"); String message = "nebula.dependency-recommender uses a properties file"; reasons.add(message); return addProvider(new PropertyFileRecommendationProvider(project), new ClosureBackedAction(closure)); @@ -95,10 +100,12 @@ public MavenBomRecommendationProvider mavenBom(Map args) { throw new IllegalArgumentException("Module may not be null"); } - if(Map.class.isAssignableFrom(dependencyNotation.getClass())) { - ((Map) dependencyNotation).put("ext", "pom"); - } else if(!dependencyNotation.toString().endsWith("@pom")) { - dependencyNotation = dependencyNotation.toString() + "@pom"; + if (!CORE_BOM_SUPPORT_ENABLED) { + if (Map.class.isAssignableFrom(dependencyNotation.getClass())) { + ((Map) dependencyNotation).put("ext", "pom"); + } else if (!dependencyNotation.toString().endsWith("@pom")) { + dependencyNotation = dependencyNotation.toString() + "@pom"; + } } project.getDependencies().add(DependencyRecommendationsPlugin.NEBULA_RECOMMENDER_BOM, dependencyNotation); @@ -106,6 +113,7 @@ public MavenBomRecommendationProvider mavenBom(Map args) { } public IvyRecommendationProvider ivyXml(Map args) { + ensureCoreBomSupportNotEnabled("ivyXml"); String message = "nebula.dependency-recommender uses a ivyXml: " + args.get("module"); reasons.add(message); Map modifiedArgs = new HashMap(args); @@ -113,12 +121,14 @@ public IvyRecommendationProvider ivyXml(Map args) { } public IvyRecommendationProvider ivyXml(Closure closure) { + ensureCoreBomSupportNotEnabled("ivyXml"); String message = "nebula.dependency-recommender uses a ivyXml"; reasons.add(message); return addProvider(new IvyRecommendationProvider(project), new ClosureBackedAction(closure)); } public DependencyLockProvider dependencyLock(Map args) { + ensureCoreBomSupportNotEnabled("dependencyLock"); String message = "nebula.dependency-recommender uses a dependency lock: " + args.get("module"); reasons.add(message); Map modifiedArgs = new HashMap(args); @@ -126,12 +136,14 @@ public DependencyLockProvider dependencyLock(Map args) { } public DependencyLockProvider dependencyLock(Closure closure) { + ensureCoreBomSupportNotEnabled("dependencyLock"); String message = "nebula.dependency-recommender uses a dependency lock for recommendations"; reasons.add(message); return addProvider(new DependencyLockProvider(project), new ClosureBackedAction(closure)); } public MapRecommendationProvider map(Map args) { + ensureCoreBomSupportNotEnabled("map"); String message = "nebula.dependency-recommender uses a provided map for recommendations"; reasons.add(message); Map modifiedArgs = new HashMap(args); @@ -139,12 +151,14 @@ public MapRecommendationProvider map(Map args) { } public MapRecommendationProvider map(Closure closure) { + ensureCoreBomSupportNotEnabled("map"); String message = "nebula.dependency-recommender uses a provided map for recommendations"; reasons.add(message); return addProvider(new MapRecommendationProvider(), new ClosureBackedAction(closure)); } public CustomRecommendationProvider addProvider(Closure closure) { + ensureCoreBomSupportNotEnabled("addProvider"); String message = "nebula.dependency-recommender uses a CustomRecommendationProvider"; reasons.add(message); return addProvider(new CustomRecommendationProvider(closure), new Action() { @@ -200,4 +214,10 @@ public Set getExcludedConfigurations() { public Set getReasons() { return reasons; } + + private static void ensureCoreBomSupportNotEnabled(String feature) { + if(CORE_BOM_SUPPORT_ENABLED) { + throw new GradleException("dependencyRecommender." + feature + " is not available with 'systemProp.nebula.features.coreBomSupport=true'"); + } + } } diff --git a/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPluginCompositeCoreBomSupportSpec.groovy b/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPluginCompositeCoreBomSupportSpec.groovy new file mode 100644 index 0000000..992f046 --- /dev/null +++ b/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPluginCompositeCoreBomSupportSpec.groovy @@ -0,0 +1,127 @@ +/* + * Copyright 2016-2017 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 netflix.nebula.dependency.recommender + +import nebula.test.IntegrationSpec +import nebula.test.dependencies.DependencyGraphBuilder +import nebula.test.dependencies.GradleDependencyGenerator +import nebula.test.dependencies.maven.ArtifactType +import nebula.test.dependencies.maven.Pom +import nebula.test.dependencies.repositories.MavenRepo + +class DependencyRecommendationsPluginCompositeCoreBomSupportSpec extends IntegrationSpec { + def repo + def generator + + def setup() { + fork = true + new File("${projectDir}/gradle.properties").text = "systemProp.nebula.features.coreBomSupport=true" + + settingsFile << """\ + enableFeaturePreview('IMPROVED_POM_SUPPORT') + """.stripIndent() + + generateRepoIn(projectDir) + } + + private void generateRepoIn(File projectDir) { + repo = new MavenRepo() + repo.root = new File(projectDir, 'build/bomrepo') + def pom = new Pom('test.nebula.bom', 'testbom', '1.0.0', ArtifactType.POM) + pom.addManagementDependency('test.nebula', 'foo', '1.0.0') + repo.poms.add(pom) + repo.generate() + def graph = new DependencyGraphBuilder() + .addModule('test.nebula:foo:1.0.0') + .build() + generator = new GradleDependencyGenerator(graph) + generator.generateTestMavenRepo() + } + + def 'can use recommender in a composite'() { + def a = addSubproject('a', '''\ + dependencies { + compile 'test.nebula:foo' + } + '''.stripIndent()) + writeHelloWorld('a', a) + def b = addSubproject('b', '''\ + dependencies { + compile project(':a') + } + '''.stripIndent()) + writeHelloWorld('b', b) + + buildFile << """\ + apply plugin: 'nebula.dependency-recommender' + dependencyRecommendations { + mavenBom module: 'test.nebula.bom:testbom:latest.release' + } + + allprojects { + group 'example' + apply plugin: 'java' + + repositories { + maven { url '${repo.root.absoluteFile.toURI()}' } + ${generator.mavenRepositoryBlock} + } + } + """.stripIndent() + + def compositeDir = new File(projectDir.parentFile, "${projectDir.name}-composite") + compositeDir.deleteDir() + projectDir.renameTo(compositeDir) + projectDir.mkdirs() + generateRepoIn(projectDir) + new File("${projectDir}/gradle.properties").text = "systemProp.nebula.features.coreBomSupport=true" + + // Composite + buildFile << """\ + apply plugin: 'java' + apply plugin: 'nebula.dependency-recommender' + + dependencyRecommendations { + mavenBom module: 'test.nebula.bom:testbom:latest.release' + } + + repositories { + maven { url '${repo.root.absoluteFile.toURI()}' } + ${generator.mavenRepositoryBlock} + } + + dependencies { + compile 'example:b:1.0.0' + } + """.stripIndent() + settingsFile << """\ + rootProject.name = 'composite' + includeBuild '$compositeDir' + enableFeaturePreview('IMPROVED_POM_SUPPORT') + """ + writeHelloWorld('c') + + when: + def results = runTasksSuccessfully(':dependencies') + + then: + noExceptionThrown() + results.standardOutput.contains 'Found project \'project :can-use-recommender-in-a-composite:b\' as substitute for module \'example:b\'.' + results.standardOutput.contains '+--- example:b:1.0.0 -> project :can-use-recommender-in-a-composite:b' + results.standardOutput.contains '| +--- project :can-use-recommender-in-a-composite:a' + results.standardOutput.contains '| | +--- test.nebula:foo -> 1.0.0' + } +} diff --git a/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPluginCoreBomSupportSpec.groovy b/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPluginCoreBomSupportSpec.groovy new file mode 100644 index 0000000..dda81c6 --- /dev/null +++ b/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPluginCoreBomSupportSpec.groovy @@ -0,0 +1,120 @@ +/* + * Copyright 2016-2017 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 netflix.nebula.dependency.recommender + +import nebula.test.IntegrationSpec +import nebula.test.dependencies.DependencyGraphBuilder +import nebula.test.dependencies.GradleDependencyGenerator +import nebula.test.dependencies.maven.ArtifactType +import nebula.test.dependencies.maven.Pom +import nebula.test.dependencies.repositories.MavenRepo +import spock.lang.Unroll + +class DependencyRecommendationsPluginCoreBomSupportSpec extends IntegrationSpec { + def repo + def generator + + def setup() { + fork = true + new File("${projectDir}/gradle.properties").text = "systemProp.nebula.features.coreBomSupport=true" + + settingsFile << """\ + enableFeaturePreview('IMPROVED_POM_SUPPORT') + """.stripIndent() + + repo = new MavenRepo() + repo.root = new File(projectDir, 'build/bomrepo') + def pom = new Pom('test.nebula.bom', 'testbom', '1.0.0', ArtifactType.POM) + pom.addManagementDependency('test.nebula', 'foo', '1.0.0') + pom.addManagementDependency('test.nebula', 'bar', '2.0.0') + pom.addManagementDependency('test.nebula', 'baz', '2.5.0') + pom.addManagementDependency('test.nebula', 'lib', '3.9.9') + repo.poms.add(pom) + repo.generate() + def graph = new DependencyGraphBuilder() + .addModule('test.nebula:foo:1.0.0') + .addModule('test.nebula:bar:2.0.0') + .addModule('test.nebula:baz:2.5.0') + .addModule('test.nebula:lib:3.9.9') + .build() + generator = new GradleDependencyGenerator(graph) + generator.generateTestMavenRepo() + } + + def 'add given bom to configs'() { + buildFile << """\ + apply plugin: 'nebula.dependency-recommender' + apply plugin: 'java' + apply plugin: 'war' + + repositories { + maven { url '${repo.root.absoluteFile.toURI()}' } + ${generator.mavenRepositoryBlock} + } + + dependencyRecommendations { + mavenBom module: 'test.nebula.bom:testbom:latest.release' + } + + dependencies { + annotationProcessor 'test.nebula:bar' + compile 'test.nebula:foo' + providedCompile 'test.nebula:lib' + runtimeOnly 'test.nebula:baz' + } + """.stripIndent() + + when: + def result = runTasksSuccessfully('dependencies') + + then: + result.standardOutput.contains("+--- test.nebula:foo -> 1.0.0") + result.standardOutput.contains("+--- test.nebula:bar -> 2.0.0") + result.standardOutput.contains("\\--- test.nebula:baz -> 2.5.0") + result.standardOutput.contains("\\--- test.nebula:lib -> 3.9.9") + } + + @Unroll + def 'error when #type(#argType) used'() { + given: + buildFile << """\ + apply plugin: 'nebula.dependency-recommender' + apply plugin: 'java' + + dependencyRecommendations { + $type $arg + } + """.stripIndent() + + when: + def result = runTasksWithFailure('dependencies', '--configuration', 'compileClasspath') + + then: + result.standardOutput.contains("> dependencyRecommender.$type is not available with 'systemProp.nebula.features.coreBomSupport=true'") + + where: + type | argType | arg + 'map' | '[:]' | "recommendations: ['test.nebula:foo': '1.0.0']" + 'map' | '{}' | "{ [recommendations: ['test.nebula:foo': '1.0.0']] }" + 'dependencyLock' | '[:]' | "module: 'sample:dependencies:1.0'" + 'dependencyLock' | '{}' | "{ [module: 'sample:dependencies:1.0'] }" + 'ivyXml' | '[:]' | "module: 'sample:sample:1.0'" + 'ivyXml' | '{}' | "{ [module: 'sample:sample:1.0'] }" + 'propertiesFile' | '[:]' | "file: 'recommendations.props'" + 'propertiesFile' | '{}' | "{ [file: 'recommendations.props'] }" + 'addProvider' | '{}' | "{ org, name -> 'latest.release' }" + } +} diff --git a/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPluginMultiprojectCoreBomSupportSpec.groovy b/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPluginMultiprojectCoreBomSupportSpec.groovy new file mode 100644 index 0000000..72fc5ce --- /dev/null +++ b/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPluginMultiprojectCoreBomSupportSpec.groovy @@ -0,0 +1,85 @@ +/* + * Copyright 2016-2017 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 netflix.nebula.dependency.recommender + +import nebula.test.IntegrationSpec +import nebula.test.dependencies.DependencyGraphBuilder +import nebula.test.dependencies.GradleDependencyGenerator +import nebula.test.dependencies.ModuleBuilder +import nebula.test.dependencies.maven.ArtifactType +import nebula.test.dependencies.maven.Pom +import nebula.test.dependencies.repositories.MavenRepo + +class DependencyRecommendationsPluginMultiprojectCoreBomSupportSpec extends IntegrationSpec { + def repo + def generator + + def setup() { + fork = true + new File("${projectDir}/gradle.properties").text = "systemProp.nebula.features.coreBomSupport=true" + + settingsFile << """\ + enableFeaturePreview('IMPROVED_POM_SUPPORT') + """.stripIndent() + + repo = new MavenRepo() + repo.root = new File(projectDir, 'build/bomrepo') + def pom = new Pom('test.nebula.bom', 'testbom', '1.0.0', ArtifactType.POM) + pom.addManagementDependency('test.nebula', 'foo', '1.0.0') + repo.poms.add(pom) + repo.generate() + def graph = new DependencyGraphBuilder() + .addModule('test.nebula:foo:1.0.0') + .build() + generator = new GradleDependencyGenerator(graph) + generator.generateTestMavenRepo() + } + + def 'can use recommender across a multiproject'() { + def a = addSubproject('a', '''\ + dependencies { + compile 'test.nebula:foo' + } + '''.stripIndent()) + writeHelloWorld('a', a) + def b = addSubproject('b', '''\ + dependencies { + compile project(':a') + } + '''.stripIndent()) + writeHelloWorld('b', b) + buildFile << """\ + apply plugin: 'nebula.dependency-recommender' + dependencyRecommendations { + mavenBom module: 'test.nebula.bom:testbom:latest.release' + } + + allprojects { + apply plugin: 'java' + + repositories { + maven { url '${repo.root.absoluteFile.toURI()}' } + ${generator.mavenRepositoryBlock} + } + } + """.stripIndent() + when: + def results = runTasksSuccessfully(':a:dependencies', '--configuration', 'compileClasspath') + + then: + results.standardOutput.contains("+--- test.nebula:foo -> 1.0.0") + } +}