Skip to content

Commit 4515c88

Browse files
committed
Merge branch 'gh-41228' into 3.2.x
Closes gh-41228
2 parents 9629363 + 654016a commit 4515c88

File tree

386 files changed

+719
-399
lines changed

Some content is hidden

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

386 files changed

+719
-399
lines changed

buildSrc/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ gradlePlugin {
9393
id = "org.springframework.boot.deployed"
9494
implementationClass = "org.springframework.boot.build.DeployedPlugin"
9595
}
96+
dockerTestPlugin {
97+
id = "org.springframework.boot.docker-test"
98+
implementationClass = "org.springframework.boot.build.test.DockerTestPlugin"
99+
}
96100
integrationTestPlugin {
97101
id = "org.springframework.boot.integration-test"
98102
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("com.datastax.oss:java-driver-core") {
1527
exclude group: "org.slf4j", module: "jcl-over-slf4j"
@@ -98,10 +110,6 @@ dependencies {
98110
testImplementation("org.skyscreamer:jsonassert")
99111
testImplementation("org.springframework:spring-test")
100112
testImplementation("com.squareup.okhttp3:mockwebserver")
101-
testImplementation("org.testcontainers:junit-jupiter")
102-
testImplementation("org.testcontainers:mongodb")
103-
testImplementation("org.testcontainers:neo4j")
104-
testImplementation("org.testcontainers:testcontainers")
105113

106114
testRuntimeOnly("ch.qos.logback:logback-classic")
107115
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
@@ -5,6 +5,7 @@ plugins {
55
id "org.springframework.boot.configuration-properties"
66
id "org.springframework.boot.conventions"
77
id "org.springframework.boot.deployed"
8+
id "org.springframework.boot.docker-test"
89
id "org.springframework.boot.optional-dependencies"
910
}
1011

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

17+
dockerTestImplementation(project(":spring-boot-project:spring-boot-test"))
18+
dockerTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support-docker"))
19+
dockerTestImplementation("org.assertj:assertj-core")
20+
dockerTestImplementation("org.junit.jupiter:junit-jupiter")
21+
dockerTestImplementation("org.mockito:mockito-core")
22+
dockerTestImplementation("org.springframework:spring-test")
23+
dockerTestImplementation("org.testcontainers:cassandra")
24+
dockerTestImplementation("org.testcontainers:couchbase")
25+
dockerTestImplementation("org.testcontainers:elasticsearch")
26+
dockerTestImplementation("org.testcontainers:junit-jupiter")
27+
dockerTestImplementation("org.testcontainers:mongodb")
28+
dockerTestImplementation("org.testcontainers:neo4j")
29+
dockerTestImplementation("org.testcontainers:pulsar")
30+
dockerTestImplementation("org.testcontainers:testcontainers")
31+
1632
optional("co.elastic.clients:elasticsearch-java") {
1733
exclude group: "commons-logging", module: "commons-logging"
1834
}
@@ -245,14 +261,6 @@ dependencies {
245261
}
246262
testImplementation("org.springframework.pulsar:spring-pulsar-cache-provider-caffeine")
247263
testImplementation("org.springframework.security:spring-security-test")
248-
testImplementation("org.testcontainers:cassandra")
249-
testImplementation("org.testcontainers:couchbase")
250-
testImplementation("org.testcontainers:elasticsearch")
251-
testImplementation("org.testcontainers:junit-jupiter")
252-
testImplementation("org.testcontainers:mongodb")
253-
testImplementation("org.testcontainers:neo4j")
254-
testImplementation("org.testcontainers:pulsar")
255-
testImplementation("org.testcontainers:testcontainers")
256264
testImplementation("org.yaml:snakeyaml")
257265

258266
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 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 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
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import static org.assertj.core.api.Assertions.assertThat;
3535

3636
/**
37-
* Integration tests for {@link OracleFreeJdbcDockerComposeConnectionDetailsFactory}
37+
* Integration tests for {@link OracleFreeJdbcDockerComposeConnectionDetailsFactory}.
3838
*
3939
* @author Andy Wilkinson
4040
*/
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import static org.assertj.core.api.Assertions.assertThat;
3434

3535
/**
36-
* Integration tests for {@link OracleFreeR2dbcDockerComposeConnectionDetailsFactory}
36+
* Integration tests for {@link OracleFreeR2dbcDockerComposeConnectionDetailsFactory}.
3737
*
3838
* @author Andy Wilkinson
3939
*/
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import static org.assertj.core.api.Assertions.assertThat;
3535

3636
/**
37-
* Integration tests for {@link OracleXeJdbcDockerComposeConnectionDetailsFactory}
37+
* Integration tests for {@link OracleXeJdbcDockerComposeConnectionDetailsFactory}.
3838
*
3939
* @author Andy Wilkinson
4040
*/
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import static org.assertj.core.api.Assertions.assertThat;
3434

3535
/**
36-
* Integration tests for {@link OracleXeR2dbcDockerComposeConnectionDetailsFactory}
36+
* Integration tests for {@link OracleXeR2dbcDockerComposeConnectionDetailsFactory}.
3737
*
3838
* @author Andy Wilkinson
3939
*/

0 commit comments

Comments
 (0)