diff --git a/deployment/src/main/java/io/quarkus/jgit/deployment/GiteaContainer.java b/deployment/src/main/java/io/quarkus/jgit/deployment/GiteaContainer.java index bd1fbf0..9e7c41d 100644 --- a/deployment/src/main/java/io/quarkus/jgit/deployment/GiteaContainer.java +++ b/deployment/src/main/java/io/quarkus/jgit/deployment/GiteaContainer.java @@ -3,7 +3,6 @@ import static org.testcontainers.containers.wait.strategy.Wait.forListeningPorts; import java.io.IOException; -import java.util.Base64; import org.jboss.logging.Logger; import org.testcontainers.containers.GenericContainer; @@ -27,8 +26,10 @@ class GiteaContainer extends GenericContainer { withEnv("GITEA__security__INSTALL_LOCK", "true"); withEnv("GITEA__server__DISABLE_SSH", "true"); withExposedPorts(HTTP_PORT); + withReuse(devServiceConfig.reuse()); waitingFor(forListeningPorts(HTTP_PORT)); - withReuse(true); + // Needed for podman (see /~https://github.com/testcontainers/testcontainers-java/issues/7310) + withStartupAttempts(2); devServiceConfig.httpPort().ifPresent(port -> addFixedExposedPort(port, HTTP_PORT)); if (devServiceConfig.showLogs()) { withLogConsumer(new JBossLoggingConsumer(log)); @@ -69,34 +70,6 @@ private void createAdminUser() throws IOException, InterruptedException { } } - private void createRepository() throws IOException, InterruptedException { - String[] cmd = { - "/usr/bin/curl", - "-X", - "POST", - "http://localhost:3000/api/v1/user/repos", - "-H", - "'Accept: application/json'", - "-H", - "'Authorization: Basic " + getBasicAuth() + "'", - "-H", - "'Content-Type: application/json'", - "-d", - "'{\"auto_init\":true,\"default_branch\":\"main\",\"name\":\"hello-world\",\"private\":false,\"readme\":\"Default\"}'" - }; - log.info(String.join(" ", cmd)); - ExecResult execResult = execInContainer(cmd); - log.info(execResult.getStdout()); - if (execResult.getExitCode() != 0) { - throw new RuntimeException("Failed to create repository: " + execResult.getStderr()); - } - } - - private String getBasicAuth() { - String auth = devServiceConfig.adminUsername() + ":" + devServiceConfig.adminPassword(); - return Base64.getEncoder().encodeToString(auth.getBytes()); - } - public String getHttpUrl() { return "http://" + getHost() + ":" + getMappedPort(HTTP_PORT); } diff --git a/deployment/src/main/java/io/quarkus/jgit/deployment/JGitBuildTimeConfig.java b/deployment/src/main/java/io/quarkus/jgit/deployment/JGitBuildTimeConfig.java index 99d98f8..4207d5a 100644 --- a/deployment/src/main/java/io/quarkus/jgit/deployment/JGitBuildTimeConfig.java +++ b/deployment/src/main/java/io/quarkus/jgit/deployment/JGitBuildTimeConfig.java @@ -46,10 +46,10 @@ interface DevService { @WithDefault("quarkus") String adminPassword(); - // /** - // * Create Hello World repository? - // */ - // @WithDefault("true") - // boolean createRepository(); + /** + * Should the container be reused? + */ + @WithDefault("false") + boolean reuse(); } } diff --git a/deployment/src/main/java/io/quarkus/jgit/deployment/JGitDevServicesProcessor.java b/deployment/src/main/java/io/quarkus/jgit/deployment/JGitDevServicesProcessor.java new file mode 100644 index 0000000..b23e31e --- /dev/null +++ b/deployment/src/main/java/io/quarkus/jgit/deployment/JGitDevServicesProcessor.java @@ -0,0 +1,54 @@ +package io.quarkus.jgit.deployment; + +import java.util.Map; +import java.util.function.BooleanSupplier; + +import org.jboss.logging.Logger; + +import io.quarkus.deployment.IsNormal; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.CuratedApplicationShutdownBuildItem; +import io.quarkus.deployment.builditem.DevServicesResultBuildItem; +import io.quarkus.deployment.builditem.DevServicesResultBuildItem.RunningDevService; +import io.quarkus.deployment.dev.devservices.GlobalDevServicesConfig; +import io.quarkus.devservices.common.ContainerShutdownCloseable; + +public class JGitDevServicesProcessor { + + private static final Logger log = Logger.getLogger(JGitDevServicesProcessor.class); + static volatile RunningDevService devService; + + @BuildStep(onlyIfNot = IsNormal.class, onlyIf = { GlobalDevServicesConfig.Enabled.class, DevServicesEnabled.class }) + DevServicesResultBuildItem createContainer(JGitBuildTimeConfig config, + CuratedApplicationShutdownBuildItem closeBuildItem) { + if (devService != null) { + // only produce DevServicesResultBuildItem when the dev service first starts. + return null; + } + var gitServer = new GiteaContainer(config.devservices()); + gitServer.start(); + String httpUrl = gitServer.getHttpUrl(); + log.infof("Gitea HTTP URL: %s", httpUrl); + Map configOverrides = Map.of("quarkus.jgit.devservices.http-url", httpUrl); + + ContainerShutdownCloseable closeable = new ContainerShutdownCloseable(gitServer, JGitProcessor.FEATURE); + closeBuildItem.addCloseTask(closeable::close, true); + devService = new RunningDevService(JGitProcessor.FEATURE, gitServer.getContainerId(), closeable, configOverrides); + return devService.toBuildItem(); + } + + public static class DevServicesEnabled implements BooleanSupplier { + + final JGitBuildTimeConfig config; + + public DevServicesEnabled(JGitBuildTimeConfig config) { + this.config = config; + } + + @Override + public boolean getAsBoolean() { + return config.devservices().enabled(); + } + } + +} diff --git a/deployment/src/main/java/io/quarkus/jgit/deployment/JGitProcessor.java b/deployment/src/main/java/io/quarkus/jgit/deployment/JGitProcessor.java index 1c29c34..851ce88 100644 --- a/deployment/src/main/java/io/quarkus/jgit/deployment/JGitProcessor.java +++ b/deployment/src/main/java/io/quarkus/jgit/deployment/JGitProcessor.java @@ -1,26 +1,16 @@ package io.quarkus.jgit.deployment; -import java.util.Map; -import java.util.function.BooleanSupplier; - -import org.jboss.logging.Logger; - -import io.quarkus.deployment.IsNormal; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; -import io.quarkus.deployment.builditem.DevServicesResultBuildItem; import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBundleBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem; -import io.quarkus.deployment.dev.devservices.GlobalDevServicesConfig; class JGitProcessor { - private static final String FEATURE = "jgit"; - - private static final Logger log = Logger.getLogger(JGitProcessor.class); + static final String FEATURE = "jgit"; @BuildStep FeatureBuildItem feature() { @@ -65,33 +55,4 @@ void runtimeInitializedClasses(BuildProducer p NativeImageResourceBundleBuildItem includeResourceBundle() { return new NativeImageResourceBundleBuildItem("org.eclipse.jgit.internal.JGitText"); } - - @SuppressWarnings("resource") - @BuildStep(onlyIfNot = IsNormal.class, onlyIf = { GlobalDevServicesConfig.Enabled.class, DevServicesEnabled.class }) - DevServicesResultBuildItem createContainer(JGitBuildTimeConfig config) { - var gitServer = new GiteaContainer(config.devservices()); - gitServer.start(); - String httpUrl = gitServer.getHttpUrl(); - log.infof("Gitea HTTP URL: %s", httpUrl); - Map configOverrides = Map.of( - "quarkus.jgit.devservices.http-url", httpUrl); - - return new DevServicesResultBuildItem.RunningDevService(FEATURE, gitServer.getContainerId(), - gitServer::close, configOverrides).toBuildItem(); - } - - public static class DevServicesEnabled implements BooleanSupplier { - - final JGitBuildTimeConfig config; - - public DevServicesEnabled(JGitBuildTimeConfig config) { - this.config = config; - } - - @Override - public boolean getAsBoolean() { - return config.devservices().enabled(); - } - } - } diff --git a/docs/modules/ROOT/pages/includes/quarkus-jgit.adoc b/docs/modules/ROOT/pages/includes/quarkus-jgit.adoc index cb644e0..ece1c88 100644 --- a/docs/modules/ROOT/pages/includes/quarkus-jgit.adoc +++ b/docs/modules/ROOT/pages/includes/quarkus-jgit.adoc @@ -93,6 +93,23 @@ endif::add-copy-button-to-env-var[] |string |`quarkus` +a|icon:lock[title=Fixed at build time] [[quarkus-jgit_quarkus-jgit-devservices-reuse]] [.property-path]##`quarkus.jgit.devservices.reuse`## + +[.description] +-- +Should the container be reused? + + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_JGIT_DEVSERVICES_REUSE+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_JGIT_DEVSERVICES_REUSE+++` +endif::add-copy-button-to-env-var[] +-- +|boolean +|`false` + a| [[quarkus-jgit_quarkus-jgit-devservices-http-url]] [.property-path]##`quarkus.jgit.devservices.http-url`## [.description] diff --git a/docs/modules/ROOT/pages/includes/quarkus-jgit_quarkus.jgit.adoc b/docs/modules/ROOT/pages/includes/quarkus-jgit_quarkus.jgit.adoc index cb644e0..ece1c88 100644 --- a/docs/modules/ROOT/pages/includes/quarkus-jgit_quarkus.jgit.adoc +++ b/docs/modules/ROOT/pages/includes/quarkus-jgit_quarkus.jgit.adoc @@ -93,6 +93,23 @@ endif::add-copy-button-to-env-var[] |string |`quarkus` +a|icon:lock[title=Fixed at build time] [[quarkus-jgit_quarkus-jgit-devservices-reuse]] [.property-path]##`quarkus.jgit.devservices.reuse`## + +[.description] +-- +Should the container be reused? + + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_JGIT_DEVSERVICES_REUSE+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_JGIT_DEVSERVICES_REUSE+++` +endif::add-copy-button-to-env-var[] +-- +|boolean +|`false` + a| [[quarkus-jgit_quarkus-jgit-devservices-http-url]] [.property-path]##`quarkus.jgit.devservices.http-url`## [.description]