Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.apache.camel.dsl.jbang.core.commands.CamelCommand;
import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
import org.apache.camel.dsl.jbang.core.common.RuntimeType;
import org.apache.camel.dsl.jbang.core.common.VersionHelper;
import org.apache.camel.dsl.jbang.core.model.UpdateListDTO;
import org.apache.camel.main.download.MavenDependencyDownloader;
import org.apache.camel.tooling.maven.MavenArtifact;
Expand Down Expand Up @@ -133,12 +134,12 @@ public Integer doCall() throws Exception {
// upgrade recipes 4.12.1 was released, but only Camel 4.12.0 is released, in this case,
// consider the major.minor only
if (runtimeVersion == null) {
String majorMinorVersion = getMajorMinorVersion(l[0]);
String majorMinorVersion = VersionHelper.getMajorMinorVersion(l[0]);
runtimeVersion
= recipesVersions.sbVersions().stream()
.filter(v -> {
// Handle micro Camel Upgrade Recipes versions like 4.14.0.1
String actualMajorMinorVersion = getMajorMinorVersion(v[0]);
String actualMajorMinorVersion = VersionHelper.getMajorMinorVersion(v[0]);
return actualMajorMinorVersion.equals(majorMinorVersion);
})
.findFirst()
Expand Down Expand Up @@ -192,12 +193,6 @@ public Integer doCall() throws Exception {
return 0;
}

private static String getMajorMinorVersion(String l) {
String[] versions = l.split("\\.");
String majorMinorVersion = versions[0] + "." + versions[1];
return majorMinorVersion;
}

/**
* Download camel, camel-spring-boot and quarkus upgrade-recipes dependencies and collect existing versions
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.apache.camel.dsl.jbang.core.commands.CamelCommand;
import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
import org.apache.camel.dsl.jbang.core.common.QuarkusHelper;
import org.apache.camel.dsl.jbang.core.common.RuntimeCompletionCandidates;
import org.apache.camel.dsl.jbang.core.common.RuntimeType;
import org.apache.camel.dsl.jbang.core.common.RuntimeTypeConverter;
Expand Down Expand Up @@ -177,6 +178,12 @@ public Integer doCall() throws Exception {
List<Row> rows = new ArrayList<>();
filterVersions(versions, rows, releases);

// resolve actual Quarkus platform versions from registry
if (RuntimeType.quarkus == runtime) {
QuarkusHelper.resolveQuarkusPlatformVersions(
rows, r -> r.runtimeVersion, (r, v) -> r.quarkusVersion = v);
}

if (lts) {
rows.removeIf(r -> !"lts".equalsIgnoreCase(r.kind));
}
Expand Down Expand Up @@ -226,17 +233,20 @@ public Integer doCall() throws Exception {
Jsoner.serialize(
rows.stream()
.map(row -> new VersionListDTO(
row.coreVersion, runtime.runtime(), row.runtimeVersion, row.jdks, row.kind,
row.releaseDate,
row.eolDate))
row.coreVersion, runtime.runtime(), row.runtimeVersion,
row.quarkusVersion, row.jdks, row.kind,
row.releaseDate, row.eolDate))
.map(VersionListDTO::toMap)
.collect(Collectors.toList())));
} else {
printer().println(AsciiTable.getTable(AsciiTable.NO_BORDERS, rows, Arrays.asList(
new Column().header("CAMEL VERSION")
.headerAlign(HorizontalAlign.CENTER).dataAlign(HorizontalAlign.CENTER).with(r -> r.coreVersion),
new Column().header("QUARKUS").visible(RuntimeType.quarkus == runtime)
new Column().header("CAMEL_QUARKUS").visible(RuntimeType.quarkus == runtime)
.headerAlign(HorizontalAlign.CENTER).dataAlign(HorizontalAlign.CENTER).with(r -> r.runtimeVersion),
new Column().header("QUARKUS").visible(RuntimeType.quarkus == runtime)
.headerAlign(HorizontalAlign.CENTER).dataAlign(HorizontalAlign.CENTER)
.with(r -> r.quarkusVersion != null ? r.quarkusVersion : ""),
new Column().header("SPRING-BOOT").visible(RuntimeType.springBoot == runtime)
.headerAlign(HorizontalAlign.CENTER).dataAlign(HorizontalAlign.CENTER).with(r -> r.runtimeVersion),
new Column().header("JDK")
Expand Down Expand Up @@ -602,6 +612,7 @@ private ReleaseModel onlineRelease(RuntimeType runtime, String coreVersion) thro
private static class Row {
String coreVersion;
String runtimeVersion;
String quarkusVersion;
String releaseDate;
long daysSince = -1;
String eolDate;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.dsl.jbang.core.common;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.camel.util.json.JsonArray;
import org.apache.camel.util.json.JsonObject;
import org.apache.camel.util.json.Jsoner;

/**
* Helper for resolving Quarkus platform information from the Quarkus registry.
*/
public final class QuarkusHelper {

public static final String QUARKUS_PLATFORM_URL_PROPERTY = "camel.jbang.quarkus.platform.url";
public static final String DEFAULT_QUARKUS_PLATFORM_URL = "https://registry.quarkus.io/client/platforms";

private QuarkusHelper() {
}

/**
* Returns the Quarkus platform registry URL, honoring the system property {@value #QUARKUS_PLATFORM_URL_PROPERTY}
* if set.
*/
public static String getQuarkusPlatformUrl() {
return System.getProperty(QUARKUS_PLATFORM_URL_PROPERTY, DEFAULT_QUARKUS_PLATFORM_URL);
}

/**
* Resolves the actual Quarkus platform version for each row by fetching the Quarkus platform registry and matching
* the Camel Quarkus major.minor version against stream IDs.
*
* @param rows the list of rows to enrich with Quarkus platform versions
* @param runtimeVersionFunc function to extract the runtime (Camel Quarkus) version from a row
* @param quarkusVersionSetter consumer to set the resolved Quarkus platform version on a row
*/
public static <T> void resolveQuarkusPlatformVersions(
List<T> rows,
Function<T, String> runtimeVersionFunc,
BiConsumer<T, String> quarkusVersionSetter) {

try {
HttpClient hc = HttpClient.newHttpClient();
HttpResponse<String> res = hc.send(
HttpRequest.newBuilder(new URI(getQuarkusPlatformUrl()))
.timeout(Duration.ofSeconds(2))
.build(),
HttpResponse.BodyHandlers.ofString());

if (res.statusCode() == 200) {
JsonObject json = (JsonObject) Jsoner.deserialize(res.body());
JsonArray platforms = json.getCollection("platforms");
if (platforms == null || platforms.isEmpty()) {
return;
}
JsonObject platform = platforms.getMap(0);
JsonArray streams = platform.getCollection("streams");
if (streams == null) {
return;
}

// keep the row with the highest runtime version per major.minor stream
BinaryOperator<T> keepLatest = (a, b) -> VersionHelper.compare(
runtimeVersionFunc.apply(a), runtimeVersionFunc.apply(b)) >= 0 ? a : b;

Map<String, T> latestPerStream = rows.stream()
.filter(row -> runtimeVersionFunc.apply(row) != null)
.collect(Collectors.toMap(
row -> VersionHelper.getMajorMinorVersion(runtimeVersionFunc.apply(row)),
Function.identity(),
keepLatest));

// match each major.minor against registry streams and set the quarkus version
latestPerStream.forEach((majorMinor, row) -> findQuarkusCoreVersion(streams, majorMinor)
.ifPresent(version -> quarkusVersionSetter.accept(row, version)));
}
} catch (Exception e) {
// ignore - if the registry is not reachable within 2 seconds, skip
}
}

/**
* Finds the quarkus-core-version from the registry streams that matches the given major.minor stream ID.
*/
private static Optional<String> findQuarkusCoreVersion(JsonArray streams, String majorMinor) {
return streams.stream()
.map(s -> (JsonObject) s)
.filter(stream -> majorMinor.equals(stream.getString("id")))
.findFirst()
.map(stream -> (JsonArray) stream.getCollection("releases"))
.filter(releases -> !releases.isEmpty())
.map(releases -> (JsonObject) releases.getMap(0))
.map(release -> release.getString("quarkus-core-version"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ public static int compare(String source, String target) {
return s.compareTo(t);
}

public static String getMajorMinorVersion(String version) {
String[] parts = version.split("\\.");
return parts[0] + "." + parts[1];
}

public static String extractCamelVersion() {
return org.apache.camel.main.util.VersionHelper.extractCamelVersion();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class VersionListDTO {
private String camelVersion;
private String runtime;
private String runtimeVersion;
private String quarkusVersion;
private String jdkVersion;
private String kind;
private String releaseDate;
Expand All @@ -33,12 +34,14 @@ public class VersionListDTO {
public VersionListDTO() {
}

public VersionListDTO(String camelVersion, String runtime, String runtimeVersion, String jdkVersion, String kind,
public VersionListDTO(String camelVersion, String runtime, String runtimeVersion, String quarkusVersion,
String jdkVersion, String kind,
String releaseDate,
String eolDate) {
this.camelVersion = camelVersion;
this.runtime = runtime;
this.runtimeVersion = runtimeVersion;
this.quarkusVersion = quarkusVersion;
this.jdkVersion = jdkVersion;
this.kind = kind;
this.releaseDate = releaseDate;
Expand Down Expand Up @@ -69,6 +72,14 @@ public void setRuntimeVersion(String runtimeVersion) {
this.runtimeVersion = runtimeVersion;
}

public String getQuarkusVersion() {
return quarkusVersion;
}

public void setQuarkusVersion(String quarkusVersion) {
this.quarkusVersion = quarkusVersion;
}

public String getJdkVersion() {
return jdkVersion;
}
Expand Down Expand Up @@ -108,6 +119,9 @@ public Map<String, Object> toMap() {
if (runtimeVersion != null) {
jo.put("runtimeVersion", runtimeVersion);
}
if (quarkusVersion != null) {
jo.put("quarkusVersion", quarkusVersion);
}
if (jdkVersion != null) {
jo.put("jdkVersion", jdkVersion);
}
Expand Down
60 changes: 60 additions & 0 deletions dsl/camel-jbang/camel-jbang-mcp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@
<artifactId>camel-yaml-dsl</artifactId>
</dependency>

<!-- Apache Commons Text for fuzzy string matching (Levenshtein distance) -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>${commons-text-version}</version>
</dependency>

<!-- test dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
Expand Down Expand Up @@ -136,6 +143,59 @@
</execution>
</executions>
</plugin>
<!-- Copy migration guide .adoc files into the uber-JAR for runtime search -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-migration-guides</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/migration-guides</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/../../../docs/user-manual/modules/ROOT/pages</directory>
<filtering>false</filtering>
<includes>
<include>camel-3-migration-guide.adoc</include>
<include>camel-4-migration-guide.adoc</include>
<include>camel-3x-upgrade-guide-3_*.adoc</include>
<include>camel-4x-upgrade-guide-4_*.adoc</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Generate index.txt listing all copied migration guide filenames -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-migration-guide-index</id>
<phase>process-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<fileset id="guide-files" dir="${project.build.outputDirectory}/migration-guides">
<include name="*.adoc"/>
</fileset>
<pathconvert property="guide-list" refid="guide-files" pathsep="${line.separator}">
<flattenmapper/>
</pathconvert>
<echo file="${project.build.outputDirectory}/migration-guides/index.txt"
message="${guide-list}"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
Expand Down
Loading