Skip to content

Commit 1f21933

Browse files
Merge branch '2.4.x'
Closes gh-24534
2 parents 4dd0e9a + dfcabe1 commit 1f21933

File tree

6 files changed

+59
-1
lines changed

6 files changed

+59
-1
lines changed

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
[[build-image]]
22
== Packaging OCI Images
3-
The plugin can create an https://github.com/opencontainers/image-spec[OCI image] from executable jars using https://buildpacks.io[Cloud Native Buildpacks] (CNB).
3+
The plugin can create an https://github.com/opencontainers/image-spec[OCI image] from an executable jar file using https://buildpacks.io[Cloud Native Buildpacks] (CNB).
44
Images can be built using the `bootBuildImage` task.
55

66
NOTE: For security reasons, images build and run as non-root users.
77
See the {buildpacks-reference}/reference/spec/platform-api/#users[CNB specification] for more details.
88

99
The task is automatically created when the `java` plugin is applied and is an instance of {boot-build-image-javadoc}[`BootBuildImage`].
1010

11+
NOTE: The `bootBuildImage` task is not supported with projects using <<packaging-executable-wars, war packaging>>.
12+
1113
NOTE: The `bootBuildImage` task can not be used with a <<packaging-executable-configuring-launch-script, fully executable Spring Boot archive>> that includes a launch script.
1214
Disable launch script configuration in the `bootJar` task when building a jar file that is intended to be used with `bootBuildImage`.
1315

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/WarPluginAction.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.gradle.api.artifacts.Configuration;
2323
import org.gradle.api.artifacts.ConfigurationContainer;
2424
import org.gradle.api.file.FileCollection;
25+
import org.gradle.api.file.RegularFile;
2526
import org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact;
2627
import org.gradle.api.plugins.BasePlugin;
2728
import org.gradle.api.plugins.WarPlugin;
@@ -30,6 +31,7 @@
3031
import org.gradle.api.tasks.SourceSetContainer;
3132
import org.gradle.api.tasks.TaskProvider;
3233

34+
import org.springframework.boot.gradle.tasks.bundling.BootBuildImage;
3335
import org.springframework.boot.gradle.tasks.bundling.BootWar;
3436

3537
/**
@@ -54,6 +56,7 @@ public Class<? extends Plugin<? extends Project>> getPluginClass() {
5456
@Override
5557
public void execute(Project project) {
5658
disableWarTask(project);
59+
disableBootBuildImageTask(project);
5760
TaskProvider<BootWar> bootWar = configureBootWarTask(project);
5861
configureArtifactPublication(bootWar);
5962
}
@@ -62,6 +65,11 @@ private void disableWarTask(Project project) {
6265
project.getTasks().named(WarPlugin.WAR_TASK_NAME).configure((war) -> war.setEnabled(false));
6366
}
6467

68+
private void disableBootBuildImageTask(Project project) {
69+
project.getTasks().named(SpringBootPlugin.BOOT_BUILD_IMAGE_TASK_NAME, BootBuildImage.class)
70+
.configure((buildImage) -> buildImage.getJar().set((RegularFile) null));
71+
}
72+
6573
private TaskProvider<BootWar> configureBootWarTask(Project project) {
6674
Configuration developmentOnly = project.getConfigurations()
6775
.getByName(SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME);

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public BootBuildImage() {
9999
* @return the jar property
100100
*/
101101
@Input
102+
@Optional
102103
public RegularFileProperty getJar() {
103104
return this.jar;
104105
}
@@ -312,6 +313,9 @@ public void docker(Closure<?> closure) {
312313

313314
@TaskAction
314315
void buildImage() throws DockerEngineException, IOException {
316+
if (!this.jar.isPresent()) {
317+
throw new GradleException("Executable jar file required for building image");
318+
}
315319
Builder builder = new Builder(this.docker.asDockerConfiguration());
316320
BuildRequest request = createRequest();
317321
builder.build(request);

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,35 @@ void failsWithPublishMissingPublishRegistry() {
181181
assertThat(result.getOutput()).contains("requires docker.publishRegistry");
182182
}
183183

184+
@TestTemplate
185+
void failsWithWarPackaging() {
186+
writeMainClass();
187+
writeLongNameResource();
188+
BuildResult result = this.gradleBuild.buildAndFail("bootBuildImage", "-PapplyWarPlugin");
189+
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.FAILED);
190+
assertThat(result.getOutput()).contains("Executable jar file required for building image");
191+
}
192+
193+
@TestTemplate
194+
void buildsImageWithWarPackagingAndJarConfiguration() throws IOException {
195+
writeMainClass();
196+
writeLongNameResource();
197+
BuildResult result = this.gradleBuild.build("bootBuildImage", "--pullPolicy=IF_NOT_PRESENT");
198+
String projectName = this.gradleBuild.getProjectDir().getName();
199+
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
200+
assertThat(result.getOutput()).contains("docker.io/library/" + projectName);
201+
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
202+
assertThat(buildLibs.listFiles())
203+
.containsExactly(new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".war"));
204+
ImageReference imageReference = ImageReference.of(ImageName.of(projectName));
205+
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
206+
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
207+
}
208+
finally {
209+
new DockerApi().image().remove(imageReference, false);
210+
}
211+
}
212+
184213
private void writeMainClass() {
185214
File examplePackage = new File(this.gradleBuild.getProjectDir(), "src/main/java/example");
186215
examplePackage.mkdirs();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
plugins {
2+
id 'war'
3+
id 'org.springframework.boot' version '{version}'
4+
}
5+
6+
bootBuildImage {
7+
jar = bootWar.archiveFile
8+
}
9+
10+
sourceCompatibility = '1.8'
11+
targetCompatibility = '1.8'

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,9 @@ plugins {
33
id 'org.springframework.boot' version '{version}'
44
}
55

6+
if (project.hasProperty('applyWarPlugin')) {
7+
apply plugin: 'war'
8+
}
9+
610
sourceCompatibility = '1.8'
711
targetCompatibility = '1.8'

0 commit comments

Comments
 (0)