Repository: quarkusio/quarkus
Issue: Regression: Quarkus-cli create app doesn't auto-detect Host java version

### Describe the bug

When you create an app with `Quarkus-cli 2.6.3` the tool detects the java version that is running in the developer environment and the resulted app has the same java version as the host. 

This feature is broken in `Quarkus 2.7.5.Final`

Reproducer: 

Quarkus 2.6.3

Install quarkus-cli 2.6.3: `jbang app install --name qs2.6.3 io.quarkus:quarkus-cli:2.6.3.Final:runner `
Create app: `qs2.6.3 create app app`

The pom has the same Java version as the host machine. 

Quarkus 2.7.5

Install quarkus-cli 2.6.3:  `jbang app install --name qs2.7.5 io.quarkus:quarkus-cli:2.7.5.Final:runner `
Create app: `qs2.7.5 create app app`
Pom Java version:`<maven.compiler.release>11</maven.compiler.release> `
Expected version: `17`


### Output of `java -version`

openjdk 17.0.1 2021-10-19 OpenJDK Runtime Environment Temurin-17.0.1+12 (build 17.0.1+12) OpenJDK 64-Bit Server VM Temurin-17.0.1+12 (build 17.0.1+12, mixed mode, sharing)



Changed files:
devtools/cli/src/main/java/io/quarkus/cli/create/TargetLanguageGroup.java
independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/codegen/CreateProjectHelperTest.java
independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/codestarts/jbang/QuarkusJBangCodestartProjectInputBuilder.java
independent-projects/tools/devtools-testing/src/test/java/io/quarkus/devtools/codestarts/jbang/QuarkusJBangCodestartGenerationTest.java
independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/CreateProjectHelper.java

diff --git a/devtools/cli/src/main/java/io/quarkus/cli/create/TargetLanguageGroup.java b/devtools/cli/src/main/java/io/quarkus/cli/create/TargetLanguageGroup.java
index ee88757a6f0..2ac56d3063b 100644
--- a/devtools/cli/src/main/java/io/quarkus/cli/create/TargetLanguageGroup.java
+++ b/devtools/cli/src/main/java/io/quarkus/cli/create/TargetLanguageGroup.java
@@ -1,8 +1,8 @@
 package io.quarkus.cli.create;
 
 import java.util.ArrayList;
-import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import io.quarkus.cli.common.OutputOptionMixin;
 import io.quarkus.devtools.project.BuildTool;
@@ -17,13 +17,13 @@ public class TargetLanguageGroup {
 
     static class VersionCandidates extends ArrayList<String> {
         VersionCandidates() {
-            super(List.copyOf(CreateProjectHelper.JAVA_VERSIONS_LTS));
+            super(CreateProjectHelper.JAVA_VERSIONS_LTS.stream().map(String::valueOf).collect(Collectors.toList()));
         }
     }
 
     @CommandLine.Option(names = {
-            "--java" }, description = "Target Java version.\\n  Valid values: ${COMPLETION-CANDIDATES}", completionCandidates = VersionCandidates.class, defaultValue = CreateProjectHelper.DEFAULT_JAVA_VERSION)
-    String javaVersion = CreateProjectHelper.DEFAULT_JAVA_VERSION;
+            "--java" }, description = "Target Java version.\\n  Valid values: ${COMPLETION-CANDIDATES}", completionCandidates = VersionCandidates.class, defaultValue = CreateProjectHelper.DETECT_JAVA_RUNTIME_VERSION)
+    String javaVersion = CreateProjectHelper.DETECT_JAVA_RUNTIME_VERSION;
 
     @CommandLine.Option(names = { "--kotlin" }, description = "Use Kotlin")
     boolean kotlin = false;
diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/codestarts/jbang/QuarkusJBangCodestartProjectInputBuilder.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/codestarts/jbang/QuarkusJBangCodestartProjectInputBuilder.java
index e91d362d1db..e9018cdfc93 100644
--- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/codestarts/jbang/QuarkusJBangCodestartProjectInputBuilder.java
+++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/codestarts/jbang/QuarkusJBangCodestartProjectInputBuilder.java
@@ -84,7 +84,8 @@ public boolean noJBangWrapper() {
 
     public QuarkusJBangCodestartProjectInput build() {
         if (!this.containsData("java")) {
-            this.addData(NestedMaps.unflatten(Map.of("java.version", CreateProjectHelper.DEFAULT_JAVA_VERSION)));
+            this.addData(NestedMaps
+                    .unflatten(Map.of("java.version", String.valueOf(CreateProjectHelper.determineBestJavaLtsVersion()))));
         }
         return new QuarkusJBangCodestartProjectInput(this);
     }
diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/CreateProjectHelper.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/CreateProjectHelper.java
index 8127af5766a..a8371290c75 100644
--- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/CreateProjectHelper.java
+++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/CreateProjectHelper.java
@@ -8,10 +8,13 @@
 import java.nio.file.Path;
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -19,9 +22,11 @@
 
 public class CreateProjectHelper {
 
-    public static final Set<String> JAVA_VERSIONS_LTS = Set.of("11", "17");
-    public static final String DEFAULT_JAVA_VERSION = "11";
-    private static final Pattern JAVA_VERSION_PATTERN = Pattern.compile("(?:1\\\\.)?(\\\\d+)(?:\\\\..*)?");
+    // ordering is important here, so let's keep them ordered
+    public static final SortedSet<Integer> JAVA_VERSIONS_LTS = new TreeSet<>(List.of(11, 17));
+    private static final int DEFAULT_JAVA_VERSION = 11;
+    public static final String DETECT_JAVA_RUNTIME_VERSION = "<<detect java runtime version>>";
+    private static final Pattern JAVA_VERSION_PATTERN = Pattern.compile("(\\\\d+)(?:\\\\..*)?");
 
     public static final String DEFAULT_GROUP_ID = "org.acme";
     public static final String DEFAULT_ARTIFACT_ID = "code-with-quarkus";
@@ -79,16 +84,36 @@ public static SourceType determineSourceType(Set<String> extensions) {
     public static void setJavaVersion(Map<String, Object> values, String javaTarget) {
         requireNonNull(values, "Must provide values");
 
-        Matcher matcher = JAVA_VERSION_PATTERN
-                .matcher(javaTarget != null ? javaTarget : System.getProperty("java.version", ""));
+        Integer javaFeatureVersionTarget = null;
 
-        if (matcher.matches()) {
-            String versionExtracted = matcher.group(1);
-            String version = JAVA_VERSIONS_LTS.contains(versionExtracted) ? versionExtracted : DEFAULT_JAVA_VERSION;
-            values.put(ProjectGenerator.JAVA_TARGET, version);
-        } else {
-            values.put(ProjectGenerator.JAVA_TARGET, DEFAULT_JAVA_VERSION);
+        if (javaTarget != null && !DETECT_JAVA_RUNTIME_VERSION.equals(javaTarget)) {
+            // Probably too much as we should push only the feature version but let's be as thorough as we used to be
+            Matcher matcher = JAVA_VERSION_PATTERN.matcher(javaTarget);
+            if (matcher.matches()) {
+                javaFeatureVersionTarget = Integer.valueOf(matcher.group(1));
+            }
+        }
+
+        if (javaFeatureVersionTarget == null) {
+            javaFeatureVersionTarget = Runtime.version().feature();
+        }
+
+        values.put(ProjectGenerator.JAVA_TARGET, String.valueOf(determineBestJavaLtsVersion(javaFeatureVersionTarget)));
+    }
+
+    public static int determineBestJavaLtsVersion() {
+        return determineBestJavaLtsVersion(Runtime.version().feature());
+    }
+
+    public static int determineBestJavaLtsVersion(int runtimeVersion) {
+        int bestLtsVersion = DEFAULT_JAVA_VERSION;
+        for (int ltsVersion : JAVA_VERSIONS_LTS) {
+            if (ltsVersion > runtimeVersion) {
+                break;
+            }
+            bestLtsVersion = ltsVersion;
         }
+        return bestLtsVersion;
     }
 
     public static Set<String> sanitizeExtensions(Set<String> extensions) {
diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/codegen/CreateProjectHelperTest.java b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/codegen/CreateProjectHelperTest.java
index 3c1e4169877..8e0dc592e7c 100644
--- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/codegen/CreateProjectHelperTest.java
+++ b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/codegen/CreateProjectHelperTest.java
@@ -11,7 +11,7 @@ class CreateProjectHelperTest {
     @Test
     public void givenJavaVersion17ShouldReturn17() {
         Map<String, Object> values = new HashMap<>();
-        values.put("nonull", "nonull");
+        values.put("nonnull", "nonnull");
 
         CreateProjectHelper.setJavaVersion(values, "17");
         assertEquals("17", values.get("java_target"));
@@ -20,9 +20,46 @@ public void givenJavaVersion17ShouldReturn17() {
     @Test
     public void givenJavaVersion16ShouldReturn11() {
         Map<String, Object> values = new HashMap<>();
-        values.put("nonull", "nonull");
+        values.put("nonnull", "nonnull");
 
         CreateProjectHelper.setJavaVersion(values, "16.0.1");
         assertEquals("11", values.get("java_target"));
     }
+
+    @Test
+    public void givenJavaVersion11ShouldReturn11() {
+        Map<String, Object> values = new HashMap<>();
+        values.put("nonnull", "nonnull");
+
+        CreateProjectHelper.setJavaVersion(values, "11");
+        assertEquals("11", values.get("java_target"));
+    }
+
+    @Test
+    public void givenJavaVersion18ShouldReturn17() {
+        Map<String, Object> values = new HashMap<>();
+        values.put("nonnull", "nonnull");
+
+        CreateProjectHelper.setJavaVersion(values, "18");
+        assertEquals("17", values.get("java_target"));
+    }
+
+    @Test
+    public void givenAutoDetectShouldReturnAppropriateVersion() {
+        Map<String, Object> values = new HashMap<>();
+        values.put("nonnull", "nonnull");
+
+        CreateProjectHelper.setJavaVersion(values, CreateProjectHelper.DETECT_JAVA_RUNTIME_VERSION);
+        assertEquals(String.valueOf(CreateProjectHelper.determineBestJavaLtsVersion(Runtime.version().feature())),
+                values.get("java_target"));
+    }
+
+    @Test
+    public void testDetermineBestLtsVersion() {
+        assertEquals(11, CreateProjectHelper.determineBestJavaLtsVersion(8));
+        assertEquals(11, CreateProjectHelper.determineBestJavaLtsVersion(11));
+        assertEquals(11, CreateProjectHelper.determineBestJavaLtsVersion(12));
+        assertEquals(17, CreateProjectHelper.determineBestJavaLtsVersion(17));
+        assertEquals(17, CreateProjectHelper.determineBestJavaLtsVersion(18));
+    }
 }
diff --git a/independent-projects/tools/devtools-testing/src/test/java/io/quarkus/devtools/codestarts/jbang/QuarkusJBangCodestartGenerationTest.java b/independent-projects/tools/devtools-testing/src/test/java/io/quarkus/devtools/codestarts/jbang/QuarkusJBangCodestartGenerationTest.java
index ee3ec9669f8..4c36f4f26db 100644
--- a/independent-projects/tools/devtools-testing/src/test/java/io/quarkus/devtools/codestarts/jbang/QuarkusJBangCodestartGenerationTest.java
+++ b/independent-projects/tools/devtools-testing/src/test/java/io/quarkus/devtools/codestarts/jbang/QuarkusJBangCodestartGenerationTest.java
@@ -6,10 +6,12 @@
 import static io.quarkus.devtools.testing.SnapshotTesting.assertThatDirectoryTreeMatchSnapshots;
 import static io.quarkus.devtools.testing.SnapshotTesting.assertThatMatchSnapshot;
 
+import io.quarkus.devtools.codestarts.utils.NestedMaps;
 import io.quarkus.devtools.testing.SnapshotTesting;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Map;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInfo;
@@ -29,6 +31,9 @@ void generateDefaultProject(TestInfo testInfo) throws Throwable {
                 .putData(QUARKUS_BOM_GROUP_ID, "io.quarkus")
                 .putData(QUARKUS_BOM_ARTIFACT_ID, "quarkus-bom")
                 .putData(QUARKUS_BOM_VERSION, "999-MOCK")
+                // define the version here as it is now autodetecting the best LTS version at runtime
+                // and we want a static version for the snapshots
+                .addData(NestedMaps.unflatten(Map.of("java.version", "11")))
                 .build();
         final Path projectDir = testDirPath.resolve("default");
         getCatalog().createProject(input).generate(projectDir);
@@ -43,6 +48,9 @@ void generatePicocliProject(TestInfo testInfo) throws Throwable {
                 .putData(QUARKUS_BOM_GROUP_ID, "io.quarkus")
                 .putData(QUARKUS_BOM_ARTIFACT_ID, "quarkus-bom")
                 .putData(QUARKUS_BOM_VERSION, "999-MOCK")
+                // define the version here as it is now autodetecting the best LTS version at runtime
+                // and we want a static version for the snapshots
+                .addData(NestedMaps.unflatten(Map.of("java.version", "11")))
                 .build();
         final Path projectDir = testDirPath.resolve("picocli");
         getCatalog().createProject(input).generate(projectDir);