Skip to content

Commit b0d4f1d

Browse files
committed
Merge branch '3.2.x' into 3.3.x
Closes gh-41257
2 parents 1a699ae + 4515c88 commit b0d4f1d

File tree

416 files changed

+730
-440
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

416 files changed

+730
-440
lines changed

buildSrc/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ gradlePlugin {
105105
id = "org.springframework.boot.deployed"
106106
implementationClass = "org.springframework.boot.build.DeployedPlugin"
107107
}
108+
dockerTestPlugin {
109+
id = "org.springframework.boot.docker-test"
110+
implementationClass = "org.springframework.boot.build.test.DockerTestPlugin"
111+
}
108112
integrationTestPlugin {
109113
id = "org.springframework.boot.integration-test"
110114
implementationClass = "org.springframework.boot.build.test.IntegrationTestPlugin"

buildSrc/src/main/java/org/springframework/boot/build/mavenplugin/MavenPluginPlugin.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787

8888
import org.springframework.boot.build.DeployedPlugin;
8989
import org.springframework.boot.build.MavenRepositoryPlugin;
90+
import org.springframework.boot.build.test.DockerTestPlugin;
9091
import org.springframework.boot.build.test.IntegrationTestPlugin;
9192
import org.springframework.core.CollectionFactory;
9293
import org.springframework.util.Assert;
@@ -138,11 +139,15 @@ private void addPopulateIntTestMavenRepositoryTask(Project project) {
138139
.set(new File(project.getBuildDir(), "runtime-classpath-repository"));
139140
project.getDependencies()
140141
.components((components) -> components.all(MavenRepositoryComponentMetadataRule.class));
141-
Sync task = project.getTasks().create("populateIntTestMavenRepository", Sync.class);
142-
task.setDestinationDir(new File(project.getBuildDir(), "int-test-maven-repository"));
142+
Sync task = project.getTasks().create("populateTestMavenRepository", Sync.class);
143+
task.setDestinationDir(new File(project.getBuildDir(), "test-maven-repository"));
143144
task.with(copyIntTestMavenRepositoryFiles(project, runtimeClasspathMavenRepository));
144145
task.dependsOn(project.getTasks().getByName(MavenRepositoryPlugin.PUBLISH_TO_PROJECT_REPOSITORY_TASK_NAME));
145146
project.getTasks().getByName(IntegrationTestPlugin.INT_TEST_TASK_NAME).dependsOn(task);
147+
project.getPlugins()
148+
.withType(DockerTestPlugin.class)
149+
.all((dockerTestPlugin) -> project.getTasks()
150+
.named(DockerTestPlugin.DOCKER_TEST_TASK_NAME, (dockerTest) -> dockerTest.dependsOn(task)));
146151
}
147152

148153
private CopySpec copyIntTestMavenRepositoryFiles(Project project,
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.build.test;
18+
19+
import org.gradle.api.Project;
20+
import org.gradle.api.provider.Provider;
21+
import org.gradle.api.services.BuildService;
22+
import org.gradle.api.services.BuildServiceParameters;
23+
24+
/**
25+
* Build service for Docker-based tests. Configured to only allow serial execution,
26+
* thereby ensuring that Docker-based tests do not run in parallel.
27+
*
28+
* @author Andy Wilkinson
29+
*/
30+
abstract class DockerTestBuildService implements BuildService<BuildServiceParameters.None> {
31+
32+
static Provider<DockerTestBuildService> registerIfNecessary(Project project) {
33+
return project.getGradle()
34+
.getSharedServices()
35+
.registerIfAbsent("dockerTest", DockerTestBuildService.class, (spec) -> spec.getMaxParallelUsages().set(1));
36+
}
37+
38+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.build.test;
18+
19+
import org.gradle.api.Plugin;
20+
import org.gradle.api.Project;
21+
import org.gradle.api.plugins.JavaPlugin;
22+
import org.gradle.api.plugins.JavaPluginExtension;
23+
import org.gradle.api.provider.Provider;
24+
import org.gradle.api.services.BuildService;
25+
import org.gradle.api.tasks.SourceSet;
26+
import org.gradle.api.tasks.SourceSetContainer;
27+
import org.gradle.api.tasks.testing.Test;
28+
import org.gradle.language.base.plugins.LifecycleBasePlugin;
29+
import org.gradle.plugins.ide.eclipse.EclipsePlugin;
30+
import org.gradle.plugins.ide.eclipse.model.EclipseModel;
31+
32+
/**
33+
* Plugin for Docker-based tests. Creates a {@link SourceSet source set}, {@link Test
34+
* test} task, and {@link BuildService shared service} named {@code dockerTest}. The build
35+
* service is configured to only allow serial usage and the {@code dockerTest} task is
36+
* configured to use the build service. In a parallel build, this ensures that only a
37+
* single {@code dockerTest} task can run at any given time.
38+
*
39+
* @author Andy Wilkinson
40+
*/
41+
public class DockerTestPlugin implements Plugin<Project> {
42+
43+
/**
44+
* Name of the {@code dockerTest} task.
45+
*/
46+
public static String DOCKER_TEST_TASK_NAME = "dockerTest";
47+
48+
/**
49+
* Name of the {@code dockerTest} source set.
50+
*/
51+
public static String DOCKER_TEST_SOURCE_SET_NAME = "dockerTest";
52+
53+
/**
54+
* Name of the {@code dockerTest} shared service.
55+
*/
56+
public static String DOCKER_TEST_SERVICE_NAME = "dockerTest";
57+
58+
@Override
59+
public void apply(Project project) {
60+
project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> configureDockerTesting(project));
61+
}
62+
63+
private void configureDockerTesting(Project project) {
64+
Provider<DockerTestBuildService> buildService = DockerTestBuildService.registerIfNecessary(project);
65+
SourceSet dockerTestSourceSet = createSourceSet(project);
66+
Provider<Test> dockerTest = createTestTask(project, dockerTestSourceSet, buildService);
67+
project.getTasks().getByName(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(dockerTest);
68+
project.getPlugins().withType(EclipsePlugin.class, (eclipsePlugin) -> {
69+
EclipseModel eclipse = project.getExtensions().getByType(EclipseModel.class);
70+
eclipse.classpath((classpath) -> classpath.getPlusConfigurations()
71+
.add(project.getConfigurations()
72+
.getByName(dockerTestSourceSet.getRuntimeClasspathConfigurationName())));
73+
});
74+
}
75+
76+
private SourceSet createSourceSet(Project project) {
77+
SourceSetContainer sourceSets = project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets();
78+
SourceSet dockerTestSourceSet = sourceSets.create(DOCKER_TEST_SOURCE_SET_NAME);
79+
SourceSet main = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
80+
SourceSet test = sourceSets.getByName(SourceSet.TEST_SOURCE_SET_NAME);
81+
dockerTestSourceSet.setCompileClasspath(dockerTestSourceSet.getCompileClasspath()
82+
.plus(main.getOutput())
83+
.plus(main.getCompileClasspath())
84+
.plus(test.getOutput()));
85+
dockerTestSourceSet.setRuntimeClasspath(dockerTestSourceSet.getRuntimeClasspath()
86+
.plus(main.getOutput())
87+
.plus(main.getRuntimeClasspath())
88+
.plus(test.getOutput()));
89+
project.getPlugins().withType(IntegrationTestPlugin.class, (integrationTestPlugin) -> {
90+
SourceSet intTest = sourceSets.getByName(IntegrationTestPlugin.INT_TEST_SOURCE_SET_NAME);
91+
dockerTestSourceSet
92+
.setCompileClasspath(dockerTestSourceSet.getCompileClasspath().plus(intTest.getOutput()));
93+
dockerTestSourceSet
94+
.setRuntimeClasspath(dockerTestSourceSet.getRuntimeClasspath().plus(intTest.getOutput()));
95+
});
96+
return dockerTestSourceSet;
97+
}
98+
99+
private Provider<Test> createTestTask(Project project, SourceSet dockerTestSourceSet,
100+
Provider<DockerTestBuildService> buildService) {
101+
Provider<Test> dockerTest = project.getTasks().register(DOCKER_TEST_TASK_NAME, Test.class, (task) -> {
102+
task.usesService(buildService);
103+
task.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP);
104+
task.setDescription("Runs Docker-based tests.");
105+
task.setTestClassesDirs(dockerTestSourceSet.getOutput().getClassesDirs());
106+
task.setClasspath(dockerTestSourceSet.getRuntimeClasspath());
107+
task.shouldRunAfter(JavaPlugin.TEST_TASK_NAME);
108+
});
109+
return dockerTest;
110+
}
111+
112+
}

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ include "spring-boot-project:spring-boot-tools:spring-boot-loader-tools"
6464
include "spring-boot-project:spring-boot-tools:spring-boot-maven-plugin"
6565
include "spring-boot-project:spring-boot-tools:spring-boot-properties-migrator"
6666
include "spring-boot-project:spring-boot-tools:spring-boot-test-support"
67+
include "spring-boot-project:spring-boot-tools:spring-boot-test-support-docker"
6768
include "spring-boot-project:spring-boot"
6869
include "spring-boot-project:spring-boot-autoconfigure"
6970
include "spring-boot-project:spring-boot-actuator"

spring-boot-project/spring-boot-actuator/build.gradle

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,25 @@ plugins {
33
id "org.springframework.boot.conventions"
44
id "org.springframework.boot.configuration-properties"
55
id "org.springframework.boot.optional-dependencies"
6+
id "org.springframework.boot.docker-test"
67
id "org.springframework.boot.deployed"
78
}
89

910
description = "Spring Boot Actuator"
1011

1112
dependencies {
1213
api(project(":spring-boot-project:spring-boot"))
14+
15+
dockerTestImplementation(project(":spring-boot-project:spring-boot-autoconfigure"))
16+
dockerTestImplementation(project(":spring-boot-project:spring-boot-test"))
17+
dockerTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support-docker"))
18+
dockerTestImplementation("org.assertj:assertj-core")
19+
dockerTestImplementation("org.junit.jupiter:junit-jupiter")
20+
dockerTestImplementation("org.springframework:spring-test")
21+
dockerTestImplementation("org.testcontainers:junit-jupiter")
22+
dockerTestImplementation("org.testcontainers:mongodb")
23+
dockerTestImplementation("org.testcontainers:neo4j")
24+
dockerTestImplementation("org.testcontainers:testcontainers")
1325

1426
optional("org.apache.cassandra:java-driver-core") {
1527
exclude group: "org.slf4j", module: "jcl-over-slf4j"
@@ -100,10 +112,6 @@ dependencies {
100112
testImplementation("org.skyscreamer:jsonassert")
101113
testImplementation("org.springframework:spring-test")
102114
testImplementation("com.squareup.okhttp3:mockwebserver")
103-
testImplementation("org.testcontainers:junit-jupiter")
104-
testImplementation("org.testcontainers:mongodb")
105-
testImplementation("org.testcontainers:neo4j")
106-
testImplementation("org.testcontainers:testcontainers")
107115

108116
testRuntimeOnly("ch.qos.logback:logback-classic")
109117
testRuntimeOnly("io.projectreactor.netty:reactor-netty-http")

spring-boot-project/spring-boot-autoconfigure/build.gradle

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ plugins {
44
id "org.springframework.boot.configuration-properties"
55
id "org.springframework.boot.conventions"
66
id "org.springframework.boot.deployed"
7+
id "org.springframework.boot.docker-test"
78
id "org.springframework.boot.optional-dependencies"
89
}
910

@@ -12,6 +13,21 @@ description = "Spring Boot AutoConfigure"
1213
dependencies {
1314
api(project(":spring-boot-project:spring-boot"))
1415

16+
dockerTestImplementation(project(":spring-boot-project:spring-boot-test"))
17+
dockerTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support-docker"))
18+
dockerTestImplementation("org.assertj:assertj-core")
19+
dockerTestImplementation("org.junit.jupiter:junit-jupiter")
20+
dockerTestImplementation("org.mockito:mockito-core")
21+
dockerTestImplementation("org.springframework:spring-test")
22+
dockerTestImplementation("org.testcontainers:cassandra")
23+
dockerTestImplementation("org.testcontainers:couchbase")
24+
dockerTestImplementation("org.testcontainers:elasticsearch")
25+
dockerTestImplementation("org.testcontainers:junit-jupiter")
26+
dockerTestImplementation("org.testcontainers:mongodb")
27+
dockerTestImplementation("org.testcontainers:neo4j")
28+
dockerTestImplementation("org.testcontainers:pulsar")
29+
dockerTestImplementation("org.testcontainers:testcontainers")
30+
1531
optional("co.elastic.clients:elasticsearch-java") {
1632
exclude group: "commons-logging", module: "commons-logging"
1733
}
@@ -239,14 +255,6 @@ dependencies {
239255
}
240256
testImplementation("org.springframework.pulsar:spring-pulsar-cache-provider-caffeine")
241257
testImplementation("org.springframework.security:spring-security-test")
242-
testImplementation("org.testcontainers:cassandra")
243-
testImplementation("org.testcontainers:couchbase")
244-
testImplementation("org.testcontainers:elasticsearch")
245-
testImplementation("org.testcontainers:junit-jupiter")
246-
testImplementation("org.testcontainers:mongodb")
247-
testImplementation("org.testcontainers:neo4j")
248-
testImplementation("org.testcontainers:pulsar")
249-
testImplementation("org.testcontainers:testcontainers")
250258
testImplementation("org.yaml:snakeyaml")
251259

252260
testRuntimeOnly("jakarta.management.j2ee:jakarta.management.j2ee-api")
Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
plugins {
2-
id "java-library"
2+
id "java-library"
33
id "org.springframework.boot.configuration-properties"
44
id "org.springframework.boot.conventions"
55
id "org.springframework.boot.deployed"
6-
id "org.springframework.boot.optional-dependencies"
6+
id "org.springframework.boot.docker-test"
7+
id "org.springframework.boot.optional-dependencies"
78
}
89

910
description = "Spring Boot Docker Compose Support"
1011

1112
dependencies {
1213
api(project(":spring-boot-project:spring-boot"))
1314

15+
dockerTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support-docker"))
16+
dockerTestImplementation("org.assertj:assertj-core")
17+
dockerTestImplementation("org.awaitility:awaitility")
18+
dockerTestImplementation("org.junit.jupiter:junit-jupiter")
19+
dockerTestImplementation("org.testcontainers:testcontainers")
20+
21+
dockerTestRuntimeOnly("com.microsoft.sqlserver:mssql-jdbc")
22+
dockerTestRuntimeOnly("com.oracle.database.r2dbc:oracle-r2dbc")
23+
dockerTestRuntimeOnly("io.r2dbc:r2dbc-mssql")
24+
1425
implementation("com.fasterxml.jackson.core:jackson-databind")
1526
implementation("com.fasterxml.jackson.module:jackson-module-parameter-names")
1627

@@ -25,14 +36,8 @@ dependencies {
2536
testImplementation(project(":spring-boot-project:spring-boot-test"))
2637
testImplementation("ch.qos.logback:logback-classic")
2738
testImplementation("org.assertj:assertj-core")
28-
testImplementation("org.awaitility:awaitility")
2939
testImplementation("org.junit.jupiter:junit-jupiter")
3040
testImplementation("org.mockito:mockito-core")
3141
testImplementation("org.springframework:spring-core-test")
3242
testImplementation("org.springframework:spring-test")
33-
testImplementation("org.testcontainers:testcontainers")
34-
35-
testRuntimeOnly("com.microsoft.sqlserver:mssql-jdbc")
36-
testRuntimeOnly("com.oracle.database.r2dbc:oracle-r2dbc")
37-
testRuntimeOnly("io.r2dbc:r2dbc-mssql")
3843
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import static org.assertj.core.api.Assertions.assertThat;
2424

2525
/**
26-
* Integration tests for {@link MariaDbJdbcDockerComposeConnectionDetailsFactory}
26+
* Integration tests for {@link MariaDbJdbcDockerComposeConnectionDetailsFactory}.
2727
*
2828
* @author Scott Frederick
2929
*/
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import static org.assertj.core.api.Assertions.assertThat;
2626

2727
/**
28-
* Integration tests for {@link MariaDbR2dbcDockerComposeConnectionDetailsFactory}
28+
* Integration tests for {@link MariaDbR2dbcDockerComposeConnectionDetailsFactory}.
2929
*
3030
* @author Scott Frederick
3131
*/
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import static org.assertj.core.api.Assertions.assertThat;
2424

2525
/**
26-
* Integration tests for {@link MariaDbJdbcDockerComposeConnectionDetailsFactory}
26+
* Integration tests for {@link MariaDbJdbcDockerComposeConnectionDetailsFactory}.
2727
*
2828
* @author Moritz Halbritter
2929
* @author Andy Wilkinson
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import static org.assertj.core.api.Assertions.assertThat;
2626

2727
/**
28-
* Integration tests for {@link MariaDbR2dbcDockerComposeConnectionDetailsFactory}
28+
* Integration tests for {@link MariaDbR2dbcDockerComposeConnectionDetailsFactory}.
2929
*
3030
* @author Moritz Halbritter
3131
* @author Andy Wilkinson
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import static org.assertj.core.api.Assertions.assertThat;
2424

2525
/**
26-
* Integration tests for {@link MySqlJdbcDockerComposeConnectionDetailsFactory}
26+
* Integration tests for {@link MySqlJdbcDockerComposeConnectionDetailsFactory}.
2727
*
2828
* @author Scott Frederick
2929
*/
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import static org.assertj.core.api.Assertions.assertThat;
2626

2727
/**
28-
* Integration tests for {@link MySqlR2dbcDockerComposeConnectionDetailsFactory}
28+
* Integration tests for {@link MySqlR2dbcDockerComposeConnectionDetailsFactory}.
2929
*
3030
* @author Scott Frederick
3131
*/
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import static org.assertj.core.api.Assertions.assertThat;
2424

2525
/**
26-
* Integration tests for {@link MySqlJdbcDockerComposeConnectionDetailsFactory}
26+
* Integration tests for {@link MySqlJdbcDockerComposeConnectionDetailsFactory}.
2727
*
2828
* @author Moritz Halbritter
2929
* @author Andy Wilkinson
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import static org.assertj.core.api.Assertions.assertThat;
2626

2727
/**
28-
* Integration tests for {@link MySqlR2dbcDockerComposeConnectionDetailsFactory}
28+
* Integration tests for {@link MySqlR2dbcDockerComposeConnectionDetailsFactory}.
2929
*
3030
* @author Moritz Halbritter
3131
* @author Andy Wilkinson

0 commit comments

Comments
 (0)