diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/dockerTest/java/org/springframework/boot/maven/BuildImageTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/dockerTest/java/org/springframework/boot/maven/BuildImageTests.java index ea58f5598d9c..140be1a6e0ab 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/dockerTest/java/org/springframework/boot/maven/BuildImageTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/dockerTest/java/org/springframework/boot/maven/BuildImageTests.java @@ -96,7 +96,7 @@ void whenBuildImageIsInvokedOnTheCommandLineWithoutRepackageTheArchiveIsRepackag } @TestTemplate - void whenBuildImageIsInvokedWithClassifierWithoutRepackageTheArchiveIsRepackagedOnTheFly(MavenBuild mavenBuild) { + void whenPackageIsInvokedWithClassifierTheOriginalArchiveIsFound(MavenBuild mavenBuild) { mavenBuild.project("dockerTest", "build-image-classifier") .goals("package") .systemProperty("spring-boot.build-image.pullPolicy", "IF_NOT_PRESENT") @@ -115,6 +115,26 @@ void whenBuildImageIsInvokedWithClassifierWithoutRepackageTheArchiveIsRepackaged }); } + @TestTemplate + void whenBuildImageIsInvokedWithClassifierAndRepackageTheOriginalArchiveIsFound(MavenBuild mavenBuild) { + mavenBuild.project("dockerTest", "build-image-fork-classifier") + .goals("spring-boot:build-image") + .systemProperty("spring-boot.build-image.pullPolicy", "IF_NOT_PRESENT") + .prepare(this::writeLongNameResource) + .execute((project) -> { + File jar = new File(project, "target/build-image-fork-classifier-0.0.1.BUILD-SNAPSHOT.jar"); + assertThat(jar).isFile(); + File classifier = new File(project, "target/build-image-fork-classifier-0.0.1.BUILD-SNAPSHOT-exec.jar"); + assertThat(classifier).exists(); + assertThat(buildLog(project)).contains("Building image") + .contains("docker.io/library/build-image-fork-classifier:0.0.1.BUILD-SNAPSHOT") + .contains("---> Test Info buildpack building") + .contains("---> Test Info buildpack done") + .contains("Successfully built image"); + removeImage("build-image-fork-classifier", "0.0.1.BUILD-SNAPSHOT"); + }); + } + @TestTemplate void whenBuildImageIsInvokedWithClassifierSourceWithoutRepackageTheArchiveIsRepackagedOnTheFly( MavenBuild mavenBuild) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/dockerTest/projects/build-image-fork-classifier/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/dockerTest/projects/build-image-fork-classifier/pom.xml new file mode 100644 index 000000000000..37e4caa7d4c7 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/dockerTest/projects/build-image-fork-classifier/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + org.springframework.boot.maven.it + build-image-fork-classifier + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + @java.version@ + @java.version@ + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + repackage + + repackage + + + + + exec + + ghcr.io/spring-io/spring-boot-cnb-test-builder:0.0.1 + + + + + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/dockerTest/projects/build-image-fork-classifier/src/main/java/org/test/SampleApplication.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/dockerTest/projects/build-image-fork-classifier/src/main/java/org/test/SampleApplication.java new file mode 100644 index 000000000000..ab4c6f35e678 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/dockerTest/projects/build-image-fork-classifier/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.test; + +public class SampleApplication { + + public static void main(String[] args) throws Exception { + System.out.println("Launched"); + synchronized(args) { + args.wait(); // Prevent exit" + } + } + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java index 3d737fa7c219..b5668f8180fe 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java @@ -298,8 +298,8 @@ private TarArchive getApplicationContent(Owner owner, Libraries libraries, Image } private File getArchiveFile() { - // We can use 'project.getArtifact().getFile()' because that was done in a - // forked lifecycle and is now null + // We can't use 'project.getArtifact().getFile()' because package can be done in a + // forked lifecycle and will be null File archiveFile = getTargetFile(this.finalName, this.classifier, this.sourceDirectory); if (!archiveFile.exists()) { archiveFile = getSourceArtifact(this.classifier).getFile(); @@ -315,9 +315,17 @@ private File getArchiveFile() { * @return the file to use to back up the original source */ private File getBackupFile() { - Artifact source = getSourceArtifact(null); - if (this.classifier != null && !this.classifier.equals(source.getClassifier())) { - return source.getFile(); + // We can't use 'project.getAttachedArtifacts()' because package can be done in a + // forked lifecycle and will be null + if (this.classifier != null) { + File backupFile = getTargetFile(this.finalName, null, this.sourceDirectory); + if (backupFile.exists()) { + return backupFile; + } + Artifact source = getSourceArtifact(null); + if (!this.classifier.equals(source.getClassifier())) { + return source.getFile(); + } } return null; }