diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc index 2fc81b860d..c2409d72b7 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc @@ -17,25 +17,30 @@ Task properties can be used to configure how the builder should operate on the p The following table summarizes the available properties and their default values: |=== -| Property | Description | Default value +| Property | Command-line option | Description | Default value | `builder` +| `--builder` | Name of the Builder image to use. | `cloudfoundry/cnb:0.0.53-bionic` | `imageName` +| `--imageName` | {spring-boot-api}/buildpack/platform/docker/type/ImageReference.html#of-java.lang.String-[Image name] for the generated image. | `docker.io/library/${project.artifactId}:${project.version}` | `environment` +| | Environment variables that should be passed to the builder. | | `cleanCache` +| | Whether to clean the cache before building. | `false` | `verboseLogging` +| | Enables verbose logging of builder operations. | `false` |=== diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.java index bc96cf8156..847361977f 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.java @@ -29,6 +29,7 @@ import org.gradle.api.provider.Property; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.TaskAction; +import org.gradle.api.tasks.options.Option; import org.springframework.boot.buildpack.platform.build.BuildRequest; import org.springframework.boot.buildpack.platform.build.Builder; @@ -107,6 +108,7 @@ public class BootBuildImage extends DefaultTask { * Sets the name of the image that will be built. * @param imageName name of the image */ + @Option(option = "imageName", description = "The name of the image to generate") public void setImageName(String imageName) { this.imageName = imageName; } @@ -126,6 +128,7 @@ public class BootBuildImage extends DefaultTask { * Sets the builder that will be used to build the image. * @param builder the builder */ + @Option(option = "builder", description = "The name of the builder image to use") public void setBuilder(String builder) { this.builder = builder; } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java index bf292a00a2..3ca0cc515e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java @@ -58,9 +58,28 @@ class BootBuildImageIntegrationTests { writeMainClass(); writeLongNameResource(); BuildResult result = this.gradleBuild.build("bootBuildImage"); + String projectName = this.gradleBuild.getProjectDir().getName(); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + assertThat(result.getOutput()).contains("docker.io/library/" + projectName); assertThat(result.getOutput()).contains("cloudfoundry/cnb:0.0.53-bionic"); - ImageReference imageReference = ImageReference.of(ImageName.of(this.gradleBuild.getProjectDir().getName())); + ImageReference imageReference = ImageReference.of(ImageName.of(projectName)); + try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { + container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); + } + finally { + new DockerApi().image().remove(imageReference, false); + } + } + + @TestTemplate + void buildsImageWithCustomName() throws IOException { + writeMainClass(); + writeLongNameResource(); + BuildResult result = this.gradleBuild.build("bootBuildImage"); + assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + assertThat(result.getOutput()).contains("example.com/test-image-name"); + assertThat(result.getOutput()).contains("cloudfoundry/cnb:0.0.53-bionic"); + ImageReference imageReference = ImageReference.of(ImageName.of("example.com/test-image-name")); try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); } @@ -74,9 +93,29 @@ class BootBuildImageIntegrationTests { writeMainClass(); writeLongNameResource(); BuildResult result = this.gradleBuild.build("bootBuildImage"); + String projectName = this.gradleBuild.getProjectDir().getName(); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + assertThat(result.getOutput()).contains("docker.io/library/" + projectName); assertThat(result.getOutput()).contains("cloudfoundry/cnb:0.0.43-bionic"); - ImageReference imageReference = ImageReference.of(ImageName.of(this.gradleBuild.getProjectDir().getName())); + ImageReference imageReference = ImageReference.of(ImageName.of(projectName)); + try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { + container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); + } + finally { + new DockerApi().image().remove(imageReference, false); + } + } + + @TestTemplate + void buildsImageWithCommandLineOptions() throws IOException { + writeMainClass(); + writeLongNameResource(); + BuildResult result = this.gradleBuild.build("bootBuildImage", "--imageName=example.com/test-image-name", + "--builder=cloudfoundry/cnb:0.0.43-bionic"); + assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + assertThat(result.getOutput()).contains("example.com/test-image-name"); + assertThat(result.getOutput()).contains("cloudfoundry/cnb:0.0.43-bionic"); + ImageReference imageReference = ImageReference.of(ImageName.of("example.com/test-image-name")); try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithCustomName.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithCustomName.gradle new file mode 100644 index 0000000000..245ed3f0af --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithCustomName.gradle @@ -0,0 +1,11 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '{version}' +} + +sourceCompatibility = '1.8' +targetCompatibility = '1.8' + + bootBuildImage { + imageName = "example.com/test-image-name" + }