|
21 | 21 | import netflix.nebula.dependency.recommender.provider.RecommendationProviderContainer; |
22 | 22 | import netflix.nebula.dependency.recommender.provider.RecommendationResolver; |
23 | 23 | import netflix.nebula.dependency.recommender.publisher.MavenBomXmlGenerator; |
| 24 | +import netflix.nebula.dependency.recommender.service.BomResolverService; |
| 25 | +import netflix.nebula.dependency.recommender.util.BomResolutionUtil; |
24 | 26 | import org.apache.commons.lang3.StringUtils; |
25 | 27 | import org.codehaus.groovy.runtime.MethodClosure; |
26 | 28 | import org.gradle.api.Action; |
|
38 | 40 | import org.gradle.api.logging.Logger; |
39 | 41 | import org.gradle.api.logging.Logging; |
40 | 42 | import org.gradle.api.plugins.ExtraPropertiesExtension; |
| 43 | +import org.gradle.api.provider.Provider; |
| 44 | +import org.gradle.util.GradleVersion; |
41 | 45 |
|
42 | 46 | import java.lang.reflect.Method; |
43 | 47 | import java.util.*; |
44 | 48 |
|
45 | 49 | public class DependencyRecommendationsPlugin implements Plugin<Project> { |
46 | 50 | public static final String NEBULA_RECOMMENDER_BOM = "nebulaRecommenderBom"; |
47 | 51 | public static final boolean CORE_BOM_SUPPORT_ENABLED = Boolean.getBoolean("nebula.features.coreBomSupport"); |
| 52 | + private static final GradleVersion GRADLE_9_0 = GradleVersion.version("9.0"); |
48 | 53 | private Logger logger = Logging.getLogger(DependencyRecommendationsPlugin.class); |
49 | 54 | private RecommendationProviderContainer recommendationProviderContainer; |
50 | 55 | //TODO: remove this exclusion once https://github.com/gradle/gradle/issues/6750 is resolved |
@@ -74,18 +79,39 @@ private void applyRecommendationsDirectly(final Project project, final Configura |
74 | 79 | project.afterEvaluate(new Action<Project>() { |
75 | 80 | @Override |
76 | 81 | public void execute(Project p) { |
| 82 | + // Eagerly resolve and cache all BOMs if using build service approach |
| 83 | + if (shouldUseBuildService(p) && BomResolutionUtil.shouldEagerlyResolveBoms(p, recommendationProviderContainer)) { |
| 84 | + BomResolutionUtil.eagerlyResolveBoms(p, recommendationProviderContainer, NEBULA_RECOMMENDER_BOM); |
| 85 | + } |
| 86 | + |
77 | 87 | p.getConfigurations().all(new ExtendRecommenderConfigurationAction(bomConfiguration, p, recommendationProviderContainer)); |
78 | 88 | p.subprojects(new Action<Project>() { |
79 | 89 | @Override |
80 | 90 | public void execute(Project sub) { |
| 91 | + // Also eagerly resolve BOMs for subprojects if using build service |
| 92 | + if (shouldUseBuildService(sub) && BomResolutionUtil.shouldEagerlyResolveBoms(sub, recommendationProviderContainer)) { |
| 93 | + BomResolutionUtil.eagerlyResolveBoms(sub, recommendationProviderContainer, NEBULA_RECOMMENDER_BOM); |
| 94 | + } |
81 | 95 | sub.getConfigurations().all(new ExtendRecommenderConfigurationAction(bomConfiguration, sub, recommendationProviderContainer)); |
82 | 96 | } |
83 | 97 | }); |
84 | 98 | } |
85 | 99 | }); |
86 | 100 | } |
| 101 | + |
87 | 102 |
|
88 | 103 | private void applyRecommendations(final Project project) { |
| 104 | + // Add eager BOM resolution for regular (non-core) BOM support |
| 105 | + project.afterEvaluate(new Action<Project>() { |
| 106 | + @Override |
| 107 | + public void execute(Project p) { |
| 108 | + if (shouldUseBuildService(p) && BomResolutionUtil.shouldEagerlyResolveBoms(p, recommendationProviderContainer)) { |
| 109 | + // Eagerly resolve and cache all BOMs after project evaluation |
| 110 | + BomResolutionUtil.eagerlyResolveBoms(p, recommendationProviderContainer, NEBULA_RECOMMENDER_BOM); |
| 111 | + } |
| 112 | + } |
| 113 | + }); |
| 114 | + |
89 | 115 | project.getConfigurations().all(new Action<Configuration>() { |
90 | 116 | @Override |
91 | 117 | public void execute(final Configuration conf) { |
@@ -245,4 +271,60 @@ public Set<String> getReasonsRecursive(Project project) { |
245 | 271 | return getReasonsRecursive(project.getParent()); |
246 | 272 | return Collections.emptySet(); |
247 | 273 | } |
| 274 | + |
| 275 | + /** |
| 276 | + * Determines whether to use the BomResolverService (build service) approach. |
| 277 | + * |
| 278 | + * <p>The build service is used when:</p> |
| 279 | + * <ul> |
| 280 | + * <li>Gradle version is 9.0 or higher, OR</li> |
| 281 | + * <li>The gradle property 'nebula.dependency-recommender.useBuildService' is set to true</li> |
| 282 | + * </ul> |
| 283 | + * |
| 284 | + * @param project the Gradle project to check |
| 285 | + * @return true if build service should be used, false otherwise |
| 286 | + */ |
| 287 | + private boolean shouldUseBuildService(Project project) { |
| 288 | + // Check if explicitly enabled via gradle property |
| 289 | + if (project.hasProperty("nebula.dependency-recommender.useBuildService")) { |
| 290 | + Object property = project.property("nebula.dependency-recommender.useBuildService"); |
| 291 | + if (Boolean.parseBoolean(property.toString())) { |
| 292 | + return true; |
| 293 | + } |
| 294 | + } |
| 295 | + |
| 296 | + // Default behavior: use build service for Gradle 9+ |
| 297 | + GradleVersion currentVersion = GradleVersion.current(); |
| 298 | + return currentVersion.compareTo(GRADLE_9_0) >= 0; |
| 299 | + } |
| 300 | + |
| 301 | + /** |
| 302 | + * Eagerly resolves BOM configurations during the configuration phase to prevent |
| 303 | + * configuration resolution lock conflicts in parallel builds. |
| 304 | + * |
| 305 | + * <p>This method delegates to {@link BomResolutionUtil#eagerlyResolveBoms} and is |
| 306 | + * provided for backward compatibility and convenience for external plugins.</p> |
| 307 | + * |
| 308 | + * <p><strong>External Plugin Usage:</strong></p> |
| 309 | + * <pre>{@code |
| 310 | + * // Get the plugin instance and container |
| 311 | + * DependencyRecommendationsPlugin plugin = project.plugins.getPlugin(DependencyRecommendationsPlugin) |
| 312 | + * RecommendationProviderContainer container = project.extensions.getByType(RecommendationProviderContainer) |
| 313 | + * |
| 314 | + * // Disable automatic resolution and add BOMs |
| 315 | + * container.setEagerlyResolve(false) |
| 316 | + * container.mavenBom(module: 'com.example:custom-bom:1.0.0') |
| 317 | + * |
| 318 | + * // Manually trigger resolution |
| 319 | + * plugin.eagerlyResolveBoms(project, container) |
| 320 | + * }</pre> |
| 321 | + * |
| 322 | + * @param project the Gradle project whose BOM configurations should be resolved |
| 323 | + * @param container the recommendation provider container to check for additional BOM providers |
| 324 | + * @since 12.7.0 |
| 325 | + * @see BomResolutionUtil#eagerlyResolveBoms(Project, RecommendationProviderContainer, String) |
| 326 | + */ |
| 327 | + public void eagerlyResolveBoms(Project project, RecommendationProviderContainer container) { |
| 328 | + BomResolutionUtil.eagerlyResolveBoms(project, container, NEBULA_RECOMMENDER_BOM); |
| 329 | + } |
248 | 330 | } |
0 commit comments