Skip to content

Commit cd44113

Browse files
Warn when image building workspace directories cannot be deleted
When the `buildWorkspace` location in the `spring-boot:build-image` Maven goal or `bootBuildImage` Gradle task is configured to use a local bind source, the location is passed to the CNB lifecycle without further processing by Spring Boot. The lifecycle is in control of creating any files in the specified location. Spring Boot tries to remove the directories at the specified location after an image is successfully created, but should not fail the image build if the lifecycle has created files or directories with permissions that keep them from being deleted successfully. Fixes gh-40760
1 parent 524424b commit cd44113

File tree

5 files changed

+26
-14
lines changed

5 files changed

+26
-14
lines changed

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/AbstractBuildLog.java

+11
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ public void taggedImage(ImageReference tag) {
102102
log();
103103
}
104104

105+
@Override
106+
public void failedCleaningWorkDir(Cache cache, Exception exception) {
107+
StringBuilder message = new StringBuilder("Warning: Working location " + cache + " could not be cleaned");
108+
if (exception != null) {
109+
message.append(": ").append(exception.getMessage());
110+
}
111+
log();
112+
log(message.toString());
113+
log();
114+
}
115+
105116
private String getDigest(Image image) {
106117
List<String> digests = image.getDigests();
107118
return (digests.isEmpty() ? "" : digests.get(0));

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildLog.java

+7
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ public interface BuildLog {
114114
*/
115115
void taggedImage(ImageReference tag);
116116

117+
/**
118+
* Log that a cache cleanup step was not completed successfully.
119+
* @param cache the cache
120+
* @param exception any exception that caused the failure
121+
*/
122+
void failedCleaningWorkDir(Cache cache, Exception exception);
123+
117124
/**
118125
* Factory method that returns a {@link BuildLog} the outputs to {@link System#out}.
119126
* @return a build log instance that logs to system out

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Lifecycle.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -311,20 +311,20 @@ private void deleteCache(Cache cache) throws IOException {
311311
deleteVolume(cache.getVolume().getVolumeName());
312312
}
313313
if (cache.getBind() != null) {
314-
deleteBind(cache.getBind().getSource());
314+
deleteBind(cache.getBind());
315315
}
316316
}
317317

318318
private void deleteVolume(VolumeName name) throws IOException {
319319
this.docker.volume().delete(name, true);
320320
}
321321

322-
private void deleteBind(String source) {
322+
private void deleteBind(Cache.Bind bind) {
323323
try {
324-
FileSystemUtils.deleteRecursively(Path.of(source));
324+
FileSystemUtils.deleteRecursively(Path.of(bind.getSource()));
325325
}
326326
catch (IOException ex) {
327-
throw new IllegalStateException("Error cleaning bind mount directory '" + source + "'", ex);
327+
this.log.failedCleaningWorkDir(bind, ex);
328328
}
329329
}
330330

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import org.apache.commons.compress.utils.IOUtils;
3737
import org.gradle.testkit.runner.BuildResult;
3838
import org.gradle.testkit.runner.TaskOutcome;
39-
import org.junit.jupiter.api.Disabled;
4039
import org.junit.jupiter.api.TestTemplate;
4140
import org.junit.jupiter.api.condition.EnabledOnOs;
4241
import org.junit.jupiter.api.condition.OS;
@@ -301,10 +300,8 @@ void buildsImageWithVolumeCaches() throws IOException {
301300
}
302301

303302
@TestTemplate
304-
@EnabledOnOs(value = OS.LINUX,
305-
disabledReason = "Works with Docker Engine on Linux but is not reliable with "
306-
+ "Docker Desktop on other OSs")
307-
@Disabled("gh-40760")
303+
@EnabledOnOs(value = OS.LINUX, disabledReason = "Works with Docker Engine on Linux but is not reliable with "
304+
+ "Docker Desktop on other OSs")
308305
void buildsImageWithBindCaches() throws IOException {
309306
writeMainClass();
310307
writeLongNameResource();

spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import java.util.Random;
2626
import java.util.stream.IntStream;
2727

28-
import org.junit.jupiter.api.Disabled;
2928
import org.junit.jupiter.api.TestTemplate;
3029
import org.junit.jupiter.api.condition.EnabledOnOs;
3130
import org.junit.jupiter.api.condition.OS;
@@ -402,10 +401,8 @@ void whenBuildImageIsInvokedWithVolumeCaches(MavenBuild mavenBuild) {
402401
}
403402

404403
@TestTemplate
405-
@EnabledOnOs(value = OS.LINUX,
406-
disabledReason = "Works with Docker Engine on Linux but is not reliable with "
407-
+ "Docker Desktop on other OSs")
408-
@Disabled("gh-40760")
404+
@EnabledOnOs(value = OS.LINUX, disabledReason = "Works with Docker Engine on Linux but is not reliable with "
405+
+ "Docker Desktop on other OSs")
409406
void whenBuildImageIsInvokedWithBindCaches(MavenBuild mavenBuild) {
410407
String testBuildId = randomString();
411408
mavenBuild.project("build-image-bind-caches")

0 commit comments

Comments
 (0)