This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 21b3604c4e56 CAMEL-23688: camel-jbang - Tests for camel version list
without downloads (#27978)
21b3604c4e56 is described below
commit 21b3604c4e56bbe8ddcc95d847bb604fa4f8031e
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Oct 17 00:09:31 2026 +0200
CAMEL-23688: camel-jbang - Tests for camel version list without downloads
(#27978)
Tests for camel version list (57% covered; its JSON was not tested),
without downloads: the Camel releases the catalog knows, here the 4.10
to 4.12 releases, which do not change any more. The table, JSON (and []),
--patch=false, --lts, --eol=false, --from-date and --to-date, the order
and --tail, and --date-format. They found these bugs, fixed here:
* A --date-format that is not a date pattern showed the dates
unformatted, and a --from-date or --to-date that is not a date was
ignored; now usage errors.
* The "Last updated" note was printed on stdout after the table; it goes
to stderr.
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
---
.../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc | 7 +
.../jbang/core/commands/version/VersionList.java | 30 +++-
.../commands/version/VersionListReleasesTest.java | 195 +++++++++++++++++++++
3 files changed, 229 insertions(+), 3 deletions(-)
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index fea6640a6d6b..9a60548ae164 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -608,6 +608,13 @@ prints the Kamelets as JSON, as the other `camel catalog`
commands do.
`2`: the first showed every error, the second none. The errors of
`--diagram` are printed on stderr, and a graphical
`--theme` in a terminal without graphics exits with `2`.
+=== camel-jbang - camel version list
+
+* `camel version list` prints the `Last updated` note on stderr, so stdout has
the table only.
+* A `--date-format` that is not a date pattern, and a `--from-date` or
`--to-date` that is not a date in the
+ `yyyy-MM-dd` format (such as `2025-01-31`), exit with `2`: the first showed
the dates unformatted, and the others were
+ ignored.
+
=== camel-jbang - the shared action file is deprecated for plugin commands
`CamelCommand.getActionFile` and `CamelCommand.getOutputFile`, the action and
output files that all the clients of an
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/version/VersionList.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/version/VersionList.java
index c5dee1e0b7e9..a0e813d1c67f 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/version/VersionList.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/version/VersionList.java
@@ -32,6 +32,7 @@ import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
@@ -171,6 +172,18 @@ public class VersionList extends CamelCommand {
@Override
public Integer doCall() throws Exception {
+ // the options are wrong whatever the releases are, so before reading
them
+ Comparator<Row> order = ORDER.comparator(sort);
+ if (dateFormat != null) {
+ try {
+ new SimpleDateFormat(dateFormat, Locale.US);
+ } catch (IllegalArgumentException e) {
+ throw CliException.usage("--date-format must be a date pattern
such as dd-MM-yyyy, was: " + dateFormat);
+ }
+ }
+ requireDate("--from-date", fromDate);
+ requireDate("--to-date", toDate);
+
// ensure from and to-version have major.minor
if (fromVersion != null) {
if (!(fromVersion.contains(".") || fromVersion.contains(","))) {
@@ -234,7 +247,7 @@ public class VersionList extends CamelCommand {
}
// sort rows
- rows = rows.sorted(ORDER.comparator(sort));
+ rows = rows.sorted(order);
List<Row> rowsList = rows.toList();
if (tail > 0) {
@@ -295,16 +308,27 @@ public class VersionList extends CamelCommand {
}
}
}
+ // not part of the table
if (date != null) {
- printer().println("Last updated: " + date + " (use --fresh to
update list from internet)");
+ printer().printDiagnostic("Last updated: " + date + " (use
--fresh to update list from internet)");
} else {
- printer().println("Last updated: none (use --fresh to update
list from internet)");
+ printer().printDiagnostic("Last updated: none (use --fresh to
update list from internet)");
}
}
return 0;
}
+ private static void requireDate(String option, String date) {
+ if (date != null) {
+ try {
+ LocalDate.parse(date, DateTimeFormatter.ofPattern(YYYY_MM_DD));
+ } catch (DateTimeParseException e) {
+ throw CliException.usage(option + " must be a date such as
2025-01-31, was: " + date);
+ }
+ }
+ }
+
public static JsonObject updateCheckerFile(JsonObject root, String
runtime, String repositories) {
if (repositories == null) {
repositories = "";
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/version/VersionListReleasesTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/version/VersionListReleasesTest.java
new file mode 100644
index 000000000000..1d6321230a21
--- /dev/null
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/version/VersionListReleasesTest.java
@@ -0,0 +1,195 @@
+/*
+ * 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.commands.version;
+
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.apache.camel.dsl.jbang.core.commands.CamelCommandBaseTestSupport;
+import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
+import org.apache.camel.dsl.jbang.core.common.CliException;
+import org.apache.camel.dsl.jbang.core.common.CliExitCode;
+import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import org.apache.camel.util.json.Jsoner;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import picocli.CommandLine;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+/**
+ * camel version list without downloads: the Camel releases the catalog knows,
here the 4.10 to 4.12 releases, which do
+ * not change any more, filtered and formatted.
+ */
+class VersionListReleasesTest extends CamelCommandBaseTestSupport {
+
+ @TempDir
+ Path home;
+
+ private Path previousHome;
+
+ @BeforeEach
+ void useHome() {
+ // without the file that says when the list was updated
+ previousHome = CommandLineHelper.getHomeDir();
+ CommandLineHelper.useHomeDir(home.toString());
+ }
+
+ @AfterEach
+ void restoreHome() {
+ CommandLineHelper.useHomeDir(previousHome.toString());
+ }
+
+ @Test
+ void theReleasesOfTheCatalog() throws Exception {
+ assertThat(command().doCall()).isZero();
+
+ String[] lines = printer.getStdout().split(System.lineSeparator());
+ assertThat(lines[0]).contains("CAMEL VERSION", "JDK", "KIND",
"RELEASED", "SUPPORTED UNTIL", "DAYS");
+ // 4.10.0 to 4.10.9, 4.11.0 and 4.12.0
+ assertThat(lines).hasSize(13);
+ assertThat(lines[1]).contains("4.10.0", "17,21", "LTS", "February
2025", "February 2026");
+ assertThat(lines[11]).contains("4.11.0", "April
2025").doesNotContain("LTS");
+ assertThat(lines[12]).contains("4.12.0", "May 2025");
+ // not part of the table
+ assertThat(printer.getStderr()).isEqualTo("Last updated: none (use
--fresh to update list from internet)");
+ }
+
+ @Test
+ void json() throws Exception {
+ assertThat(command("--json", "--to-version=4.10.1").doCall()).isZero();
+
+ JsonArray releases = Jsoner.deserialize(printer.getStdout(),
(JsonArray) null);
+ assertThat(releases).hasSize(1);
+ JsonObject release = releases.getMap(0);
+ assertThat(release.getString("camelVersion")).isEqualTo("4.10.0");
+ assertThat(release.getString("runtime")).isEqualTo("main");
+ assertThat(release.getString("jdkVersion")).isEqualTo("17,21");
+ assertThat(release.getString("kind")).isEqualTo("lts");
+ assertThat(release.getString("releaseDate")).isEqualTo("2025-02-11");
+ assertThat(release.getString("eolDate")).isEqualTo("2026-02-10");
+ // the JSON is the output
+ assertThat(printer.getStderr()).isEmpty();
+ }
+
+ @Test
+ void jsonWithoutReleasesIsAnEmptyArray() throws Exception {
+ assertThat(command("--json",
"--from-date=2030-01-01").doCall()).isZero();
+
+ assertThat(printer.getStdout()).isEqualTo("[]");
+ }
+
+ @Test
+ void withoutPatchReleases() throws Exception {
+ assertThat(command("--patch=false").doCall()).isZero();
+
+ assertThat(versions()).containsExactly("4.10.0", "4.11.0", "4.12.0");
+ }
+
+ @Test
+ void ltsOnly() throws Exception {
+ assertThat(command("--lts", "--patch=false").doCall()).isZero();
+
+ assertThat(versions()).containsExactly("4.10.0");
+ }
+
+ @Test
+ void withoutTheReleasesAtTheirEndOfLife() throws Exception {
+ // the 4.10 releases were supported until February 2026; the others
have no end of life
+ assertThat(command("--eol=false").doCall()).isZero();
+
+ assertThat(versions()).containsExactly("4.11.0", "4.12.0");
+ }
+
+ @Test
+ void releasedBetweenTwoDates() throws Exception {
+ assertThat(command("--from-date=2025-04-01",
"--to-date=2025-06-01").doCall()).isZero();
+
+ assertThat(versions()).containsExactly("4.10.4", "4.11.0", "4.12.0");
+ }
+
+ @Test
+ void theNewestFirstAndTheTail() throws Exception {
+ assertThat(command("--sort=-version", "--tail=2").doCall()).isZero();
+
+ // the end of the table: the oldest two
+ assertThat(versions()).containsExactly("4.10.1", "4.10.0");
+ }
+
+ @Test
+ void theDateFormat() throws Exception {
+ assertThat(command("--date-format=yyyy-MM-dd", "--days=false",
"--to-version=4.10.1").doCall()).isZero();
+
+ String[] lines = printer.getStdout().split(System.lineSeparator());
+ assertThat(lines[0]).doesNotContain("DAYS");
+ assertThat(lines[1]).contains("4.10.0", "2025-02-11", "2026-02-10");
+ }
+
+ @Test
+ void aDateFormatThatIsNotAPatternIsAUsageError() {
+ VersionList command = command("--date-format=yyyy-bb");
+
+ assertThatThrownBy(command::doCall)
+ .isInstanceOfSatisfying(CliException.class,
+ e ->
assertThat(e.getExitCode()).isEqualTo(CliExitCode.USAGE))
+ .hasMessage("--date-format must be a date pattern such as
dd-MM-yyyy, was: yyyy-bb");
+ }
+
+ @Test
+ void aFromDateThatIsNotADateIsAUsageError() {
+ VersionList command = command("--from-date=last year");
+
+ assertThatThrownBy(command::doCall)
+ .isInstanceOfSatisfying(CliException.class,
+ e ->
assertThat(e.getExitCode()).isEqualTo(CliExitCode.USAGE))
+ .hasMessage("--from-date must be a date such as 2025-01-31,
was: last year");
+ }
+
+ @Test
+ void aToDateThatIsNotADateIsAUsageError() {
+ VersionList command = command("--to-date=31-12-2025");
+
+ assertThatThrownBy(command::doCall)
+ .isInstanceOfSatisfying(CliException.class,
+ e ->
assertThat(e.getExitCode()).isEqualTo(CliExitCode.USAGE))
+ .hasMessage("--to-date must be a date such as 2025-01-31, was:
31-12-2025");
+ }
+
+ // the 4.10 to 4.12 releases, without downloading the releases since the
catalog
+ private VersionList command(String... args) {
+ VersionList command = new VersionList(new
CamelJBangMain().withPrinter(printer));
+ List<String> all = Stream.concat(Stream.of("--download=false",
"--from-version=4.10", "--to-version=4.13"),
+ Arrays.stream(args)).toList();
+ // the last of an option given twice wins, as the arguments say
+ CommandLine cl = new CommandLine(command);
+ cl.setOverwrittenOptionsAllowed(true);
+ cl.parseArgs(all.toArray(String[]::new));
+ return command;
+ }
+
+ private List<String> versions() {
+ return
Arrays.stream(printer.getStdout().split(System.lineSeparator())).skip(1)
+ .map(l -> l.strip().split("\\s+")[0]).toList();
+ }
+}