diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/AbstractBuildLog.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/AbstractBuildLog.java index 2d3c49898eb4..9cf1de13e3db 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/AbstractBuildLog.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/AbstractBuildLog.java @@ -128,6 +128,13 @@ public void sensitiveTargetBindingDetected(Binding binding) { log(); } + @Override + public void stackIdsDoNotMatch(String runImageStackId, String builderImageStackId) { + log("Warning: Run image stack '%s' does not match builder stack '%s'. Stack IDs are deprecated, but the images may not be compatible." + .formatted(runImageStackId, builderImageStackId)); + log(); + } + private String getDigest(Image image) { List digests = image.getDigests(); return (digests.isEmpty() ? "" : digests.get(0)); diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildLog.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildLog.java index ad7fbd61d5a8..01597ea4f2c3 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildLog.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildLog.java @@ -135,6 +135,16 @@ Consumer pullingImage(ImageReference imageReference, @Nullab */ void sensitiveTargetBindingDetected(Binding binding); + /** + * Log that the stack ID of the run image does not match the stack ID of the builder + * image. + * @param runImageStackId the stack ID of the run image + * @param builderImageStackId the stack ID of the builder image + * @since 4.0.8 + */ + default void stackIdsDoNotMatch(String runImageStackId, String builderImageStackId) { + } + /** * Factory method that returns a {@link BuildLog} the outputs to {@link System#out}. * @return a build log instance that logs to system out diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Builder.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Builder.java index 0657b314db05..3532cfc24725 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Builder.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Builder.java @@ -120,7 +120,7 @@ public void build(BuildRequest request) throws DockerEngineException, IOExceptio request = request.withRunImage(request.getRunImage().withDigest(runImage.getPrimaryDigest())); runImage = imageFetcher.fetchImage(ImageType.RUNNER, request.getRunImage(), platform); } - assertStackIdsMatch(runImage, builderImage); + warnIfStackIdsDoNotMatch(runImage, builderImage); BuildOwner buildOwner = BuildOwner.fromEnv(builderImage.getConfig().getEnv()); BuildpackLayersMetadata buildpackLayersMetadata = BuildpackLayersMetadata.fromImage(builderImage); Buildpacks buildpacks = getBuildpacks(request, imageFetcher, platform, builderMetadata, @@ -159,12 +159,11 @@ private ImageReference getRunImageReference(BuilderMetadata metadata) { return ImageReference.of(runImageName).inTaggedOrDigestForm(); } - private void assertStackIdsMatch(Image runImage, Image builderImage) { + private void warnIfStackIdsDoNotMatch(Image runImage, Image builderImage) { StackId runImageStackId = StackId.fromImage(runImage); StackId builderImageStackId = StackId.fromImage(builderImage); - if (runImageStackId.hasId() && builderImageStackId.hasId()) { - Assert.state(runImageStackId.equals(builderImageStackId), () -> "Run image stack '" + runImageStackId - + "' does not match builder stack '" + builderImageStackId + "'"); + if (runImageStackId.hasId() && builderImageStackId.hasId() && !runImageStackId.equals(builderImageStackId)) { + this.log.stackIdsDoNotMatch(runImageStackId.toString(), builderImageStackId.toString()); } } diff --git a/buildpack/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java b/buildpack/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java index 56ea417fd9e9..3c38c55cf62c 100644 --- a/buildpack/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java +++ b/buildpack/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java @@ -447,7 +447,7 @@ void buildInvokesBuilderWithPlatform() throws Exception { } @Test - void buildWhenStackIdDoesNotMatchThrowsException() throws Exception { + void buildWhenStackIdDoesNotMatchLogsWarning() throws Exception { TestPrintStream out = new TestPrintStream(); DockerApi docker = mockDockerApi(); Image builderImage = loadImage("image.json"); @@ -458,9 +458,11 @@ void buildWhenStackIdDoesNotMatchThrowsException() throws Exception { .willAnswer(withPulledImage(runImage)); Builder builder = new Builder(BuildLog.to(out), docker, null); BuildRequest request = getTestRequest(); - assertThatIllegalStateException().isThrownBy(() -> builder.build(request)) - .withMessage( - "Run image stack 'org.cloudfoundry.stacks.cfwindowsfs3' does not match builder stack 'io.buildpacks.stacks.bionic'"); + builder.build(request); + assertThat(out.toString()).contains( + "Warning: Run image stack 'org.cloudfoundry.stacks.cfwindowsfs3' does not match builder stack 'io.buildpacks.stacks.bionic'"); + assertThat(out.toString()).contains("Running creator"); + assertThat(out.toString()).contains("Successfully built image 'docker.io/library/my-application:latest'"); } @Test