Skip to content

Commit

Permalink
Apply exclusions earlier to avoid deprecation warning
Browse files Browse the repository at this point in the history
Previously, the dependency management plugin used a before resolve
action to apply Maven-style exclusions. Gradle performs configuration
resolution in two passes and, despite its name, a before resolve
action is called after the first pass. With Gradle 8.8 and later,
using a before resolve action to configure the exclusions can result
in a deprecation warning. The deprecation warning states that support
for mutating the dependency attributes of a configuration after it
has been resolved has been deprecated.

This commit addresses the deprecation warning by configuring the
exclusions earlier, in the withDependencies callback. The callback is
called before the first pass of the resolution process, thereby
avoiding the warning. Configuring the exclusions at this step
prevents the exclusions from being configured on a per-dependency
basis so they are now configured on the configuration. Without any
additional changes, this regresses the fix for gh-21 as the
exclusions are now inherited and cause an exclusion in one
configuration where it should apply to leak into another
configuration where it should not. To overcome this regression,
exclusions are only applied to configurations that can be resolved.
Typically, these are configurations like compileClasspath,
testRuntimeClasspath and so on, that are leaves and are not extended
by other configurations, thereby minimizing the risk of any
inheritance-related problems.

Closes gh-384
  • Loading branch information
wilkinsona committed Jul 2, 2024
1 parent 68f86ea commit caad92a
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2022 the original author or authors.
* Copyright 2014-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,7 +20,7 @@
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ResolvableDependencies;
import org.gradle.api.artifacts.DependencySet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -75,11 +75,11 @@ public void execute(Configuration configuration) {
.getManagedVersionsForConfiguration(configuration));
VersionConfiguringAction versionConfiguringAction = new VersionConfiguringAction(this.project,
this.dependencyManagementContainer, configuration);
configuration.getIncoming().beforeResolve(configureMavenExclusions(configuration, versionConfiguringAction));
configuration.withDependencies(configureMavenExclusions(configuration, versionConfiguringAction));
versionConfiguringAction.applyTo(configuration);
}

private Action<ResolvableDependencies> configureMavenExclusions(Configuration configuration,
private Action<DependencySet> configureMavenExclusions(Configuration configuration,
VersionConfiguringAction versionConfiguringAction) {
return new ExclusionConfiguringAction(this.dependencyManagementSettings, this.dependencyManagementContainer,
this.configurationContainer, configuration, this.exclusionResolver, versionConfiguringAction::applyTo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.DependencyConstraintSet;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ResolvableDependencies;
import org.gradle.api.artifacts.component.ComponentSelector;
Expand All @@ -48,7 +47,7 @@
*
* @author Andy Wilkinson
*/
class ExclusionConfiguringAction implements Action<ResolvableDependencies> {
class ExclusionConfiguringAction implements Action<DependencySet> {

private static final Logger logger = LoggerFactory.getLogger(ExclusionConfiguringAction.class);

Expand Down Expand Up @@ -77,21 +76,18 @@ class ExclusionConfiguringAction implements Action<ResolvableDependencies> {
}

@Override
public void execute(ResolvableDependencies resolvableDependencies) {
if (this.configuration.isTransitive() && this.dependencyManagementSettings.isApplyMavenExclusions()) {
applyMavenExclusions(resolvableDependencies);
public void execute(DependencySet dependencySet) {
if (this.configuration.isCanBeResolved() && this.configuration.isTransitive()
&& this.dependencyManagementSettings.isApplyMavenExclusions()) {
applyMavenExclusions(dependencySet);
}
}

private void applyMavenExclusions(ResolvableDependencies resolvableDependencies) {
private void applyMavenExclusions(DependencySet dependencySet) {
Set<DependencyCandidate> excludedDependencies = findExcludedDependencies();
logger.info("Excluding {}", excludedDependencies);
for (org.gradle.api.artifacts.Dependency dependency : resolvableDependencies.getDependencies()) {
if (dependency instanceof ModuleDependency) {
for (DependencyCandidate excludedDependency : excludedDependencies) {
((ModuleDependency) dependency).exclude(excludedDependency.asMap());
}
}
for (DependencyCandidate excludedDependency : excludedDependencies) {
this.configuration.exclude(excludedDependency.asMap());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2023 the original author or authors.
* Copyright 2014-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,8 @@

package io.spring.gradle.dependencymanagement;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand All @@ -38,7 +40,7 @@ class GradleVersionCompatibilityIntegrationTests {
@RegisterExtension
private final GradleBuild gradleBuild = new GradleBuild();

@ParameterizedTest(name = "Gradle {0}")
@ParameterizedTest(name = "{displayName} (Gradle {0})")
@MethodSource("gradleVersions")
void pluginIsCompatible(String gradleVersion) {
BuildResult result = this.gradleBuild.runner()
Expand All @@ -48,9 +50,21 @@ void pluginIsCompatible(String gradleVersion) {
assertThat(result.task(":resolve").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
}

@ParameterizedTest(name = "{displayName} (Gradle {0})")
@MethodSource("gradleVersions")
void buildDoesNotProduceDeprecationWarnings(String gradleVersion) throws IOException {
File projectDir = this.gradleBuild.runner().getProjectDir();
File javaSource = new File(projectDir, "src/main/java/com/example/Main.java");
javaSource.getParentFile().mkdirs();
javaSource.createNewFile();
BuildResult result = this.gradleBuild.runner().withGradleVersion(gradleVersion).withArguments("build").build();
assertThat(result.getOutput()).doesNotContainIgnoringCase("deprecated");
assertThat(result.task(":build").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
}

static List<String[]> gradleVersions() {
List<String> versions = Arrays.asList("6.8.3", "6.9.4", "7.0.2", "7.1.1", "7.2", "7.3.3", "7.4.2", "7.5.1",
"8.0.2", "8.1.1", "8.2.1", "8.3", "8.4", "8.5", "8.6", "8.7");
"8.0.2", "8.1.1", "8.2.1", "8.3", "8.4", "8.5", "8.6", "8.7", "8.8");
List<String[]> result = new ArrayList<>();
for (String version : versions) {
result.add(new String[] { version });
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
plugins {
id "java"
id "io.spring.dependency-management"
}

repositories {
mavenCentral()
}

dependencyManagement {
imports {
mavenBom 'org.springframework.boot:spring-boot-dependencies:2.7.15'
}
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.keycloak:keycloak-admin-client:25.0.1")
}

0 comments on commit caad92a

Please sign in to comment.