From da9d8d6055dd458419e4268a7924f7abd33ee919 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Tue, 30 Mar 2021 16:44:36 -0500 Subject: [PATCH] Use test harness for image building integration tests This commit modifies the integration tests for the Maven and Gradle image building goal and task to use a custom builder as a test harness to verify that the plugins invoke the builder as expected. Fixes gh-25838 --- .../BootBuildImageIntegrationTests.java | 75 ++++------ ...s-buildsImageWithCommandLineOptions.gradle | 7 + ...dsImageWithCustomBuilderAndRunImage.gradle | 4 +- ...tionTests-buildsImageWithCustomName.gradle | 1 + ...WithWarPackagingAndJarConfiguration.gradle | 4 + ...egrationTests-failsWithBuilderError.gradle | 3 +- .../BootBuildImageIntegrationTests.gradle | 4 + .../boot/maven/BuildImageTests.java | 129 +++++------------- .../build-image-builder-error/pom.xml | 3 +- .../pom.xml | 5 + .../build-image-classifier-source/pom.xml | 5 + .../pom.xml | 5 + .../projects/build-image-classifier/pom.xml | 5 + .../projects/build-image-cmd-line/pom.xml | 29 ++++ .../main/java/org/test/SampleApplication.java | 28 ++++ .../build-image-custom-builder/pom.xml | 4 +- .../projects/build-image-custom-name/pom.xml | 1 + .../build-image-empty-env-entry/pom.xml | 1 + .../projects/build-image-final-name/pom.xml | 3 + .../build-image-with-repackage/pom.xml | 5 + .../src/intTest/projects/build-image/pom.xml | 5 + src/spring-boot-builder/README.adoc | 15 ++ src/spring-boot-builder/builder/builder.toml | 18 +++ .../buildpacks/test-info/bin/build | 30 ++++ .../buildpacks/test-info/bin/detect | 28 ++++ .../buildpacks/test-info/buildpack.toml | 13 ++ 26 files changed, 285 insertions(+), 145 deletions(-) create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithCommandLineOptions.gradle create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-cmd-line/pom.xml create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-cmd-line/src/main/java/org/test/SampleApplication.java create mode 100644 src/spring-boot-builder/README.adoc create mode 100644 src/spring-boot-builder/builder/builder.toml create mode 100755 src/spring-boot-builder/buildpacks/test-info/bin/build create mode 100755 src/spring-boot-builder/buildpacks/test-info/bin/detect create mode 100644 src/spring-boot-builder/buildpacks/test-info/buildpack.toml 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 f958154fd38..1bf4b4fca4d 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,8 +29,6 @@ import org.gradle.testkit.runner.BuildResult; import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.wait.strategy.Wait; import org.springframework.boot.buildpack.platform.docker.DockerApi; import org.springframework.boot.buildpack.platform.docker.type.ImageName; @@ -61,14 +59,10 @@ class BootBuildImageIntegrationTests { 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("paketo-buildpacks/builder"); - 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); - } + assertThat(result.getOutput()).contains("---> Test Info buildpack building"); + assertThat(result.getOutput()).contains("env: BP_JVM_VERSION=8.*"); + assertThat(result.getOutput()).contains("---> Test Info buildpack done"); + removeImage(projectName); } @TestTemplate @@ -78,14 +72,10 @@ class BootBuildImageIntegrationTests { BuildResult result = this.gradleBuild.build("bootBuildImage"); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); assertThat(result.getOutput()).contains("example/test-image-name"); - assertThat(result.getOutput()).contains("paketo-buildpacks/builder"); - ImageReference imageReference = ImageReference.of(ImageName.of("example/test-image-name")); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - new DockerApi().image().remove(imageReference, false); - } + assertThat(result.getOutput()).contains("---> Test Info buildpack building"); + assertThat(result.getOutput()).contains("env: BP_JVM_VERSION=8.*"); + assertThat(result.getOutput()).contains("---> Test Info buildpack done"); + removeImage("example/test-image-name"); } @TestTemplate @@ -95,15 +85,11 @@ class BootBuildImageIntegrationTests { BuildResult result = this.gradleBuild.build("bootBuildImage"); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); assertThat(result.getOutput()).contains("example/test-image-custom"); - assertThat(result.getOutput()).contains("paketobuildpacks/builder:full"); - assertThat(result.getOutput()).contains("paketobuildpacks/run:full-cnb"); - ImageReference imageReference = ImageReference.of(ImageName.of("example/test-image-custom")); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - new DockerApi().image().remove(imageReference, false); - } + assertThat(result.getOutput()).contains("springci/spring-boot-cnb-builder:0.0.1"); + assertThat(result.getOutput()).contains("paketobuildpacks/run:tiny-cnb"); + assertThat(result.getOutput()).contains("---> Test Info buildpack building"); + assertThat(result.getOutput()).contains("---> Test Info buildpack done"); + removeImage("example/test-image-custom"); } @TestTemplate @@ -111,18 +97,14 @@ class BootBuildImageIntegrationTests { writeMainClass(); writeLongNameResource(); BuildResult result = this.gradleBuild.build("bootBuildImage", "--imageName=example/test-image-cmd", - "--builder=paketobuildpacks/builder:full", "--runImage=paketobuildpacks/run:full-cnb"); + "--builder=springci/spring-boot-cnb-builder:0.0.1", "--runImage=paketobuildpacks/run:tiny-cnb"); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); assertThat(result.getOutput()).contains("example/test-image-cmd"); - assertThat(result.getOutput()).contains("paketobuildpacks/builder:full"); - assertThat(result.getOutput()).contains("paketobuildpacks/run:full-cnb"); - ImageReference imageReference = ImageReference.of(ImageName.of("example/test-image-cmd")); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - new DockerApi().image().remove(imageReference, false); - } + assertThat(result.getOutput()).contains("springci/spring-boot-cnb-builder:0.0.1"); + assertThat(result.getOutput()).contains("paketobuildpacks/run:tiny-cnb"); + assertThat(result.getOutput()).contains("---> Test Info buildpack building"); + assertThat(result.getOutput()).contains("---> Test Info buildpack done"); + removeImage("example/test-image-cmd"); } @TestTemplate @@ -140,6 +122,7 @@ class BootBuildImageIntegrationTests { writeLongNameResource(); BuildResult result = this.gradleBuild.buildAndFail("bootBuildImage"); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.FAILED); + assertThat(result.getOutput()).contains("Forced builder failure"); assertThat(result.getOutput()).containsPattern("Builder lifecycle '.*' failed with status code"); } @@ -170,17 +153,12 @@ class BootBuildImageIntegrationTests { 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("paketo-buildpacks/builder"); + assertThat(result.getOutput()).contains("---> Test Info buildpack building"); + assertThat(result.getOutput()).contains("---> Test Info buildpack done"); File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs"); assertThat(buildLibs.listFiles()) .containsExactly(new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".war")); - 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); - } + removeImage(projectName); } private void writeMainClass() { @@ -222,4 +200,9 @@ class BootBuildImageIntegrationTests { } } + private void removeImage(String name) throws IOException { + ImageReference imageReference = ImageReference.of(ImageName.of(name)); + new DockerApi().image().remove(imageReference, false); + } + } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithCommandLineOptions.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithCommandLineOptions.gradle new file mode 100644 index 00000000000..8971742147d --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithCommandLineOptions.gradle @@ -0,0 +1,7 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '{version}' +} + +sourceCompatibility = '1.8' +targetCompatibility = '1.8' diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithCustomBuilderAndRunImage.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithCustomBuilderAndRunImage.gradle index 9878fe16dbf..621742d3bab 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithCustomBuilderAndRunImage.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithCustomBuilderAndRunImage.gradle @@ -8,6 +8,6 @@ targetCompatibility = '1.8' bootBuildImage { imageName = "example/test-image-custom" - builder = "paketobuildpacks/builder:full" - runImage = "paketobuildpacks/run:full-cnb" + builder = "springci/spring-boot-cnb-builder:0.0.1" + runImage = "paketobuildpacks/run:tiny-cnb" } 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 index e306457624c..c78bd4f43c2 100644 --- 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 @@ -8,4 +8,5 @@ targetCompatibility = '1.8' bootBuildImage { imageName = "example/test-image-name" + builder = "springci/spring-boot-cnb-builder:0.0.1" } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithWarPackagingAndJarConfiguration.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithWarPackagingAndJarConfiguration.gradle index 5aa8c27efe1..5165f759d00 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithWarPackagingAndJarConfiguration.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithWarPackagingAndJarConfiguration.gradle @@ -9,3 +9,7 @@ bootBuildImage { sourceCompatibility = '1.8' targetCompatibility = '1.8' + +bootBuildImage { + builder = "springci/spring-boot-cnb-builder:0.0.1" +} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-failsWithBuilderError.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-failsWithBuilderError.gradle index fb706c51ca6..2873acc6344 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-failsWithBuilderError.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-failsWithBuilderError.gradle @@ -7,5 +7,6 @@ sourceCompatibility = '1.8' targetCompatibility = '1.8' bootBuildImage { - environment = ["BP_JVM_VERSION": "13.9.9"] + builder = "springci/spring-boot-cnb-builder:0.0.1" + environment = ["FORCE_FAILURE": "true"] } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.gradle index 5e0df9a58c9..f34b7e643a3 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.gradle @@ -9,3 +9,7 @@ if (project.hasProperty('applyWarPlugin')) { sourceCompatibility = '1.8' targetCompatibility = '1.8' + +bootBuildImage { + builder = "springci/spring-boot-cnb-builder:0.0.1" +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java index 5f6abcd0aaf..1129d2835cd 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java @@ -25,8 +25,6 @@ import java.util.Random; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.wait.strategy.Wait; import org.springframework.boot.buildpack.platform.docker.DockerApi; import org.springframework.boot.buildpack.platform.docker.type.ImageName; @@ -52,16 +50,11 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { assertThat(jar).isFile(); File original = new File(project, "target/build-image-0.0.1.BUILD-SNAPSHOT.jar.original"); assertThat(original).doesNotExist(); - assertThat(buildLog(project)).contains("Building image").contains("paketo-buildpacks/builder") + assertThat(buildLog(project)).contains("Building image") .contains("docker.io/library/build-image:0.0.1.BUILD-SNAPSHOT") - .contains("Successfully built image"); - ImageReference imageReference = ImageReference.of(ImageName.of("build-image"), "0.0.1.BUILD-SNAPSHOT"); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - removeImage(imageReference); - } + .contains("---> Test Info buildpack building").contains("env: BP_JVM_VERSION=8.*") + .contains("---> Test Info buildpack done").contains("Successfully built image"); + removeImage("build-image", "0.0.1.BUILD-SNAPSHOT"); }); } @@ -75,15 +68,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { assertThat(classifier).doesNotExist(); assertThat(buildLog(project)).contains("Building image") .contains("docker.io/library/build-image-classifier:0.0.1.BUILD-SNAPSHOT") - .contains("Successfully built image"); - ImageReference imageReference = ImageReference.of(ImageName.of("build-image-classifier"), - "0.0.1.BUILD-SNAPSHOT"); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - removeImage(imageReference); - } + .contains("---> Test Info buildpack building").contains("env: BP_JVM_VERSION=8.*") + .contains("---> Test Info buildpack done").contains("Successfully built image"); + removeImage("build-image-classifier", "0.0.1.BUILD-SNAPSHOT"); }); } @@ -99,15 +86,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { assertThat(original).doesNotExist(); assertThat(buildLog(project)).contains("Building image") .contains("docker.io/library/build-image-classifier-source:0.0.1.BUILD-SNAPSHOT") + .contains("---> Test Info buildpack building").contains("---> Test Info buildpack done") .contains("Successfully built image"); - ImageReference imageReference = ImageReference.of(ImageName.of("build-image-classifier-source"), - "0.0.1.BUILD-SNAPSHOT"); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - removeImage(imageReference); - } + removeImage("build-image-classifier-source", "0.0.1.BUILD-SNAPSHOT"); }); } @@ -120,17 +101,11 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { File original = new File(project, "target/build-image-with-repackage-0.0.1.BUILD-SNAPSHOT.jar.original"); assertThat(original).isFile(); - assertThat(buildLog(project)).contains("Building image").contains("paketo-buildpacks/builder") + assertThat(buildLog(project)).contains("Building image") .contains("docker.io/library/build-image-with-repackage:0.0.1.BUILD-SNAPSHOT") + .contains("---> Test Info buildpack building").contains("---> Test Info buildpack done") .contains("Successfully built image"); - ImageReference imageReference = ImageReference.of(ImageName.of("build-image-with-repackage"), - "0.0.1.BUILD-SNAPSHOT"); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - removeImage(imageReference); - } + removeImage("build-image-with-repackage", "0.0.1.BUILD-SNAPSHOT"); }); } @@ -146,15 +121,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { assertThat(original).isFile(); assertThat(buildLog(project)).contains("Building image") .contains("docker.io/library/build-image-classifier-with-repackage:0.0.1.BUILD-SNAPSHOT") + .contains("---> Test Info buildpack building").contains("---> Test Info buildpack done") .contains("Successfully built image"); - ImageReference imageReference = ImageReference - .of(ImageName.of("build-image-classifier-with-repackage"), "0.0.1.BUILD-SNAPSHOT"); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - removeImage(imageReference); - } + removeImage("build-image-classifier-with-repackage", "0.0.1.BUILD-SNAPSHOT"); }); } @@ -170,15 +139,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { assertThat(original).isFile(); assertThat(buildLog(project)).contains("Building image").contains( "docker.io/library/build-image-classifier-source-with-repackage:0.0.1.BUILD-SNAPSHOT") + .contains("---> Test Info buildpack building").contains("---> Test Info buildpack done") .contains("Successfully built image"); - ImageReference imageReference = ImageReference - .of(ImageName.of("build-image-classifier-source-with-repackage"), "0.0.1.BUILD-SNAPSHOT"); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - removeImage(imageReference); - } + removeImage("build-image-classifier-source-with-repackage", "0.0.1.BUILD-SNAPSHOT"); }); } @@ -194,53 +157,37 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { assertThat(original).doesNotExist(); assertThat(buildLog(project)).contains("Building image") .contains("example.com/test/build-image:0.0.1.BUILD-SNAPSHOT") + .contains("---> Test Info buildpack building").contains("---> Test Info buildpack done") .contains("Successfully built image"); - ImageReference imageReference = ImageReference - .of("example.com/test/build-image:0.0.1.BUILD-SNAPSHOT"); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - removeImage(imageReference); - } + removeImage("example.com/test/build-image", "0.0.1.BUILD-SNAPSHOT"); }); } @TestTemplate void whenBuildImageIsInvokedWithCommandLineParameters(MavenBuild mavenBuild) { - mavenBuild.project("build-image").goals("package") + mavenBuild.project("build-image-cmd-line").goals("package") .systemProperty("spring-boot.build-image.imageName", "example.com/test/cmd-property-name:v1") - .systemProperty("spring-boot.build-image.builder", "paketobuildpacks/builder:full") - .systemProperty("spring-boot.build-image.runImage", "paketobuildpacks/run:full-cnb") + .systemProperty("spring-boot.build-image.builder", "springci/spring-boot-cnb-builder:0.0.1") + .systemProperty("spring-boot.build-image.runImage", "paketobuildpacks/run:tiny-cnb") .execute((project) -> { assertThat(buildLog(project)).contains("Building image") - .contains("example.com/test/cmd-property-name:v1").contains("paketobuildpacks/builder:full") - .contains("paketobuildpacks/run:full-cnb").contains("Successfully built image"); - ImageReference imageReference = ImageReference.of("example.com/test/cmd-property-name:v1"); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - removeImage(imageReference); - } + .contains("example.com/test/cmd-property-name:v1") + .contains("springci/spring-boot-cnb-builder:0.0.1") + .contains("paketobuildpacks/run:tiny-cnb").contains("---> Test Info buildpack building") + .contains("---> Test Info buildpack done").contains("Successfully built image"); + removeImage("example.com/test/cmd-property-name", "v1"); }); } @TestTemplate void whenBuildImageIsInvokedWithCustomBuilderImageAndRunImage(MavenBuild mavenBuild) { mavenBuild.project("build-image-custom-builder").goals("package").execute((project) -> { - assertThat(buildLog(project)).contains("Building image").contains("paketobuildpacks/builder:full") - .contains("paketobuildpacks/run:full-cnb") + assertThat(buildLog(project)).contains("Building image") .contains("docker.io/library/build-image-v2-builder:0.0.1.BUILD-SNAPSHOT") + .contains("springci/spring-boot-cnb-builder:0.0.1").contains("paketobuildpacks/run:tiny-cnb") + .contains("---> Test Info buildpack building").contains("---> Test Info buildpack done") .contains("Successfully built image"); - ImageReference imageReference = ImageReference - .of("docker.io/library/build-image-v2-builder:0.0.1.BUILD-SNAPSHOT"); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - removeImage(imageReference); - } + removeImage("docker.io/library/build-image-v2-builder", "0.0.1.BUILD-SNAPSHOT"); }); } @@ -248,17 +195,11 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { void whenBuildImageIsInvokedWithEmptyEnvEntry(MavenBuild mavenBuild) { mavenBuild.project("build-image-empty-env-entry").goals("package").prepare(this::writeLongNameResource) .execute((project) -> { - assertThat(buildLog(project)).contains("Building image").contains("paketo-buildpacks/builder") + assertThat(buildLog(project)).contains("Building image") .contains("docker.io/library/build-image-empty-env-entry:0.0.1.BUILD-SNAPSHOT") + .contains("---> Test Info buildpack building").contains("---> Test Info buildpack done") .contains("Successfully built image"); - ImageReference imageReference = ImageReference.of(ImageName.of("build-image-empty-env-entry"), - "0.0.1.BUILD-SNAPSHOT"); - try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { - container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); - } - finally { - removeImage(imageReference); - } + removeImage("build-image-empty-env-entry", "0.0.1.BUILD-SNAPSHOT"); }); } @@ -266,6 +207,7 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { void failsWhenBuilderFails(MavenBuild mavenBuild) { mavenBuild.project("build-image-builder-error").goals("package") .executeAndFail((project) -> assertThat(buildLog(project)).contains("Building image") + .contains("---> Test Info buildpack building").contains("Forced builder failure") .containsPattern("Builder lifecycle '.*' failed with status code")); } @@ -295,7 +237,8 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { } } - private void removeImage(ImageReference imageReference) { + private void removeImage(String name, String version) { + ImageReference imageReference = ImageReference.of(ImageName.of(name), version); try { new DockerApi().image().remove(imageReference, false); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-builder-error/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-builder-error/pom.xml index 5b7491e88e0..4866c1cd2e9 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-builder-error/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-builder-error/pom.xml @@ -23,8 +23,9 @@ + springci/spring-boot-cnb-builder:0.0.1 - 13.9.9 + true diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-source-with-repackage/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-source-with-repackage/pom.xml index 7734c543d65..15fd86bd7c3 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-source-with-repackage/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-source-with-repackage/pom.xml @@ -43,6 +43,11 @@ build-image + + + springci/spring-boot-cnb-builder:0.0.1 + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-source/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-source/pom.xml index 30b605a5bca..e5d62a6c481 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-source/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-source/pom.xml @@ -37,6 +37,11 @@ build-image + + + springci/spring-boot-cnb-builder:0.0.1 + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-with-repackage/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-with-repackage/pom.xml index d2f34ba4c62..997a7b24c36 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-with-repackage/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier-with-repackage/pom.xml @@ -27,6 +27,11 @@ build-image + + + springci/spring-boot-cnb-builder:0.0.1 + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier/pom.xml index ba64b1df5ff..118ce18b480 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-classifier/pom.xml @@ -21,6 +21,11 @@ build-image + + + springci/spring-boot-cnb-builder:0.0.1 + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-cmd-line/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-cmd-line/pom.xml new file mode 100644 index 00000000000..0451a8426e8 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-cmd-line/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + org.springframework.boot.maven.it + build-image + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + @java.version@ + @java.version@ + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + build-image + + + + + + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-cmd-line/src/main/java/org/test/SampleApplication.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-cmd-line/src/main/java/org/test/SampleApplication.java new file mode 100644 index 00000000000..5053809ef1f --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-cmd-line/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.test; + +public class SampleApplication { + + public static void main(String[] args) throws Exception { + System.out.println("Launched"); + synchronized(args) { + args.wait(); // Prevent exit" + } + } + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-custom-builder/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-custom-builder/pom.xml index 457cb7c9337..db0c55aa6af 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-custom-builder/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-custom-builder/pom.xml @@ -23,8 +23,8 @@ - paketobuildpacks/builder:full - paketobuildpacks/run:full-cnb + springci/spring-boot-cnb-builder:0.0.1 + paketobuildpacks/run:tiny-cnb diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-custom-name/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-custom-name/pom.xml index 57ec39dd848..0ad3c6f5676 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-custom-name/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-custom-name/pom.xml @@ -23,6 +23,7 @@ + springci/spring-boot-cnb-builder:0.0.1 example.com/test/build-image:${project.version} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-empty-env-entry/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-empty-env-entry/pom.xml index e453fd95d6a..e0b7f897f6e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-empty-env-entry/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-empty-env-entry/pom.xml @@ -23,6 +23,7 @@ + springci/spring-boot-cnb-builder:0.0.1 diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-final-name/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-final-name/pom.xml index 599371978a8..11b81efa0a8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-final-name/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-final-name/pom.xml @@ -24,6 +24,9 @@ final-name + + springci/spring-boot-cnb-builder:0.0.1 + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-with-repackage/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-with-repackage/pom.xml index c9a9bd03227..d9cd19b233d 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-with-repackage/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-with-repackage/pom.xml @@ -27,6 +27,11 @@ build-image + + + springci/spring-boot-cnb-builder:0.0.1 + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image/pom.xml index 0451a8426e8..ab9c918a020 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image/pom.xml @@ -21,6 +21,11 @@ build-image + + + springci/spring-boot-cnb-builder:0.0.1 + + diff --git a/src/spring-boot-builder/README.adoc b/src/spring-boot-builder/README.adoc new file mode 100644 index 00000000000..dfaf0efb070 --- /dev/null +++ b/src/spring-boot-builder/README.adoc @@ -0,0 +1,15 @@ += Spring Boot Test Builder + +This directory contains a Cloud Native Buildpacks https://buildpacks.io/docs/concepts/components/builder/[builder] and https://buildpacks.io/docs/concepts/components/buildpack/[buildpack] that is used by integration tests to verify the behavior of the Spring Boot build plugins. + +== Creating the builder + +* Install the https://buildpacks.io/docs/install-pack/[pack CLI] +* Authenticate to Docker Hub via `docker login` using the `springci` repository credentials +* Use `pack` to create the builder image and publish it to Docker Hub: + +[source,bash] +---- +$ cd builder +$ pack builder create springci/spring-boot-cnb-builder:0.0.1 --config builder.toml --publish +---- diff --git a/src/spring-boot-builder/builder/builder.toml b/src/spring-boot-builder/builder/builder.toml new file mode 100644 index 00000000000..5ee00bb862f --- /dev/null +++ b/src/spring-boot-builder/builder/builder.toml @@ -0,0 +1,18 @@ +# Buildpacks to include in builder +[[buildpacks]] +id = "spring-boot/test-info" +version = "0.0.1" +uri = "../buildpacks/test-info" + +# Order used for detection +[[order]] +[[order.group]] +id = "spring-boot/test-info" +version = "0.0.1" + +# Stack that will be used by the builder +[stack] +id = "io.paketo.stacks.tiny" +build-image = "index.docker.io/paketobuildpacks/build:1.2.2-tiny-cnb" +run-image = "index.docker.io/paketobuildpacks/run:tiny-cnb" +run-image-mirrors = ["gcr.io/paketo-buildpacks/run:tiny-cnb"] diff --git a/src/spring-boot-builder/buildpacks/test-info/bin/build b/src/spring-boot-builder/buildpacks/test-info/bin/build new file mode 100755 index 00000000000..7698b0f6ba9 --- /dev/null +++ b/src/spring-boot-builder/buildpacks/test-info/bin/build @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +set -eo pipefail + +echo "---> Test Info buildpack building" + +# INPUT ARGUMENTS +platform_dir=$2 +env_dir=${platform_dir}/env +bindings_dir=${platform_dir}/bindings + +if [[ -f ${env_dir}/FORCE_FAILURE ]]; then + echo "Forced builder failure" + exit 1 +fi + +if compgen -G "${env_dir}/*" > /dev/null; then + for var in ${env_dir}/*; do + echo "env: $(basename ${var})=$(<${var})" + done +fi + +if compgen -G "${bindings_dir}/*" > /dev/null; then + for binding in ${bindings_dir}/*; do + for f in ${binding}/*; do + echo "binding: $(basename ${binding})/$(basename ${f})=$(<${f})" + done + done +fi + +echo "---> Test Info buildpack done" diff --git a/src/spring-boot-builder/buildpacks/test-info/bin/detect b/src/spring-boot-builder/buildpacks/test-info/bin/detect new file mode 100755 index 00000000000..f7e1c76ebcc --- /dev/null +++ b/src/spring-boot-builder/buildpacks/test-info/bin/detect @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +set -eo pipefail + +# 1. CHECK IF APPLICABLE +if [[ ! -f META-INF/MANIFEST.MF ]]; then + exit 100 +fi + +# 2. GET ARGS +plan_path=$2 + +# 3. DECLARE DEPENDENCIES (OPTIONAL) +cat >> "${plan_path}" <