From 22d250f06f14deed7fc9c41b9b873d9a5277b031 Mon Sep 17 00:00:00 2001 From: Ioannis Canellos Date: Thu, 9 Mar 2023 11:58:10 +0200 Subject: [PATCH] fix: imageBuild / imagePush dependency handling --- .../io/quarkus/gradle/tasks/ImageBuild.java | 39 +++------ .../io/quarkus/gradle/tasks/ImagePush.java | 6 +- .../io/quarkus/gradle/tasks/ImageTask.java | 80 ++++++++++++++++++- 3 files changed, 92 insertions(+), 33 deletions(-) diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImageBuild.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImageBuild.java index 54af7a114d870..187c3bd28040c 100644 --- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImageBuild.java +++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImageBuild.java @@ -1,29 +1,21 @@ package io.quarkus.gradle.tasks; -import java.util.List; +import java.util.Collections; import java.util.Map; -import java.util.stream.Collectors; +import java.util.Optional; import javax.inject.Inject; -import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.options.Option; public abstract class ImageBuild extends ImageTask { - public enum Builder { - docker, - jib, - buildpack, - openshift - } - - Builder builder = Builder.docker; + Optional builder = Optional.empty(); @Option(option = "builder", description = "The container image extension to use for building the image (e.g. docker, jib, buildpack, openshift).") public void setBuilder(Builder builder) { - this.builder = builder; + this.builder = Optional.of(builder); } @Inject @@ -33,24 +25,13 @@ public ImageBuild(QuarkusBuildConfiguration buildConfiguration) { @Override public Map forcedProperties() { - return Map.of("quarkus.container-image.build", "true", - "quarkus.container-image.builder", builder.name()); + return builder().map(b -> Map.of(QUARKUS_CONTAINER_IMAGE_BUILD, "true", QUARKUS_CONTAINER_IMAGE_BUILDER, b.name())) + .orElse(Collections.emptyMap()); } - @TaskAction - public void checkRequiredExtensions() { - // Currently forcedDependencies() is not implemented for gradle. - // So, let's give users a meaningful warning message. - String requiredExtension = "quarkus-container-image-" + builder.name(); - String requiredDependency = requiredExtension + "-deployment"; - List projectDependencies = getProject().getConfigurations().stream().flatMap(c -> c.getDependencies().stream()) - .map(d -> d.getName()) - .collect(Collectors.toList()); - - if (!projectDependencies.contains(requiredDependency)) { - getProject().getLogger().warn("Task: {} requires extensions: {}", getName(), requiredDependency); - getProject().getLogger().warn("To add the extensions to the project you can run the following command:"); - getProject().getLogger().warn("\tgradle addExtension --extensions={}", requiredExtension); - } + public Optional builder() { + return builder + .or(() -> builderFromSystemProperties()) + .or(() -> availableBuilders().stream().findFirst()); } } diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImagePush.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImagePush.java index e1fe6732a19bf..fcb633ab790da 100644 --- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImagePush.java +++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImagePush.java @@ -19,7 +19,7 @@ public ImagePush(QuarkusBuildConfiguration buildConfiguration) { @Override public Map forcedProperties() { - return Map.of("quarkus.container-image.push", "true"); + return Map.of(QUARKUS_CONTAINER_IMAGE_PUSH, "true"); } @TaskAction @@ -27,11 +27,11 @@ public void checkRequiredExtensions() { List containerImageExtensions = getProject().getConfigurations().stream() .flatMap(c -> c.getDependencies().stream()) .map(d -> d.getName()) - .filter(n -> n.startsWith("quarkus-container-image")) + .filter(n -> n.startsWith(QUARKUS_CONTAINER_IMAGE_PREFIX)) .map(n -> n.replaceAll("-deployment$", "")) .collect(Collectors.toList()); - List extensions = Arrays.stream(ImageBuild.Builder.values()).map(b -> "quarkus-container-image-" + b.name()) + List extensions = Arrays.stream(ImageBuild.Builder.values()).map(b -> QUARKUS_CONTAINER_IMAGE_PREFIX + b.name()) .collect(Collectors.toList()); if (containerImageExtensions.isEmpty()) { diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImageTask.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImageTask.java index 8f41049fe4515..d015137f6a8fd 100644 --- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImageTask.java +++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/ImageTask.java @@ -1,16 +1,94 @@ package io.quarkus.gradle.tasks; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.gradle.api.tasks.StopExecutionException; +import org.gradle.api.tasks.TaskAction; public abstract class ImageTask extends QuarkusBuildProviderTask { + static final String QUARKUS_CONTAINER_IMAGE_PREFIX = "quarkus-container-image-"; + static final String QUARKUS_CONTAINER_IMAGE_BUILD = "quarkus.container-image.build"; + static final String QUARKUS_CONTAINER_IMAGE_PUSH = "quarkus.container-image.push"; + static final String QUARKUS_CONTAINER_IMAGE_BUILDER = "quarkus.container-image.builder"; + + static final Map BUILDERS = new HashMap<>(); + static { + for (Builder builder : Builder.values()) { + BUILDERS.put(builder.name(), builder); + } + } + + enum Builder { + docker, + jib, + buildpack, + openshift + } + public ImageTask(QuarkusBuildConfiguration buildConfiguration, String description) { super(buildConfiguration, description); } @Override public Map forcedProperties() { - return Map.of("quarkus.container-image.build", "true"); + return Map.of(QUARKUS_CONTAINER_IMAGE_BUILD, "true"); + } + + Optional builder() { + return builderFromSystemProperties(); + } + + Optional builderFromSystemProperties() { + return Optional.ofNullable(System.getProperty(QUARKUS_CONTAINER_IMAGE_BUILDER)) + .filter(BUILDERS::containsKey) + .map(BUILDERS::get); + } + + List availableBuilders() { + return getProject().getConfigurations().stream().flatMap(c -> c.getDependencies().stream()) + .map(d -> d.getName()) + .filter(n -> n.startsWith(QUARKUS_CONTAINER_IMAGE_PREFIX)) + .map(n -> n.replace(QUARKUS_CONTAINER_IMAGE_PREFIX, "")) + .filter(BUILDERS::containsKey) + .map(BUILDERS::get) + .collect(Collectors.toList()); + } + + @TaskAction + public void checkRequiredExtensions() { + // Currently forcedDependencies() is not implemented for gradle. + // So, let's give users a meaningful warning message. + List availableBuidlers = availableBuilders(); + Optional missingBuilder = builder().filter(Predicate.not(availableBuidlers::contains)); + missingBuilder.map(builder -> QUARKUS_CONTAINER_IMAGE_PREFIX + builder.name()).ifPresent(missingDependency -> { + getProject().getLogger().warn("Task: {} requires extensions: {}", getName(), missingDependency); + getProject().getLogger().warn("To add the extensions to the project you can run the following command:"); + getProject().getLogger().warn("\tgradle addExtension --extensions={}", missingDependency); + abort("Aborting."); + }); + + if (!missingBuilder.isPresent() && availableBuidlers.isEmpty()) { + getProject().getLogger().warn("Task: {} requires on of extensions: {}", getName(), + Arrays.stream(Builder.values()).map(Builder::name).collect(Collectors.joining(", ", "[", "]"))); + getProject().getLogger().warn("To add the extensions to the project you can run the following command:"); + getProject().getLogger().warn("\tgradle addExtension --extensions="); + abort("Aborting."); + } + } + + void abort(String message, Object... args) { + getProject().getLogger().warn(message, args); + getProject().getTasks().stream().filter(t -> t != this).forEach(t -> { + t.setEnabled(false); + }); + throw new StopExecutionException(); } }