diff --git a/CHANGELOG.md b/CHANGELOG.md index ebf83f9..24fb143 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +3.6.3 / 2016-07-19 +================== + +* *BUGFIX* handle recommendations across a multiproject where subproject B depends on A which has a dependency it needs to pick up from recommendations + 3.2.0 / 2016-01-11 ================== diff --git a/README.md b/README.md index dff2f76..0545b1b 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ buildscript { repositories { jcenter() } dependencies { - classpath 'com.netflix.nebula:nebula-dependency-recommender:3.4.0' + classpath 'com.netflix.nebula:nebula-dependency-recommender:3.6.3' } } diff --git a/src/main/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPlugin.java b/src/main/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPlugin.java index 382c0ff..3a462d6 100644 --- a/src/main/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPlugin.java +++ b/src/main/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsPlugin.java @@ -12,6 +12,9 @@ import org.gradle.api.logging.Logging; import org.gradle.api.plugins.ExtraPropertiesExtension; +import java.util.ArrayList; +import java.util.List; + public class DependencyRecommendationsPlugin implements Plugin { private Logger logger = Logging.getLogger(DependencyRecommendationsPlugin.class); @@ -23,6 +26,20 @@ public void apply(final Project project) { enhancePublicationsWithBomProducer(project); } + private void applyRecommendationToDependency(final RecommendationStrategyFactory factory, Dependency dependency, List visited) { + if (dependency instanceof ExternalModuleDependency) { + factory.getRecommendationStrategy().inspectDependency(dependency); + } else if (dependency instanceof ProjectDependency) { + if (!visited.contains(dependency)) { + visited.add((ProjectDependency)dependency); + DependencySet dependencies = ((ProjectDependency) dependency).getProjectConfiguration().getAllDependencies(); + for (Dependency dep : dependencies) { + applyRecommendationToDependency(factory, dep, visited); + } + } + } + } + private void applyRecommendations(final Project project) { project.getConfigurations().all(new Action() { @Override @@ -32,7 +49,10 @@ public void execute(final Configuration conf) { @Override public void execute(ResolvableDependencies resolvableDependencies) { for (Dependency dependency : resolvableDependencies.getDependencies()) { - rsFactory.getRecommendationStrategy().inspectDependency(dependency); + applyRecommendationToDependency(rsFactory, dependency, new ArrayList()); + + // if project dependency, pull all first orders and apply recomendations if missing dependency versions + // dependency.getProjectConfiguration().allDependencies iterate and inspect them as well } conf.getResolutionStrategy().eachDependency(new Action() { diff --git a/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsMultiprojectPluginSpec.groovy b/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsMultiprojectPluginSpec.groovy new file mode 100644 index 0000000..cd55585 --- /dev/null +++ b/src/test/groovy/netflix/nebula/dependency/recommender/DependencyRecommendationsMultiprojectPluginSpec.groovy @@ -0,0 +1,52 @@ +package netflix.nebula.dependency.recommender + +import nebula.test.IntegrationSpec +import nebula.test.dependencies.DependencyGraphBuilder +import nebula.test.dependencies.GradleDependencyGenerator + +class DependencyRecommendationsMultiprojectPluginSpec extends IntegrationSpec { + def 'can use recommender across a multiproject'() { + def depGraph = new DependencyGraphBuilder() + .addModule('example:foo:1.0.0') + .addModule('example:bar:1.0.0') + .build() + def generator = new GradleDependencyGenerator(depGraph) + generator.generateTestMavenRepo() + + def a = addSubproject('a', '''\ + dependencies { + compile 'example:foo' + } + '''.stripIndent()) + writeHelloWorld('a', a) + def b = addSubproject('b', '''\ + dependencies { + compile project(':a') + } + '''.stripIndent()) + writeHelloWorld('b', b) + buildFile << """\ + allprojects { + apply plugin: 'nebula.dependency-recommender' + dependencyRecommendations { + map recommendations: ['example:foo': '1.0.0'] + } + } + subprojects { + apply plugin: 'java' + + repositories { + ${generator.mavenRepositoryBlock} + } + } + """.stripIndent() + when: + def results = runTasksSuccessfully(':a:dependencies', ':b:dependencies', 'build') + + then: + noExceptionThrown() + results.standardOutput.contains 'Recommending version 1.0.0 for dependency example:foo\n' + + '\\--- project :a\n' + + ' \\--- example:foo: -> 1.0.0' + } +}