diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 31559c058b..6176fc8b5c 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -67,6 +67,10 @@ gradlePlugin { id = "org.springframework.boot.integration-test" implementationClass = "org.springframework.boot.build.test.IntegrationTestPlugin" } + systemTestPlugin { + id = "org.springframework.boot.system-test" + implementationClass = "org.springframework.boot.build.test.SystemTestPlugin" + } mavenPluginPlugin { id = "org.springframework.boot.maven-plugin" implementationClass = "org.springframework.boot.build.mavenplugin.MavenPluginPlugin" diff --git a/buildSrc/src/main/java/org/springframework/boot/build/test/SystemTestPlugin.java b/buildSrc/src/main/java/org/springframework/boot/build/test/SystemTestPlugin.java new file mode 100644 index 0000000000..e0352bbf02 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/boot/build/test/SystemTestPlugin.java @@ -0,0 +1,83 @@ +/* + * 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.springframework.boot.build.test; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.JavaPluginConvention; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.SourceSetContainer; +import org.gradle.api.tasks.testing.Test; +import org.gradle.language.base.plugins.LifecycleBasePlugin; +import org.gradle.plugins.ide.eclipse.EclipsePlugin; +import org.gradle.plugins.ide.eclipse.model.EclipseModel; + +/** + * A {@link Plugin} to configure system testing support in a {@link Project}. + * + * @author Andy Wilkinson + * @author Scott Frederick + */ +public class SystemTestPlugin implements Plugin { + + /** + * Name of the {@code systemTest} task. + */ + public static String SYSTEM_TEST_TASK_NAME = "systemTest"; + + /** + * Name of the {@code systemTest} source set. + */ + public static String SYSTEM_TEST_SOURCE_SET_NAME = "systemTest"; + + @Override + public void apply(Project project) { + project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> configureSystemTesting(project)); + } + + private void configureSystemTesting(Project project) { + SourceSet systemTestSourceSet = createSourceSet(project); + createTestTask(project, systemTestSourceSet); + project.getPlugins().withType(EclipsePlugin.class, (eclipsePlugin) -> { + EclipseModel eclipse = project.getExtensions().getByType(EclipseModel.class); + eclipse.classpath((classpath) -> classpath.getPlusConfigurations().add( + project.getConfigurations().getByName(systemTestSourceSet.getRuntimeClasspathConfigurationName()))); + }); + } + + private SourceSet createSourceSet(Project project) { + SourceSetContainer sourceSets = project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets(); + SourceSet systemTestSourceSet = sourceSets.create(SYSTEM_TEST_SOURCE_SET_NAME); + SourceSet mainSourceSet = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME); + systemTestSourceSet + .setCompileClasspath(systemTestSourceSet.getCompileClasspath().plus(mainSourceSet.getOutput())); + systemTestSourceSet + .setRuntimeClasspath(systemTestSourceSet.getRuntimeClasspath().plus(mainSourceSet.getOutput())); + return systemTestSourceSet; + } + + private void createTestTask(Project project, SourceSet systemTestSourceSet) { + Test systemTest = project.getTasks().create(SYSTEM_TEST_TASK_NAME, Test.class); + systemTest.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP); + systemTest.setDescription("Runs system tests."); + systemTest.setTestClassesDirs(systemTestSourceSet.getOutput().getClassesDirs()); + systemTest.setClasspath(systemTestSourceSet.getRuntimeClasspath()); + systemTest.shouldRunAfter(JavaPlugin.TEST_TASK_NAME); + } + +} diff --git a/ci/pipeline.yml b/ci/pipeline.yml index c83a76ac4e..63b1f67ff9 100644 --- a/ci/pipeline.yml +++ b/ci/pipeline.yml @@ -41,6 +41,14 @@ anchors: BRANCH: ((branch)) <<: *gradle-enterprise-task-params <<: *docker-hub-task-params + run-system-tests-task-params: &run-system-tests-task-params + privileged: true + timeout: ((task-timeout)) + file: git-repo/ci/tasks/run-system-tests.yml + params: + BRANCH: ((branch)) + <<: *gradle-enterprise-task-params + <<: *docker-hub-task-params artifactory-repo-put-params: &artifactory-repo-put-params signing_key: ((signing-key)) signing_passphrase: ((signing-passphrase)) @@ -165,6 +173,12 @@ resources: source: <<: *registry-image-resource-source repository: ((docker-hub-organization))/spring-boot-ci-jdk16 +- name: paketo-builder-base-image + type: registry-image + icon: docker + source: + repository: paketobuildpacks/builder + tag: base - name: artifactory-repo type: artifactory-resource icon: package-variant @@ -668,11 +682,86 @@ jobs: - put: homebrew-tap-repo params: repository: updated-homebrew-tap-repo +- name: run-system-tests + serial: true + public: true + plan: + - get: ci-image + - get: git-repo + - get: paketo-builder-base-image + trigger: true + - get: daily + trigger: true + - do: + - task: run-system-tests + image: ci-image + <<: *run-system-tests-task-params + on_failure: + do: + - put: slack-alert + params: + <<: *slack-fail-params + - put: slack-alert + params: + <<: *slack-success-params +- name: jdk11-run-system-tests + serial: true + public: true + plan: + - get: ci-image-jdk11 + - get: git-repo + - get: paketo-builder-base-image + trigger: true + - get: daily + trigger: true + - do: + - task: run-system-tests + image: ci-image-jdk11 + <<: *run-system-tests-task-params + on_failure: + do: + - put: slack-alert + params: + <<: *slack-fail-params + - put: slack-alert + params: + <<: *slack-success-params +- name: jdk16-run-system-tests + serial: true + public: true + plan: + - get: ci-image-jdk16 + - get: git-repo + - get: paketo-builder-base-image + trigger: true + - get: daily + trigger: true + - do: + - task: run-system-tests + image: ci-image-jdk16 + privileged: true + timeout: ((task-timeout)) + file: git-repo/ci/tasks/run-system-tests.yml + params: + BRANCH: ((branch)) + TOOLCHAIN_JAVA_VERSION: 16 + <<: *gradle-enterprise-task-params + <<: *docker-hub-task-params + on_failure: + do: + - put: slack-alert + params: + <<: *slack-fail-params + - put: slack-alert + params: + <<: *slack-success-params groups: - name: "builds" jobs: ["build", "jdk11-build", "jdk16-build", "windows-build"] - name: "releases" jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release", "publish-gradle-plugin", "publish-to-sdkman", "update-homebrew-tap"] +- name: "system-tests" + jobs: ["run-system-tests", "jdk11-run-system-tests", "jdk16-run-system-tests"] - name: "ci-images" jobs: ["build-ci-images", "detect-docker-updates", "detect-jdk-updates", "detect-ubuntu-image-updates"] - name: "pull-requests" diff --git a/ci/scripts/run-system-tests.sh b/ci/scripts/run-system-tests.sh new file mode 100755 index 0000000000..4cb3025da6 --- /dev/null +++ b/ci/scripts/run-system-tests.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +source $(dirname $0)/common.sh + +pushd git-repo > /dev/null +if [[ -d /opt/openjdk-toolchain ]]; then + ./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 --rerun-tasks systemTest -PtoolchainVersion=${TOOLCHAIN_JAVA_VERSION} -Porg.gradle.java.installations.auto-detect=false -Porg.gradle.java.installations.auto-download=false -Porg.gradle.java.installations.paths=/opt/openjdk-toolchain/ +else + ./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 --rerun-tasks systemTest +fi +popd > /dev/null diff --git a/ci/tasks/run-system-tests.yml b/ci/tasks/run-system-tests.yml new file mode 100644 index 0000000000..5a1f6e5bd0 --- /dev/null +++ b/ci/tasks/run-system-tests.yml @@ -0,0 +1,21 @@ +--- +platform: linux +inputs: +- name: git-repo +caches: +- path: gradle +params: + BRANCH: + CI: true + GRADLE_ENTERPRISE_ACCESS_KEY: + GRADLE_ENTERPRISE_CACHE_USERNAME: + GRADLE_ENTERPRISE_CACHE_PASSWORD: + GRADLE_ENTERPRISE_URL: https://ge.spring.io +run: + path: bash + args: + - -ec + - | + source /docker-lib.sh + start_docker + ${PWD}/git-repo/ci/scripts/run-system-tests.sh diff --git a/settings.gradle b/settings.gradle index c75bb113f1..90c976ef51 100644 --- a/settings.gradle +++ b/settings.gradle @@ -75,6 +75,7 @@ include "spring-boot-tests:spring-boot-integration-tests:spring-boot-configurati include "spring-boot-tests:spring-boot-integration-tests:spring-boot-launch-script-tests" include "spring-boot-tests:spring-boot-integration-tests:spring-boot-loader-tests" include "spring-boot-tests:spring-boot-integration-tests:spring-boot-server-tests" +include "spring-boot-system-tests:spring-boot-image-tests" file("${rootDir}/spring-boot-project/spring-boot-starters").eachDirMatch(~/spring-boot-starter.*/) { include "spring-boot-project:spring-boot-starters:${it.name}" diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/GettingStartedDocumentationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/GettingStartedDocumentationTests.java index 404dba2c72..a1ce4a316e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/GettingStartedDocumentationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/GettingStartedDocumentationTests.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. @@ -20,7 +20,7 @@ import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.gradle.junit.GradleMultiDslExtension; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; /** * Tests for the getting started documentation. diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/IntegratingWithActuatorDocumentationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/IntegratingWithActuatorDocumentationTests.java index da30a982fc..748899b2aa 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/IntegratingWithActuatorDocumentationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/IntegratingWithActuatorDocumentationTests.java @@ -25,7 +25,7 @@ import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.gradle.junit.GradleMultiDslExtension; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/ManagingDependenciesDocumentationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/ManagingDependenciesDocumentationTests.java index d2608379fa..be33e3567d 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/ManagingDependenciesDocumentationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/ManagingDependenciesDocumentationTests.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. @@ -20,8 +20,8 @@ import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.gradle.junit.GradleMultiDslExtension; -import org.springframework.boot.gradle.testkit.Dsl; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.Dsl; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assumptions.assumingThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java index 6b68af4c5b..cc0330e423 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java @@ -33,7 +33,7 @@ import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.gradle.junit.GradleMultiDslExtension; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import org.springframework.util.FileCopyUtils; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PublishingDocumentationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PublishingDocumentationTests.java index 028dfdd109..6bbba73fac 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PublishingDocumentationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PublishingDocumentationTests.java @@ -22,7 +22,7 @@ import org.junit.jupiter.api.condition.JRE; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.gradle.junit.GradleMultiDslExtension; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/RunningDocumentationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/RunningDocumentationTests.java index 87d597f384..dbf5b95622 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/RunningDocumentationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/RunningDocumentationTests.java @@ -27,7 +27,7 @@ import org.junit.jupiter.api.condition.JRE; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.gradle.junit.GradleMultiDslExtension; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/dsl/BuildInfoDslIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/dsl/BuildInfoDslIntegrationTests.java index 3ca1134000..c584b3deda 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/dsl/BuildInfoDslIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/dsl/BuildInfoDslIntegrationTests.java @@ -26,7 +26,7 @@ import org.junit.jupiter.api.TestTemplate; import org.springframework.boot.gradle.junit.GradleCompatibility; import org.springframework.boot.gradle.tasks.buildinfo.BuildInfo; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleBuildFieldSetter.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleBuildFieldSetter.java index 19ea8e67cc..7dcf7be83e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleBuildFieldSetter.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleBuildFieldSetter.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. @@ -21,7 +21,7 @@ import java.lang.reflect.Field; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import org.springframework.util.ReflectionUtils; /** diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleCompatibility.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleCompatibility.java index 9617f0d94d..5ab519faee 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleCompatibility.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleCompatibility.java @@ -26,7 +26,7 @@ import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.Extension; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; /** * {@link Extension} that runs {@link TestTemplate templated tests} against multiple diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleCompatibilityExtension.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleCompatibilityExtension.java index 7d4876e20a..ce30517e0f 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleCompatibilityExtension.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleCompatibilityExtension.java @@ -21,7 +21,6 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Stream; -import org.gradle.api.JavaVersion; import org.gradle.util.GradleVersion; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.Extension; @@ -30,8 +29,9 @@ import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider; import org.junit.platform.commons.util.AnnotationUtils; -import org.springframework.boot.gradle.testkit.GradleBuild; -import org.springframework.boot.gradle.testkit.GradleBuildExtension; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuildExtension; +import org.springframework.boot.testsupport.gradle.testkit.GradleVersions; import org.springframework.util.StringUtils; /** @@ -43,26 +43,11 @@ import org.springframework.util.StringUtils; */ final class GradleCompatibilityExtension implements TestTemplateInvocationContextProvider { - private static final List GRADLE_VERSIONS; - - static { - JavaVersion javaVersion = JavaVersion.current(); - if (javaVersion.isCompatibleWith(JavaVersion.VERSION_16)) { - GRADLE_VERSIONS = Arrays.asList("7.0.2", "7.1.1"); - } - else { - GRADLE_VERSIONS = Arrays.asList("6.8.3", "current", "7.0.2", "7.1.1"); - } - } + private static final List GRADLE_VERSIONS = GradleVersions.allCompatible(); @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { - Stream gradleVersions = GRADLE_VERSIONS.stream().map((version) -> { - if (version.equals("current")) { - return GradleVersion.current().getVersion(); - } - return version; - }); + Stream gradleVersions = GRADLE_VERSIONS.stream(); GradleCompatibility gradleCompatibility = AnnotationUtils .findAnnotation(context.getRequiredTestClass(), GradleCompatibility.class).get(); if (StringUtils.hasText(gradleCompatibility.versionsLessThan())) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleMultiDslExtension.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleMultiDslExtension.java index 829e220e1b..9cebd90121 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleMultiDslExtension.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleMultiDslExtension.java @@ -20,16 +20,16 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Stream; -import org.gradle.api.JavaVersion; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider; -import org.springframework.boot.gradle.testkit.Dsl; -import org.springframework.boot.gradle.testkit.GradleBuild; -import org.springframework.boot.gradle.testkit.GradleBuildExtension; +import org.springframework.boot.testsupport.gradle.testkit.Dsl; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuildExtension; +import org.springframework.boot.testsupport.gradle.testkit.GradleVersions; /** * {@link Extension} that runs {@link TestTemplate templated tests} against the Groovy and @@ -61,10 +61,7 @@ public class GradleMultiDslExtension implements TestTemplateInvocationContextPro @Override public List getAdditionalExtensions() { GradleBuild gradleBuild = new GradleBuild(this.dsl); - JavaVersion javaVersion = JavaVersion.current(); - if (javaVersion.isCompatibleWith(JavaVersion.VERSION_16)) { - gradleBuild.gradleVersion("7.0.2"); - } + gradleBuild.gradleVersion(GradleVersions.currentOrMinimumCompatible()); return Arrays.asList(new GradleBuildFieldSetter(gradleBuild), new GradleBuildExtension()); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.java index 5a595258c0..fee3f56d77 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.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. @@ -32,7 +32,7 @@ import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.TestTemplate; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/DependencyManagementPluginActionIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/DependencyManagementPluginActionIntegrationTests.java index 73975c1435..1041969f10 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/DependencyManagementPluginActionIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/DependencyManagementPluginActionIntegrationTests.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. @@ -20,7 +20,7 @@ import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.TestTemplate; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.java index 9633fc1830..8bfb19ac37 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.java @@ -26,7 +26,7 @@ import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.TestTemplate; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/KotlinPluginActionIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/KotlinPluginActionIntegrationTests.java index 4f3a0732e3..07568b49a5 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/KotlinPluginActionIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/KotlinPluginActionIntegrationTests.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. @@ -19,7 +19,7 @@ package org.springframework.boot.gradle.plugin; import org.junit.jupiter.api.TestTemplate; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/MavenPluginActionIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/MavenPluginActionIntegrationTests.java index c4672e8071..3c8fc1279b 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/MavenPluginActionIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/MavenPluginActionIntegrationTests.java @@ -21,7 +21,7 @@ import org.junit.jupiter.api.condition.DisabledForJreRange; import org.junit.jupiter.api.condition.JRE; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/OnlyDependencyManagementIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/OnlyDependencyManagementIntegrationTests.java index ad8145a1f8..e9424d9032 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/OnlyDependencyManagementIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/OnlyDependencyManagementIntegrationTests.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. @@ -19,7 +19,7 @@ package org.springframework.boot.gradle.plugin; import org.junit.jupiter.api.TestTemplate; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java index d51b3f85f0..72361e8f82 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java @@ -22,8 +22,8 @@ import org.junit.jupiter.api.condition.DisabledForJreRange; import org.junit.jupiter.api.condition.JRE; import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.gradle.testkit.GradleBuild; -import org.springframework.boot.gradle.testkit.GradleBuildExtension; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuildExtension; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/WarPluginActionIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/WarPluginActionIntegrationTests.java index 73e7cda463..e1030c63d8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/WarPluginActionIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/WarPluginActionIntegrationTests.java @@ -23,7 +23,7 @@ import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.TestTemplate; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.java index e18d9ecee6..bc9e7a4fe7 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.java @@ -30,8 +30,8 @@ import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.TestTemplate; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; import org.springframework.boot.loader.tools.FileUtils; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java index 48f62516f9..aa733804e7 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java @@ -49,9 +49,9 @@ import org.gradle.testkit.runner.BuildResult; import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.TestTemplate; -import org.springframework.boot.gradle.testkit.GradleBuild; import org.springframework.boot.loader.tools.FileUtils; import org.springframework.boot.loader.tools.JarModeLibrary; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import org.springframework.util.FileSystemUtils; import org.springframework.util.StringUtils; 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 14742f09a7..90dc7d3c61 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 @@ -44,7 +44,7 @@ import org.springframework.boot.buildpack.platform.docker.type.ImageName; import org.springframework.boot.buildpack.platform.docker.type.ImageReference; import org.springframework.boot.buildpack.platform.io.FilePermissions; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import org.springframework.boot.testsupport.testcontainers.DisabledIfDockerUnavailable; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageRegistryIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageRegistryIntegrationTests.java index 5fd56b4abb..babc242ed2 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageRegistryIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageRegistryIntegrationTests.java @@ -36,7 +36,7 @@ import org.springframework.boot.buildpack.platform.docker.UpdateListener; import org.springframework.boot.buildpack.platform.docker.type.Image; import org.springframework.boot.buildpack.platform.docker.type.ImageReference; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import org.springframework.boot.testsupport.testcontainers.DockerImageNames; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/MavenIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/MavenIntegrationTests.java index 975c63c8f4..09f21ebc12 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/MavenIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/MavenIntegrationTests.java @@ -25,7 +25,7 @@ import org.junit.jupiter.api.condition.DisabledForJreRange; import org.junit.jupiter.api.condition.JRE; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/MavenPublishingIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/MavenPublishingIntegrationTests.java index 2571e1e256..f39eafce40 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/MavenPublishingIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/MavenPublishingIntegrationTests.java @@ -23,7 +23,7 @@ import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.TestTemplate; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/run/BootRunIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/run/BootRunIntegrationTests.java index 67590476fa..c9953c3e41 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/run/BootRunIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/run/BootRunIntegrationTests.java @@ -30,7 +30,7 @@ import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.TestTemplate; import org.springframework.boot.gradle.junit.GradleCompatibility; -import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; import org.springframework.util.FileSystemUtils; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-test-support/build.gradle index afcb084d11..922c6530a3 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-test-support/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/build.gradle @@ -20,6 +20,16 @@ dependencies { compileOnly("org.springframework.data:spring-data-redis") compileOnly("org.testcontainers:testcontainers") + compileOnly(project(":spring-boot-project:spring-boot-tools:spring-boot-buildpack-platform")) + compileOnly(project(":spring-boot-project:spring-boot-tools:spring-boot-loader-tools")) + compileOnly("io.spring.gradle:dependency-management-plugin") + compileOnly(gradleTestKit()) + compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + compileOnly("org.jetbrains.kotlin:kotlin-compiler-embeddable:$kotlinVersion") + compileOnly("org.jetbrains.kotlin:kotlin-compiler-runner:$kotlinVersion") + compileOnly("org.jetbrains.kotlin:kotlin-daemon-client:$kotlinVersion") + compileOnly("org.apache.commons:commons-compress") + implementation("org.apache.maven.resolver:maven-resolver-connector-basic") implementation("org.apache.maven.resolver:maven-resolver-impl") implementation("org.apache.maven:maven-resolver-provider") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/Dsl.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/Dsl.java similarity index 83% rename from spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/Dsl.java rename to spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/Dsl.java index ac352bf031..27e2ff2e99 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/Dsl.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/Dsl.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. @@ -14,13 +14,18 @@ * limitations under the License. */ -package org.springframework.boot.gradle.testkit; +package org.springframework.boot.testsupport.gradle.testkit; /** - * The DSLs supported by Gradle and demonstrated in the documentation samples + * The DSLs supported by Gradle and demonstrated in the documentation samples. + * + * @author Andy Wilkinson */ public enum Dsl { + /** + * Supported DSL variants. + */ GROOVY("Groovy", ".gradle"), KOTLIN("Kotlin", ".gradle.kts"); private final String name; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/GradleBuild.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleBuild.java similarity index 92% rename from spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/GradleBuild.java rename to spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleBuild.java index d2f3a7be46..605b1b02f6 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/GradleBuild.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleBuild.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.gradle.testkit; +package org.springframework.boot.testsupport.gradle.testkit; import java.io.File; import java.io.FileReader; @@ -74,8 +74,12 @@ public class GradleBuild { private String script; + private String settings; + private String gradleVersion; + private String springBootVersion = "TEST-SNAPSHOT"; + private GradleVersion expectDeprecationWarnings; private boolean configurationCache = false; @@ -84,8 +88,6 @@ public class GradleBuild { public GradleBuild() { this(Dsl.GROOVY); - this.scriptProperties.put("bootVersion", getBootVersion()); - this.scriptProperties.put("dependencyManagementPluginVersion", getDependencyManagementPluginVersion()); } public GradleBuild(Dsl dsl) { @@ -133,6 +135,10 @@ public class GradleBuild { return this; } + public void settings(String settings) { + this.settings = settings; + } + public GradleBuild expectDeprecationWarningsWithAtLeastVersion(String gradleVersion) { this.expectDeprecationWarnings = GradleVersion.version(gradleVersion); return this; @@ -173,12 +179,20 @@ public class GradleBuild { public GradleRunner prepareRunner(String... arguments) throws IOException { String scriptContent = FileCopyUtils.copyToString(new FileReader(this.script)); + this.scriptProperties.put("bootVersion", getBootVersion()); + this.scriptProperties.put("dependencyManagementPluginVersion", getDependencyManagementPluginVersion()); for (Entry property : this.scriptProperties.entrySet()) { scriptContent = scriptContent.replace("{" + property.getKey() + "}", property.getValue()); } FileCopyUtils.copy(scriptContent, new FileWriter(new File(this.projectDir, "build" + this.dsl.getExtension()))); - FileSystemUtils.copyRecursively(new File("src/test/resources/repository"), - new File(this.projectDir, "repository")); + if (this.settings != null) { + FileCopyUtils.copy(new FileReader(this.settings), + new FileWriter(new File(this.projectDir, "settings.gradle"))); + } + File repository = new File("src/test/resources/repository"); + if (repository.exists()) { + FileSystemUtils.copyRecursively(repository, new File(this.projectDir, "repository")); + } GradleRunner gradleRunner = GradleRunner.create().withProjectDir(this.projectDir) .withPluginClasspath(pluginClasspath()); if (this.dsl != Dsl.KOTLIN && !this.configurationCache) { @@ -225,8 +239,13 @@ public class GradleBuild { return this.gradleVersion; } - private static String getBootVersion() { - return "TEST-SNAPSHOT"; + public GradleBuild bootVersion(String version) { + this.springBootVersion = version; + return this; + } + + private String getBootVersion() { + return this.springBootVersion; } private static String getDependencyManagementPluginVersion() { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/GradleBuildExtension.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleBuildExtension.java similarity index 87% rename from spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/GradleBuildExtension.java rename to spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleBuildExtension.java index eadf21d445..ee2583cd9a 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/GradleBuildExtension.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleBuildExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.gradle.testkit; +package org.springframework.boot.testsupport.gradle.testkit; import java.lang.reflect.Field; import java.net.URL; @@ -32,6 +32,7 @@ import org.springframework.util.ReflectionUtils; * field named {@code gradleBuild}. * * @author Andy Wilkinson + * @author Scott Frederick */ public class GradleBuildExtension implements BeforeEachCallback, AfterEachCallback { @@ -46,6 +47,10 @@ public class GradleBuildExtension implements BeforeEachCallback, AfterEachCallba if (scriptUrl != null) { gradleBuild.script(scriptUrl.getFile()); } + URL settingsUrl = getSettings(context); + if (settingsUrl != null) { + gradleBuild.settings(settingsUrl.getFile()); + } gradleBuild.before(); } @@ -80,6 +85,11 @@ public class GradleBuildExtension implements BeforeEachCallback, AfterEachCallba return testClass.getResource(testClass.getSimpleName() + this.dsl.getExtension()); } + private URL getSettings(ExtensionContext context) { + Class testClass = context.getRequiredTestClass(); + return testClass.getResource("settings.gradle"); + } + @Override public void afterEach(ExtensionContext context) throws Exception { extractGradleBuild(context).after(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleVersions.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleVersions.java new file mode 100644 index 0000000000..12280b21bd --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleVersions.java @@ -0,0 +1,53 @@ +/* + * 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.springframework.boot.testsupport.gradle.testkit; + +import java.util.Arrays; +import java.util.List; + +import org.gradle.api.JavaVersion; +import org.gradle.util.GradleVersion; + +/** + * Versions of Gradle used for testing. + * + * @author Scott Frederick + */ +public final class GradleVersions { + + private GradleVersions() { + } + + public static List allCompatible() { + if (isJava16()) { + return Arrays.asList("7.0.2", "7.1"); + } + return Arrays.asList("6.8.3", GradleVersion.current().getVersion(), "7.0.2", "7.1.1"); + } + + public static String currentOrMinimumCompatible() { + if (isJava16()) { + return "7.0.2"; + } + return GradleVersion.current().getVersion(); + } + + private static boolean isJava16() { + return JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_16); + } + +} diff --git a/spring-boot-system-tests/spring-boot-image-tests/build.gradle b/spring-boot-system-tests/spring-boot-image-tests/build.gradle new file mode 100644 index 0000000000..a81b650293 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/build.gradle @@ -0,0 +1,35 @@ +plugins { + id 'java-gradle-plugin' + id "org.springframework.boot.conventions" + id "org.springframework.boot.system-test" +} + +description = "Spring Boot Image Building Tests" + +configurations { + providedRuntime { + extendsFrom dependencyManagement + } +} + +systemTest { + if (project.hasProperty("springBootVersion")) { + systemProperty "springBootVersion", project.properties["springBootVersion"] + } else { + systemProperty "springBootVersion", project.getVersion() + } +} + +dependencies { + implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-web")) { + exclude group: "org.hibernate.validator" + } + + systemTestImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test")) + systemTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support")) + systemTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-buildpack-platform")) + systemTestImplementation(gradleTestKit()) + systemTestImplementation("org.assertj:assertj-core") + systemTestImplementation("org.testcontainers:junit-jupiter") + systemTestImplementation("org.testcontainers:testcontainers") +} diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ContainerConfigAssert.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ContainerConfigAssert.java new file mode 100644 index 0000000000..890af544a8 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ContainerConfigAssert.java @@ -0,0 +1,134 @@ +/* + * 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.springframework.boot.image.assertions; + +import java.util.List; +import java.util.Map; + +import com.github.dockerjava.api.model.ContainerConfig; +import org.assertj.core.api.AbstractAssert; +import org.assertj.core.api.AbstractListAssert; +import org.assertj.core.api.AbstractObjectAssert; +import org.assertj.core.api.AbstractStringAssert; +import org.assertj.core.api.Assertions; +import org.assertj.core.api.AssertionsForClassTypes; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.assertj.core.api.ListAssert; +import org.assertj.core.api.ObjectAssert; + +import org.springframework.boot.test.json.JsonContentAssert; + +/** + * AssertJ {@link org.assertj.core.api.Assert} for Docker image container configuration. + * + * @author Scott Frederick + */ +public class ContainerConfigAssert extends AbstractAssert { + + private static final String BUILD_METADATA_LABEL = "io.buildpacks.build.metadata"; + + private static final String LIFECYCLE_METADATA_LABEL = "io.buildpacks.lifecycle.metadata"; + + ContainerConfigAssert(ContainerConfig containerConfig) { + super(containerConfig, ContainerConfigAssert.class); + } + + public BuildMetadataAssert buildMetadata() { + return new BuildMetadataAssert(jsonLabel(BUILD_METADATA_LABEL)); + } + + public LifecycleMetadataAssert lifecycleMetadata() { + return new LifecycleMetadataAssert(jsonLabel(LIFECYCLE_METADATA_LABEL)); + } + + public AbstractStringAssert label(String label) { + return AssertionsForClassTypes.assertThat(getLabel(label)); + } + + private JsonContentAssert jsonLabel(String label) { + return new JsonContentAssert(ContainerConfigAssert.class, getLabel(label)); + } + + private String getLabel(String label) { + Map labels = this.actual.getLabels(); + if (labels == null) { + failWithMessage("Container config contains no labels"); + } + if (!labels.containsKey(label)) { + failWithActualExpectedAndMessage(labels, label, "Expected label not found in container config"); + } + return labels.get(label); + } + + /** + * Asserts for the JSON content in the {@code io.buildpacks.build.metadata} label. + * + * See the + * spec + */ + public static class BuildMetadataAssert extends AbstractAssert { + + BuildMetadataAssert(JsonContentAssert jsonContentAssert) { + super(jsonContentAssert, BuildMetadataAssert.class); + } + + public ListAssert buildpacks() { + return this.actual.extractingJsonPathArrayValue("$.buildpacks[*].id"); + } + + public ListAssert bomDependencies() { + return this.actual + .extractingJsonPathArrayValue("$.bom[?(@.name=='dependencies')].metadata.dependencies[*].name"); + } + + public AbstractStringAssert bomJavaVersion(String javaType) { + return this.actual.extractingJsonPathArrayValue("$.bom[?(@.name=='%s')].metadata.version", javaType) + .singleElement(Assertions.as(InstanceOfAssertFactories.STRING)); + } + + public AbstractObjectAssert processOfType(String type) { + return this.actual.extractingJsonPathArrayValue("$.processes[?(@.type=='%s')]", type).singleElement(); + } + + } + + /** + * Asserts for the the JSON content in the {@code io.buildpacks.lifecycle.metadata} + * label. + * + * See the + * spec + */ + public static class LifecycleMetadataAssert extends AbstractAssert { + + LifecycleMetadataAssert(JsonContentAssert jsonContentAssert) { + super(jsonContentAssert, LifecycleMetadataAssert.class); + } + + public ListAssert buildpackLayers(String buildpackId) { + return this.actual.extractingJsonPathArrayValue("$.buildpacks[?(@.key=='%s')].layers", buildpackId); + } + + public AbstractListAssert, Object, ObjectAssert> appLayerShas() { + return this.actual.extractingJsonPathArrayValue("$.app").extracting("sha"); + } + + } + +} diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java new file mode 100644 index 0000000000..5baf076491 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java @@ -0,0 +1,91 @@ +/* + * 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.springframework.boot.image.assertions; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.assertj.core.api.AbstractAssert; +import org.assertj.core.api.Assertions; +import org.assertj.core.api.ListAssert; + +import org.springframework.boot.buildpack.platform.docker.DockerApi; +import org.springframework.boot.buildpack.platform.docker.type.ImageReference; +import org.springframework.boot.buildpack.platform.docker.type.Layer; + +/** + * AssertJ {@link org.assertj.core.api.Assert} for Docker image contents. + * + * @author Scott Frederick + */ +public class ImageAssert extends AbstractAssert { + + private final HashMap layers = new HashMap<>(); + + ImageAssert(ImageReference imageReference) throws IOException { + super(imageReference, ImageAssert.class); + getLayers(); + } + + public LayerContentAssert hasLayer(String layerDigest) { + if (!this.layers.containsKey(layerDigest)) { + failWithMessage("Layer with digest '%s' not found in image", layerDigest); + } + return new LayerContentAssert(this.layers.get(layerDigest)); + } + + private void getLayers() throws IOException { + new DockerApi().image().exportLayers(this.actual, (id, tarArchive) -> { + Layer layer = Layer.fromTarArchive(tarArchive); + this.layers.put(layer.getId().toString(), layer); + }); + } + + /** + * Asserts for image layers. + */ + public static class LayerContentAssert extends AbstractAssert { + + public LayerContentAssert(Layer layer) { + super(layer, LayerContentAssert.class); + } + + public ListAssert entries() throws IOException { + List entryNames = new ArrayList<>(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + this.actual.writeTo(out); + try (TarArchiveInputStream in = new TarArchiveInputStream(new ByteArrayInputStream(out.toByteArray()))) { + TarArchiveEntry entry = in.getNextTarEntry(); + while (entry != null) { + if (!entry.isDirectory()) { + entryNames.add(entry.getName().replaceFirst("^/workspace/", "")); + } + entry = in.getNextTarEntry(); + } + } + return Assertions.assertThat(entryNames); + } + + } + +} diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssertions.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssertions.java new file mode 100644 index 0000000000..b13083943e --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssertions.java @@ -0,0 +1,44 @@ +/* + * 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.springframework.boot.image.assertions; + +import java.io.IOException; + +import com.github.dockerjava.api.model.ContainerConfig; + +import org.springframework.boot.buildpack.platform.docker.type.ImageReference; + +/** + * Factory class for custom AssertJ {@link org.assertj.core.api.Assert}s related to images + * and containers. + * + * @author Scott Frederick + */ +public final class ImageAssertions { + + private ImageAssertions() { + } + + public static ContainerConfigAssert assertThat(ContainerConfig containerConfig) { + return new ContainerConfigAssert(containerConfig); + } + + public static ImageAssert assertThat(ImageReference imageReference) throws IOException { + return new ImageAssert(imageReference); + } + +} diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/junit/GradleBuildInjectionExtension.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/junit/GradleBuildInjectionExtension.java new file mode 100644 index 0000000000..4cafc9b3b0 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/junit/GradleBuildInjectionExtension.java @@ -0,0 +1,54 @@ +/* + * 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.springframework.boot.image.junit; + +import java.lang.reflect.Field; + +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleVersions; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +/** + * A {@link BeforeEachCallback} to configure and set a test class's {@code gradleBuild} + * field prior to test execution. + * + * @author Scott Frederick + */ +public class GradleBuildInjectionExtension implements BeforeEachCallback { + + private final GradleBuild gradleBuild; + + GradleBuildInjectionExtension() { + this.gradleBuild = new GradleBuild(); + this.gradleBuild.gradleVersion(GradleVersions.currentOrMinimumCompatible()); + String bootVersion = System.getProperty("springBootVersion"); + Assert.notNull(bootVersion, "Property 'springBootVersion' must be set in build environment"); + this.gradleBuild.bootVersion(bootVersion); + } + + @Override + public void beforeEach(ExtensionContext context) throws Exception { + Field field = ReflectionUtils.findField(context.getRequiredTestClass(), "gradleBuild"); + field.setAccessible(true); + field.set(context.getRequiredTestInstance(), this.gradleBuild); + } + +} diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/LayersIndex.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/LayersIndex.java new file mode 100644 index 0000000000..34460dbbe6 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/LayersIndex.java @@ -0,0 +1,53 @@ +/* + * 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.springframework.boot.image.paketo; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; + +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; + +/** + * Index file describing the layers in the jar or war file and the files or directories in + * each layer. + * + * @author Scott Frederick + */ +class LayersIndex extends ArrayList>> { + + List getLayer(String layerName) { + return stream().filter((entry) -> entry.containsKey(layerName)).findFirst().map((entry) -> entry.get(layerName)) + .orElse(Collections.emptyList()); + } + + static LayersIndex fromArchiveFile(File archiveFile) throws IOException { + String indexPath = (archiveFile.getName().endsWith(".war") ? "WEB-INF/layers.idx" : "BOOT-INF/layers.idx"); + try (JarFile jarFile = new JarFile(archiveFile)) { + ZipEntry indexEntry = jarFile.getEntry(indexPath); + Yaml yaml = new Yaml(new Constructor(LayersIndex.class)); + return yaml.load(jarFile.getInputStream(indexEntry)); + } + } + +} diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/PaketoBuilderTests.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/PaketoBuilderTests.java new file mode 100644 index 0000000000..a0523919f8 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/PaketoBuilderTests.java @@ -0,0 +1,402 @@ +/* + * 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.springframework.boot.image.paketo; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.jar.Attributes; +import java.util.jar.JarFile; + +import com.github.dockerjava.api.model.ContainerConfig; +import org.assertj.core.api.Condition; +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.TaskOutcome; +import org.junit.jupiter.api.Test; +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; +import org.springframework.boot.buildpack.platform.docker.type.ImageReference; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; +import org.springframework.boot.testsupport.gradle.testkit.GradleBuildExtension; +import org.springframework.boot.image.assertions.ImageAssertions; +import org.springframework.boot.image.junit.GradleBuildInjectionExtension; +import org.springframework.util.StringUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration tests for the Paketo builder and buildpacks. + * + * See + * https://paketo.io/docs/buildpacks/language-family-buildpacks/java/#additional-metadata + * + * @author Scott Frederick + */ +@ExtendWith({ GradleBuildInjectionExtension.class, GradleBuildExtension.class }) +class PaketoBuilderTests { + + GradleBuild gradleBuild; + + @Test + void executableJarApp() throws Exception { + writeMainClass(); + String imageName = "paketo-integration/" + this.gradleBuild.getProjectDir().getName(); + ImageReference imageReference = ImageReference.of(ImageName.of(imageName)); + BuildResult result = buildImage(imageName); + assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + try (GenericContainer container = new GenericContainer<>(imageName).withExposedPorts(8080)) { + container.waitingFor(Wait.forHttp("/test")).start(); + ContainerConfig config = container.getContainerInfo().getConfig(); + assertLabelsMatchManifestAttributes(config); + ImageAssertions.assertThat(config).buildMetadata().buildpacks().containsExactly( + "paketo-buildpacks/ca-certificates", "paketo-buildpacks/bellsoft-liberica", + "paketo-buildpacks/executable-jar", "paketo-buildpacks/dist-zip", "paketo-buildpacks/spring-boot"); + ImageAssertions.assertThat(config).buildMetadata().bomDependencies().contains("spring-beans", "spring-boot", + "spring-boot-autoconfigure", "spring-boot-jarmode-layertools", "spring-context", "spring-core", + "spring-web"); + ImageAssertions.assertThat(config).buildMetadata().bomJavaVersion("jre").startsWith(javaMajorVersion()); + ImageAssertions.assertThat(config).buildMetadata().processOfType("web").extracting("command", "args") + .containsExactly("java", Collections.singletonList("org.springframework.boot.loader.JarLauncher")); + ImageAssertions.assertThat(config).buildMetadata().processOfType("executable-jar") + .extracting("command", "args") + .containsExactly("java", Collections.singletonList("org.springframework.boot.loader.JarLauncher")); + assertImageLayersMatchLayersIndex(imageReference, config); + } + finally { + removeImage(imageReference); + } + } + + @Test + void executableJarAppWithAdditionalArgs() throws Exception { + writeMainClass(); + String imageName = "paketo-integration/" + this.gradleBuild.getProjectDir().getName(); + ImageReference imageReference = ImageReference.of(ImageName.of(imageName)); + BuildResult result = buildImage(imageName); + assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + try (GenericContainer container = new GenericContainer<>(imageName).withCommand("--server.port=9090") + .withExposedPorts(9090)) { + container.waitingFor(Wait.forHttp("/test")).start(); + } + finally { + removeImage(imageReference); + } + } + + @Test + void executableJarAppBuiltTwiceWithCaching() throws Exception { + writeMainClass(); + String imageName = "paketo-integration/" + this.gradleBuild.getProjectDir().getName(); + ImageReference imageReference = ImageReference.of(ImageName.of(imageName)); + BuildResult result = buildImage(imageName); + assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + try (GenericContainer container = new GenericContainer<>(imageName).withExposedPorts(8080)) { + container.waitingFor(Wait.forHttp("/test")).start(); + container.stop(); + } + result = buildImage(imageName); + assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + try (GenericContainer container = new GenericContainer<>(imageName).withExposedPorts(8080)) { + container.waitingFor(Wait.forHttp("/test")).start(); + } + finally { + removeImage(imageReference); + } + } + + @Test + void bootDistZipJarApp() throws Exception { + writeMainClass(); + String projectName = this.gradleBuild.getProjectDir().getName(); + String imageName = "paketo-integration/" + projectName; + ImageReference imageReference = ImageReference.of(ImageName.of(imageName)); + BuildResult result = buildImage(imageName, "assemble", "bootDistZip"); + assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + try (GenericContainer container = new GenericContainer<>(imageName).withExposedPorts(8080)) { + container.waitingFor(Wait.forHttp("/test")).start(); + ContainerConfig config = container.getContainerInfo().getConfig(); + ImageAssertions.assertThat(config).buildMetadata().buildpacks().containsExactly( + "paketo-buildpacks/ca-certificates", "paketo-buildpacks/bellsoft-liberica", + "paketo-buildpacks/dist-zip", "paketo-buildpacks/spring-boot"); + ImageAssertions.assertThat(config).buildMetadata().bomJavaVersion("jre").startsWith(javaMajorVersion()); + ImageAssertions.assertThat(config).buildMetadata().processOfType("web").extracting("command", "args") + .containsExactly("/workspace/" + projectName + "-boot/bin/" + projectName, Collections.emptyList()); + ImageAssertions.assertThat(config).buildMetadata().processOfType("dist-zip").extracting("command", "args") + .containsExactly("/workspace/" + projectName + "-boot/bin/" + projectName, Collections.emptyList()); + DigestCapturingCondition digests = new DigestCapturingCondition(); + ImageAssertions.assertThat(config).lifecycleMetadata().appLayerShas().haveExactly(1, digests); + ImageAssertions.assertThat(imageReference).hasLayer(digests.getDigest(0)).entries().contains( + projectName + "-boot/bin/" + projectName, projectName + "-boot/lib/" + projectName + ".jar"); + } + finally { + removeImage(imageReference); + } + } + + @Test + void plainDistZipJarApp() throws Exception { + writeMainClass(); + String projectName = this.gradleBuild.getProjectDir().getName(); + String imageName = "paketo-integration/" + projectName; + ImageReference imageReference = ImageReference.of(ImageName.of(imageName)); + BuildResult result = buildImage(imageName, "assemble", "bootDistZip"); + assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + try (GenericContainer container = new GenericContainer<>(imageName).withExposedPorts(8080)) { + container.waitingFor(Wait.forHttp("/test")).start(); + ContainerConfig config = container.getContainerInfo().getConfig(); + ImageAssertions.assertThat(config).buildMetadata().buildpacks().containsExactly( + "paketo-buildpacks/ca-certificates", "paketo-buildpacks/bellsoft-liberica", + "paketo-buildpacks/dist-zip", "paketo-buildpacks/spring-boot"); + ImageAssertions.assertThat(config).buildMetadata().bomJavaVersion("jre").startsWith(javaMajorVersion()); + ImageAssertions.assertThat(config).buildMetadata().processOfType("web").extracting("command", "args") + .containsExactly("/workspace/" + projectName + "/bin/" + projectName, Collections.emptyList()); + ImageAssertions.assertThat(config).buildMetadata().processOfType("dist-zip").extracting("command", "args") + .containsExactly("/workspace/" + projectName + "/bin/" + projectName, Collections.emptyList()); + DigestCapturingCondition digests = new DigestCapturingCondition(); + ImageAssertions.assertThat(config).lifecycleMetadata().appLayerShas().haveExactly(1, digests); + ImageAssertions.assertThat(imageReference).hasLayer(digests.getDigest(0)).entries() + .contains(projectName + "/bin/" + projectName, projectName + "/lib/" + projectName + "-plain.jar") + .anyMatch((s) -> s.startsWith(projectName + "/lib/spring-boot-")) + .anyMatch((s) -> s.startsWith(projectName + "/lib/spring-core-")) + .anyMatch((s) -> s.startsWith(projectName + "/lib/spring-web-")); + } + finally { + removeImage(imageReference); + } + } + + @Test + void executableWarApp() throws Exception { + writeMainClass(); + writeServletInitializerClass(); + String imageName = "paketo-integration/" + this.gradleBuild.getProjectDir().getName(); + ImageReference imageReference = ImageReference.of(ImageName.of(imageName)); + BuildResult result = buildImage(imageName); + assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + try (GenericContainer container = new GenericContainer<>(imageName).withExposedPorts(8080)) { + container.waitingFor(Wait.forHttp("/test")).start(); + ContainerConfig config = container.getContainerInfo().getConfig(); + assertLabelsMatchManifestAttributes(config); + ImageAssertions.assertThat(config).buildMetadata().buildpacks().containsExactly( + "paketo-buildpacks/ca-certificates", "paketo-buildpacks/bellsoft-liberica", + "paketo-buildpacks/executable-jar", "paketo-buildpacks/dist-zip", "paketo-buildpacks/spring-boot"); + ImageAssertions.assertThat(config).buildMetadata().bomDependencies().contains("spring-beans", "spring-boot", + "spring-boot-autoconfigure", "spring-boot-jarmode-layertools", "spring-context", "spring-core", + "spring-web"); + ImageAssertions.assertThat(config).buildMetadata().bomJavaVersion("jre").startsWith(javaMajorVersion()); + ImageAssertions.assertThat(config).buildMetadata().processOfType("web").extracting("command", "args") + .containsExactly("java", Collections.singletonList("org.springframework.boot.loader.WarLauncher")); + ImageAssertions.assertThat(config).buildMetadata().processOfType("executable-jar") + .extracting("command", "args") + .containsExactly("java", Collections.singletonList("org.springframework.boot.loader.WarLauncher")); + assertImageLayersMatchLayersIndex(imageReference, config); + } + finally { + removeImage(imageReference); + } + } + + @Test + void plainWarApp() throws Exception { + writeMainClass(); + writeServletInitializerClass(); + String imageName = "paketo-integration/" + this.gradleBuild.getProjectDir().getName(); + ImageReference imageReference = ImageReference.of(ImageName.of(imageName)); + BuildResult result = buildImage(imageName); + assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + try (GenericContainer container = new GenericContainer<>(imageName).withExposedPorts(8080)) { + container.waitingFor(Wait.forHttp("/test")).start(); + ContainerConfig config = container.getContainerInfo().getConfig(); + ImageAssertions.assertThat(config).buildMetadata().buildpacks().containsExactly( + "paketo-buildpacks/ca-certificates", "paketo-buildpacks/bellsoft-liberica", + "paketo-buildpacks/apache-tomcat", "paketo-buildpacks/dist-zip", "paketo-buildpacks/spring-boot"); + ImageAssertions.assertThat(config).buildMetadata().bomJavaVersion("jre").startsWith(javaMajorVersion()); + ImageAssertions.assertThat(config).buildMetadata().processOfType("web").extracting("command", "args") + .containsExactly("catalina.sh", Collections.singletonList("run")); + ImageAssertions.assertThat(config).buildMetadata().processOfType("tomcat").extracting("command", "args") + .containsExactly("catalina.sh", Collections.singletonList("run")); + DigestCapturingCondition digests = new DigestCapturingCondition(); + ImageAssertions.assertThat(config).lifecycleMetadata().appLayerShas().haveExactly(1, digests); + ImageAssertions.assertThat(imageReference).hasLayer(digests.getDigest(0)).entries() + .contains("WEB-INF/classes/example/ExampleApplication.class", + "WEB-INF/classes/example/HelloController.class", "META-INF/MANIFEST.MF") + .anyMatch((s) -> s.startsWith("WEB-INF/lib/spring-boot-")) + .anyMatch((s) -> s.startsWith("WEB-INF/lib/spring-core-")) + .anyMatch((s) -> s.startsWith("WEB-INF/lib/spring-web-")); + } + finally { + removeImage(imageReference); + } + } + + public BuildResult buildImage(String imageName, String... arguments) { + String[] buildImageArgs = { "bootBuildImage", "--imageName=" + imageName, "--pullPolicy=IF_NOT_PRESENT" }; + String[] args = StringUtils.concatenateStringArrays(arguments, buildImageArgs); + return this.gradleBuild.build(args); + } + + private void writeMainClass() throws IOException { + writeProjectFile("ExampleApplication.java", (writer) -> { + writer.println("package example;"); + writer.println(); + writer.println("import org.springframework.boot.SpringApplication;"); + writer.println("import org.springframework.boot.autoconfigure.SpringBootApplication;"); + writer.println("import org.springframework.stereotype.Controller;"); + writer.println("import org.springframework.web.bind.annotation.RequestMapping;"); + writer.println("import org.springframework.web.bind.annotation.ResponseBody;"); + writer.println(); + writer.println("@SpringBootApplication"); + writer.println("public class ExampleApplication {"); + writer.println(); + writer.println(" public static void main(String[] args) {"); + writer.println(" SpringApplication.run(ExampleApplication.class, args);"); + writer.println(" }"); + writer.println(); + writer.println("}"); + writer.println(); + writer.println("@Controller"); + writer.println("class HelloController {"); + writer.println(); + writer.println(" @RequestMapping(\"/test\")"); + writer.println(" @ResponseBody"); + writer.println(" String home() {"); + writer.println(" return \"Hello, world!\";"); + writer.println(" }"); + writer.println(); + writer.println("}"); + }); + } + + private void writeServletInitializerClass() throws IOException { + writeProjectFile("ServletInitializer.java", (writer) -> { + writer.println("package example;"); + writer.println(); + writer.println("import org.springframework.boot.builder.SpringApplicationBuilder;"); + writer.println("import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;"); + writer.println(); + writer.println("public class ServletInitializer extends SpringBootServletInitializer {"); + writer.println(); + writer.println(" @Override"); + writer.println(" protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {"); + writer.println(" return application.sources(ExampleApplication.class);"); + writer.println(" }"); + writer.println(); + writer.println("}"); + }); + } + + private void writeProjectFile(String fileName, Consumer consumer) throws IOException { + File examplePackage = new File(this.gradleBuild.getProjectDir(), "src/main/java/example"); + examplePackage.mkdirs(); + File main = new File(examplePackage, fileName); + try (PrintWriter writer = new PrintWriter(new FileWriter(main))) { + consumer.accept(writer); + } + } + + private void assertLabelsMatchManifestAttributes(ContainerConfig config) throws IOException { + JarFile jarFile = new JarFile(projectArchiveFile()); + Attributes attributes = jarFile.getManifest().getMainAttributes(); + ImageAssertions.assertThat(config).label("org.springframework.boot.version") + .isEqualTo(attributes.getValue("Spring-Boot-Version")); + ImageAssertions.assertThat(config).label("org.opencontainers.image.title") + .isEqualTo(attributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE)); + ImageAssertions.assertThat(config).label("org.opencontainers.image.version") + .isEqualTo(attributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION)); + } + + private void assertImageLayersMatchLayersIndex(ImageReference imageReference, ContainerConfig config) + throws IOException { + DigestCapturingCondition digests = new DigestCapturingCondition(); + ImageAssertions.assertThat(config).lifecycleMetadata().appLayerShas().haveExactly(5, digests); + LayersIndex layersIndex = LayersIndex.fromArchiveFile(projectArchiveFile()); + ImageAssertions.assertThat(imageReference).hasLayer(digests.getDigest(0)).entries() + .allMatch((entry) -> startsWithOneOf(entry, layersIndex.getLayer("dependencies"))); + ImageAssertions.assertThat(imageReference).hasLayer(digests.getDigest(1)).entries() + .allMatch((entry) -> startsWithOneOf(entry, layersIndex.getLayer("spring-boot-loader"))); + ImageAssertions.assertThat(imageReference).hasLayer(digests.getDigest(2)).entries() + .allMatch((entry) -> startsWithOneOf(entry, layersIndex.getLayer("snapshot-dependencies"))); + ImageAssertions.assertThat(imageReference).hasLayer(digests.getDigest(3)).entries() + .allMatch((entry) -> startsWithOneOf(entry, layersIndex.getLayer("application"))); + ImageAssertions.assertThat(imageReference).hasLayer(digests.getDigest(4)).entries() + .allMatch((entry) -> entry.contains("lib/spring-cloud-bindings-")); + } + + private File projectArchiveFile() { + return new File(this.gradleBuild.getProjectDir(), "build/libs").listFiles()[0]; + } + + private String javaMajorVersion() { + String javaVersion = System.getProperty("java.version"); + if (javaVersion.startsWith("1.")) { + return javaVersion.substring(2, 3); + } + else { + int firstDotIndex = javaVersion.indexOf("."); + if (firstDotIndex != -1) { + return javaVersion.substring(0, firstDotIndex); + } + } + return javaVersion; + } + + private boolean startsWithOneOf(String actual, List expectedPrefixes) { + for (String prefix : expectedPrefixes) { + if (actual.startsWith(prefix)) { + return true; + } + } + return false; + } + + private void removeImage(ImageReference image) throws IOException { + new DockerApi().image().remove(image, false); + } + + private static class DigestCapturingCondition extends Condition { + + private static List digests; + + DigestCapturingCondition() { + super(predicate(), "a value starting with 'sha256:'"); + } + + private static Predicate predicate() { + digests = new ArrayList<>(); + return (sha) -> { + digests.add(sha.toString()); + return sha.toString().startsWith("sha256:"); + }; + } + + String getDigest(int index) { + return digests.get(index); + } + + } + +} diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-bootDistZipJarApp.gradle b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-bootDistZipJarApp.gradle new file mode 100644 index 0000000000..a74b6cb9e8 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-bootDistZipJarApp.gradle @@ -0,0 +1,33 @@ +plugins { + id 'org.springframework.boot' version '{bootVersion}' + id 'io.spring.dependency-management' version '{dependencyManagementPluginVersion}' + id 'java' + id 'application' +} + +repositories { + mavenCentral() + maven { url 'https://repo.spring.io/milestone' } + maven { url 'https://repo.spring.io/snapshot' } +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}") +} + +bootJar { + manifest { + attributes( + 'Implementation-Version': '1.0.0', + 'Implementation-Title': "Paketo Test" + ) + } +} + +application { + mainClass = 'example.ExampleApplication' +} + +bootBuildImage { + archiveFile = new File("${buildDir}/distributions/${project.name}-boot.zip") +} \ No newline at end of file diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-executableWarApp.gradle b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-executableWarApp.gradle new file mode 100644 index 0000000000..e7892dd5e7 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-executableWarApp.gradle @@ -0,0 +1,26 @@ +plugins { + id 'org.springframework.boot' version '{bootVersion}' + id 'io.spring.dependency-management' version '{dependencyManagementPluginVersion}' + id 'java' + id 'war' +} + +repositories { + mavenCentral() + maven { url 'https://repo.spring.io/milestone' } + maven { url 'https://repo.spring.io/snapshot' } +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}") + providedRuntime("org.springframework.boot:spring-boot-starter-tomcat:{bootVersion}") +} + +bootWar { + manifest { + attributes( + 'Implementation-Version': '1.0.0', + 'Implementation-Title': "Paketo Test" + ) + } +} diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-plainDistZipJarApp.gradle b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-plainDistZipJarApp.gradle new file mode 100644 index 0000000000..fb331a1704 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-plainDistZipJarApp.gradle @@ -0,0 +1,33 @@ +plugins { + id 'org.springframework.boot' version '{bootVersion}' + id 'io.spring.dependency-management' version '{dependencyManagementPluginVersion}' + id 'java' + id 'application' +} + +repositories { + mavenCentral() + maven { url 'https://repo.spring.io/milestone' } + maven { url 'https://repo.spring.io/snapshot' } +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}") +} + +bootJar { + manifest { + attributes( + 'Implementation-Version': '1.0.0', + 'Implementation-Title': "Paketo Test" + ) + } +} + +application { + mainClass = 'example.ExampleApplication' +} + +bootBuildImage { + archiveFile = new File("${buildDir}/distributions/${project.name}.zip") +} \ No newline at end of file diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-plainWarApp.gradle b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-plainWarApp.gradle new file mode 100644 index 0000000000..3a40cc9271 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests-plainWarApp.gradle @@ -0,0 +1,26 @@ +plugins { + id 'org.springframework.boot' version '{bootVersion}' + id 'io.spring.dependency-management' version '{dependencyManagementPluginVersion}' + id 'java' + id 'war' +} + +repositories { + mavenCentral() + maven { url 'https://repo.spring.io/milestone' } + maven { url 'https://repo.spring.io/snapshot' } +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}") + providedRuntime("org.springframework.boot:spring-boot-starter-tomcat:{bootVersion}") +} + +war { + enabled = true + archiveClassifier.set('plain') +} + +bootBuildImage { + archiveFile = war.archiveFile +} diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests.gradle b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests.gradle new file mode 100644 index 0000000000..305b7f3af2 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/PaketoBuilderTests.gradle @@ -0,0 +1,24 @@ +plugins { + id 'org.springframework.boot' version '{bootVersion}' + id 'io.spring.dependency-management' version '{dependencyManagementPluginVersion}' + id 'java' +} + +repositories { + mavenCentral() + maven { url 'https://repo.spring.io/milestone' } + maven { url 'https://repo.spring.io/snapshot' } +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}") +} + +bootJar { + manifest { + attributes( + 'Implementation-Version': '1.0.0', + 'Implementation-Title': "Paketo Test" + ) + } +} \ No newline at end of file diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/settings.gradle b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/settings.gradle new file mode 100644 index 0000000000..fb0915aec8 --- /dev/null +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/resources/org/springframework/boot/image/paketo/settings.gradle @@ -0,0 +1,7 @@ +pluginManagement { + repositories { + maven { url 'https://repo.spring.io/milestone' } + maven { url 'https://repo.spring.io/snapshot' } + gradlePluginPortal() + } +} \ No newline at end of file diff --git a/src/checkstyle/checkstyle-suppressions.xml b/src/checkstyle/checkstyle-suppressions.xml index c9553cb27b..bdbeedc22d 100644 --- a/src/checkstyle/checkstyle-suppressions.xml +++ b/src/checkstyle/checkstyle-suppressions.xml @@ -45,7 +45,9 @@ + +