Skip to content

Commit

Permalink
Require dependency on s-b-dependencies to use its constraints
Browse files Browse the repository at this point in the history
Previously, Spring Boot's modules published Gradle Module Metadata
(GMM) the declared a platform dependency on spring-boot-dependencies.
This provided versions for each module's own dependencies but also had
they unwanted side-effect of pulling in spring-boot-dependencies
constraints which would influence the version of other dependencies
declared in the same configuration. This was undesirable as users
should be able to opt in to this level of dependency management, either
by using the dependency management plugin or by using Gradle's built-in
support via a platform dependency on spring-boot-dependencies.

This commit reworks how Spring Boot's build uses
spring-boot-dependencies and spring-boot-parent to provide its own
dependency management. Configurations that aren't seen by consumers are
configured to extend a dependencyManagement configuration that has an
enforced platform dependency on spring-boot-parent. This enforces
spring-boot-parent's version constraints on Spring Boot's build without
making them visible to consumers. To ensure that the versions that
Spring Boot has been built against are visible to consumers, the
Maven publication that produces pom files and GMM for the published
modules is configured to use the resolved versions from the module's
runtime classpath.

Fixes gh-21911
  • Loading branch information
wilkinsona committed Jun 16, 2020
1 parent e30b8bf commit 0de466e
Show file tree
Hide file tree
Showing 92 changed files with 122 additions and 194 deletions.
4 changes: 0 additions & 4 deletions buildSrc/build.gradle
Expand Up @@ -54,10 +54,6 @@ gradlePlugin {
id = "org.springframework.boot.conventions"
implementationClass = "org.springframework.boot.build.ConventionsPlugin"
}
dependencyManagementPlugin {
id = "org.springframework.boot.internal-dependency-management"
implementationClass = "org.springframework.boot.build.InternalDependencyManagementPlugin"
}
deployedPlugin {
id = "org.springframework.boot.deployed"
implementationClass = "org.springframework.boot.build.DeployedPlugin"
Expand Down

This file was deleted.

Expand Up @@ -17,6 +17,7 @@

import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
Expand All @@ -25,8 +26,12 @@
import io.spring.javaformat.gradle.FormatTask;
import io.spring.javaformat.gradle.SpringJavaFormatPlugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.quality.CheckstyleExtension;
import org.gradle.api.plugins.quality.CheckstylePlugin;
import org.gradle.api.tasks.bundling.Jar;
Expand All @@ -36,6 +41,7 @@
import org.gradle.testretry.TestRetryPlugin;
import org.gradle.testretry.TestRetryTaskExtension;

import org.springframework.boot.build.optional.OptionalDependenciesPlugin;
import org.springframework.boot.build.testing.TestFailuresPlugin;

/**
Expand All @@ -60,6 +66,7 @@
* <li>{@code Implementation-Title}
* <li>{@code Implementation-Version}
* </ul>
* <li>{@code spring-boot-parent} is used for dependency management</li>
* </ul>
*
* <p/>
Expand All @@ -80,6 +87,7 @@ void apply(Project project) {
configureJavadocConventions(project);
configureTestConventions(project);
configureJarManifestConventions(project);
configureDependencyManagement(project);
});
}

Expand Down Expand Up @@ -164,4 +172,22 @@ private void configureSpringJavaFormat(Project project) {
.add(project.getDependencies().create("io.spring.javaformat:spring-javaformat-checkstyle:" + version));
}

private void configureDependencyManagement(Project project) {
ConfigurationContainer configurations = project.getConfigurations();
Configuration dependencyManagement = configurations.create("dependencyManagement", (configuration) -> {
configuration.setVisible(false);
configuration.setCanBeConsumed(false);
configuration.setCanBeResolved(false);
});
configurations
.matching((configuration) -> configuration.getName().endsWith("Classpath")
|| JavaPlugin.ANNOTATION_PROCESSOR_CONFIGURATION_NAME.equals(configuration.getName()))
.all((configuration) -> configuration.extendsFrom(dependencyManagement));
Dependency springBootParent = project.getDependencies().enforcedPlatform(project.getDependencies()
.project(Collections.singletonMap("path", ":spring-boot-project:spring-boot-parent")));
dependencyManagement.getDependencies().add(springBootParent);
project.getPlugins().withType(OptionalDependenciesPlugin.class, (optionalDependencies) -> configurations
.getByName(OptionalDependenciesPlugin.OPTIONAL_CONFIGURATION_NAME).extendsFrom(dependencyManagement));
}

}
Expand Up @@ -18,6 +18,7 @@

import org.apache.maven.artifact.repository.MavenArtifactRepository;
import org.gradle.api.Project;
import org.gradle.api.attributes.Usage;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.publish.PublishingExtension;
Expand All @@ -40,8 +41,12 @@
* it.
* <li>The poms of all {@link MavenPublication Maven publications} are customized to meet
* Maven Central's requirements.
* <li>If the {@link JavaPlugin Java plugin} has also been applied, creation of Javadoc
* and source jars is enabled.
* <li>If the {@link JavaPlugin Java plugin} has also been applied:
* <ul>
* <li>Creation of Javadoc and source jars is enabled.
* <li>Publication metadata (poms and Gradle module metadata) is configured to use
* resolved versions.
* </ul>
* </ul>
*
* <p/>
Expand All @@ -62,7 +67,7 @@ void apply(Project project) {
});
}
publishing.getPublications().withType(MavenPublication.class)
.all((mavenPublication) -> customizePom(mavenPublication.getPom(), project));
.all((mavenPublication) -> customizeMavenPublication(mavenPublication, project));
project.getPlugins().withType(JavaPlugin.class).all((javaPlugin) -> {
JavaPluginExtension extension = project.getExtensions().getByType(JavaPluginExtension.class);
extension.withJavadocJar();
Expand All @@ -71,6 +76,12 @@ void apply(Project project) {
});
}

private void customizeMavenPublication(MavenPublication publication, Project project) {
customizePom(publication.getPom(), project);
project.getPlugins().withType(JavaPlugin.class)
.all((javaPlugin) -> customizeJavaMavenPublication(publication, project));
}

private void customizePom(MavenPom pom, Project project) {
pom.getUrl().set("https://spring.io/projects/spring-boot");
pom.getName().set(project.provider(project::getName));
Expand All @@ -82,6 +93,13 @@ private void customizePom(MavenPom pom, Project project) {
pom.issueManagement(this::customizeIssueManagement);
}

private void customizeJavaMavenPublication(MavenPublication publication, Project project) {
publication.versionMapping((strategy) -> strategy.usage(Usage.JAVA_API, (mappingStrategy) -> mappingStrategy
.fromResolutionOf(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME)));
publication.versionMapping((strategy) -> strategy.usage(Usage.JAVA_RUNTIME,
(mappingStrategy) -> mappingStrategy.fromResolutionResult()));
}

private void customizeOrganization(MavenPomOrganization organization) {
organization.getName().set("Pivotal Software, Inc.");
organization.getUrl().set("https://spring.io");
Expand Down
Expand Up @@ -29,7 +29,6 @@

import org.springframework.boot.build.ConventionsPlugin;
import org.springframework.boot.build.DeployedPlugin;
import org.springframework.boot.build.InternalDependencyManagementPlugin;
import org.springframework.boot.build.classpath.CheckClasspathForConflicts;
import org.springframework.boot.build.classpath.CheckClasspathForProhibitedDependencies;
import org.springframework.util.StringUtils;
Expand All @@ -47,7 +46,6 @@ public void apply(Project project) {
plugins.apply(DeployedPlugin.class);
plugins.apply(JavaLibraryPlugin.class);
plugins.apply(ConventionsPlugin.class);
plugins.apply(InternalDependencyManagementPlugin.class);
StarterMetadata starterMetadata = project.getTasks().create("starterMetadata", StarterMetadata.class);
ConfigurationContainer configurations = project.getConfigurations();
Configuration runtimeClasspath = configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME);
Expand Down
Expand Up @@ -51,6 +51,17 @@ class ConventionsPluginTests {
void setup(@TempDir File projectDir) throws IOException {
this.projectDir = projectDir;
this.buildFile = new File(this.projectDir, "build.gradle");
File settingsFile = new File(this.projectDir, "settings.gradle");
try (PrintWriter out = new PrintWriter(new FileWriter(settingsFile))) {
out.println("include ':spring-boot-project:spring-boot-parent'");
}
File springBootParent = new File(this.projectDir, "spring-boot-project/spring-boot-parent/build.gradle");
springBootParent.getParentFile().mkdirs();
try (PrintWriter out = new PrintWriter(new FileWriter(springBootParent))) {
out.println("plugins {");
out.println(" id 'java-platform'");
out.println("}");
}
}

@Test
Expand Down
Expand Up @@ -5,22 +5,21 @@ plugins {
id "org.springframework.boot.auto-configuration"
id "org.springframework.boot.conventions"
id "org.springframework.boot.deployed"
id "org.springframework.boot.internal-dependency-management"
id "org.springframework.boot.optional-dependencies"
}

description = "Spring Boot Actuator AutoConfigure"

configurations {
asciidoctorExtensions
asciidoctorExtensions {
extendsFrom dependencyManagement
}
documentation
}

dependencies {
asciidoctorExtensions(platform(project(":spring-boot-project:spring-boot-dependencies")))
asciidoctorExtensions("org.springframework.restdocs:spring-restdocs-asciidoctor")

api(platform(project(":spring-boot-project:spring-boot-dependencies")))
api(project(":spring-boot-project:spring-boot-actuator"))

api(project(":spring-boot-project:spring-boot"))
Expand All @@ -29,7 +28,6 @@ dependencies {
implementation("com.fasterxml.jackson.core:jackson-databind")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")

optional(platform(project(":spring-boot-project:spring-boot-dependencies")))
optional("ch.qos.logback:logback-classic")
optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml")
optional("com.github.ben-manes.caffeine:caffeine")
Expand Down
2 changes: 0 additions & 2 deletions spring-boot-project/spring-boot-actuator/build.gradle
Expand Up @@ -9,10 +9,8 @@ plugins {
description = "Spring Boot Actuator"

dependencies {
api(platform(project(":spring-boot-project:spring-boot-dependencies")))
api(project(":spring-boot-project:spring-boot"))

optional(platform(project(":spring-boot-project:spring-boot-dependencies")))
optional("com.fasterxml.jackson.core:jackson-databind")
optional("com.github.ben-manes.caffeine:caffeine")
optional("com.hazelcast:hazelcast")
Expand Down
4 changes: 0 additions & 4 deletions spring-boot-project/spring-boot-autoconfigure/build.gradle
Expand Up @@ -4,17 +4,14 @@ plugins {
id "org.springframework.boot.auto-configuration"
id "org.springframework.boot.conventions"
id "org.springframework.boot.deployed"
id "org.springframework.boot.internal-dependency-management"
id "org.springframework.boot.optional-dependencies"
}

description = "Spring Boot AutoConfigure"

dependencies {
api(project(":spring-boot-project:spring-boot"))
api(platform(project(":spring-boot-project:spring-boot-dependencies")))

optional(platform(project(":spring-boot-project:spring-boot-dependencies")))
optional("com.atomikos:transactions-jdbc")
optional("com.atomikos:transactions-jta")
optional("com.fasterxml.jackson.core:jackson-databind")
Expand Down Expand Up @@ -151,7 +148,6 @@ dependencies {
optional("org.thymeleaf.extras:thymeleaf-extras-springsecurity5")
optional("redis.clients:jedis")

testImplementation(platform(project(":spring-boot-project:spring-boot-parent")))
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
testImplementation(project(":spring-boot-project:spring-boot-test"))
testImplementation("ch.qos.logback:logback-classic")
Expand Down
3 changes: 0 additions & 3 deletions spring-boot-project/spring-boot-cli/build.gradle
Expand Up @@ -3,7 +3,6 @@ plugins {
id "org.springframework.boot.deployed"
id "org.springframework.boot.conventions"
id "org.springframework.boot.integration-test"
id "org.springframework.boot.internal-dependency-management"
}

description = "Spring Boot CLI"
Expand All @@ -22,7 +21,6 @@ dependencies {

dependenciesBom(project(path: ":spring-boot-project:spring-boot-dependencies", configuration: "effectiveBom"))

implementation(platform(project(":spring-boot-project:spring-boot-parent")))
implementation(project(":spring-boot-project:spring-boot-tools:spring-boot-loader-tools"))
implementation("com.vaadin.external.google:android-json")
implementation("jline:jline")
Expand Down Expand Up @@ -50,7 +48,6 @@ dependencies {
implementation("org.springframework:spring-core")
implementation("org.springframework.security:spring-security-crypto")

intTestImplementation(platform(project(":spring-boot-project:spring-boot-dependencies")))
intTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-loader-tools"))
intTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
intTestImplementation("org.assertj:assertj-core")
Expand Down
7 changes: 3 additions & 4 deletions spring-boot-project/spring-boot-devtools/build.gradle
Expand Up @@ -4,18 +4,18 @@ plugins {
id "org.springframework.boot.conventions"
id "org.springframework.boot.deployed"
id "org.springframework.boot.integration-test"
id "org.springframework.boot.internal-dependency-management"
id "org.springframework.boot.optional-dependencies"
}

description = "Spring Boot Developer Tools"

configurations {
intTestDependencies
intTestDependencies {
extendsFrom dependencyManagement
}
}

dependencies {
api(platform(project(":spring-boot-project:spring-boot-dependencies")))
api(project(":spring-boot-project:spring-boot"))
api(project(":spring-boot-project:spring-boot-autoconfigure"))

Expand All @@ -32,7 +32,6 @@ dependencies {

intTestRuntimeOnly("org.springframework:spring-web")

optional(platform(project(":spring-boot-project:spring-boot-dependencies")))
optional("javax.servlet:javax.servlet-api")
optional("org.apache.derby:derby")
optional("org.hibernate:hibernate-core")
Expand Down
5 changes: 3 additions & 2 deletions spring-boot-project/spring-boot-docs/build.gradle
Expand Up @@ -10,7 +10,9 @@ description = "Spring Boot Docs"

configurations {
actuatorApiDocumentation
asciidoctorExtensions
asciidoctorExtensions {
extendsFrom dependencyManagement
}
autoConfiguration
configurationProperties
gradlePluginDocumentation
Expand Down Expand Up @@ -40,7 +42,6 @@ plugins.withType(EclipsePlugin) {
dependencies {
actuatorApiDocumentation(project(path: ":spring-boot-project:spring-boot-actuator-autoconfigure", configuration: "documentation"))

asciidoctorExtensions(platform(project(":spring-boot-project:spring-boot-parent")))
asciidoctorExtensions("io.spring.asciidoctor:spring-asciidoctor-extensions-spring-boot")
asciidoctorExtensions(project(path: ":spring-boot-project:spring-boot-actuator-autoconfigure"))
asciidoctorExtensions(project(path: ":spring-boot-project:spring-boot-autoconfigure"))
Expand Down
1 change: 0 additions & 1 deletion spring-boot-project/spring-boot-parent/build.gradle
Expand Up @@ -2,7 +2,6 @@ plugins {
id "java-platform"
id "org.springframework.boot.conventions"
id "org.springframework.boot.deployed"
id "org.springframework.boot.internal-dependency-management"
}

description = "Spring Boot Parent"
Expand Down
Expand Up @@ -2,13 +2,11 @@ plugins {
id "java-library"
id "org.springframework.boot.conventions"
id "org.springframework.boot.deployed"
id "org.springframework.boot.internal-dependency-management"
}

description = "Spring Boot Properties Migrator"

dependencies {
api(platform(project(":spring-boot-project:spring-boot-dependencies")))
api(project(":spring-boot-project:spring-boot"))
api(project(":spring-boot-project:spring-boot-tools:spring-boot-configuration-metadata"))

Expand Down

0 comments on commit 0de466e

Please sign in to comment.