Skip to content

Commit

Permalink
Refactor camel update
Browse files Browse the repository at this point in the history
  • Loading branch information
Croway committed Jan 23, 2025
1 parent 344048e commit 2190cdc
Show file tree
Hide file tree
Showing 4 changed files with 341 additions and 204 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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.update;

import java.util.List;

import org.apache.camel.main.download.MavenDependencyDownloader;

public class CamelQuarkusUpdate extends CamelUpdate {

/**
* Quarkus updates are in the form 3.8, 3.15, 3.17... Downloads Camel Quarkus catalog for the given Camel version
* and get the Quarkus stream version
*
* @param downloader
* @param repos
* @param version
* @return
*/
public String getQuarkusStream(MavenDependencyDownloader downloader, String repos, String version) {
// Assume that the quarkus updates are in the form 3.8, 3.15, 3.16...
List<String[]> qVersions
= downloader.resolveAvailableVersions("org.apache.camel.quarkus", "camel-quarkus-catalog", version,
repos);
String streamVersion = null;
for (String[] qVersion : qVersions) {
if (qVersion[0].equals(version)) {
streamVersion = qVersion[1].substring(0, qVersion[1].lastIndexOf('.'));
}
}

return streamVersion;
}

@Override
public String debug(boolean debug) {
String result = "--no-transfer-progress";
if (debug) {
result = "-X";
}

return result;
}

@Override
public String runMode(boolean dryRun) {
String result = "-DrewriteFullRun";
if (dryRun) {
result = "-DrewriteDryRun";
}

return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* 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.update;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import org.apache.camel.main.download.MavenDependencyDownloader;
import org.apache.camel.tooling.maven.MavenArtifact;

public class CamelUpdate {

protected List<String> commands = new ArrayList<>();

/**
* Download the jar containing the recipes and extract the recipe name to be used in the maven command
*
* @return
*/
public List<String> activeRecipes(MavenDependencyDownloader downloader, String recipesArtifactId, String version) {
List<Recipe> recipes;
MavenArtifact mavenArtifact
= downloader.downloadArtifact("org.apache.camel.upgrade", recipesArtifactId, version);

try {
recipes = getRecipesInJar(mavenArtifact.getFile());
} catch (IOException ex) {
throw new RuntimeException(ex);
}

List<String> activeRecipes = new ArrayList<>();
for (Recipe recipe : recipes) {
// The recipe named latest.yaml contains all the recipe for the update up to the selected version
if (recipe.name().contains("latest")) {
activeRecipes.clear();
recipe.recipeName().ifPresent(name -> activeRecipes.add(name));
break;
}

recipe.recipeName().ifPresent(name -> activeRecipes.add(name));
}

return activeRecipes;
}

public String debug(boolean debug) {
String result = "--no-transfer-progress";
if (debug) {
result = "-X";
}

return result;
}

public String runMode(boolean dryRun) {
String task = "run";
if (dryRun) {
task = "dryRun";
}

return task;
}

private List<Recipe> getRecipesInJar(File jar) throws IOException {
List<Recipe> recipes = new ArrayList<>();
Path jarPath = jar.toPath();

try (FileSystem fileSystem = FileSystems.newFileSystem(jarPath, (ClassLoader) null)) {
Path recipePath = fileSystem.getPath("META-INF", "rewrite");
if (Files.exists(recipePath)) {
try (Stream<Path> walk = Files.walk(recipePath)) {
walk.filter(p -> p.toString().endsWith(".yaml"))
.forEach(p -> {
try {
recipes.add(new Recipe(
p.getFileName().toString(),
Files.readString(p)));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
}
}
}
return recipes;
}

record Recipe(String name, String content) {

/**
* Retrieves the name of the recipe if it is a Camel upgrade recipe.
*
* @return an Optional containing the recipe name if it is a Camel upgrade recipe, otherwise empty
*/
public Optional<String> recipeName() {
return Arrays.stream(content().split(System.lineSeparator()))
.filter(l -> l.startsWith("name") && l.contains("org.apache.camel.upgrade"))
.map(l -> l.substring(l.indexOf("org.apache.camel.upgrade")))
.findFirst();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,87 +109,25 @@ public Integer doCall() throws Exception {
downloader.setRepositories(repos);
downloader.start();

CompletableFuture<List<String[]>> plainCamelRecipesVersionFuture
= CompletableFuture.supplyAsync(() -> downloader.resolveAvailableVersions(
CAMEL_UPGRADE_GROUPID,
CAMEL_UPGRADE_ARTIFACTID,
FIRST_RECIPE_VERSION,
repos));

final List<String[]> sbVersions = new ArrayList<>();
CompletableFuture<List<String[]>> camelSpringBootRecipesVersionFuture = CompletableFuture.supplyAsync(() -> {
List<String[]> camelSpringBootRecipesVersion = downloader.resolveAvailableVersions(
CAMEL_UPGRADE_GROUPID,
CAMEL_SB_UPGRADE_ARTIFACTID,
FIRST_RECIPE_VERSION,
repos);
if (!camelSpringBootRecipesVersion.isEmpty()) {
// 4.8.0 is the first version with update recipes
sbVersions.addAll(
downloader.resolveAvailableVersions(
"org.apache.camel.springboot",
"camel-spring-boot",
FIRST_RECIPE_VERSION,
repos));
}

return camelSpringBootRecipesVersion;
});

final Set<QuarkusUpdates> quarkusUpdateRecipes = new LinkedHashSet<>();
CompletableFuture<List<String[]>> camelQuarkusRecipesVersionsFuture = CompletableFuture
.supplyAsync(() -> {
List<String[]> camelQuarkusRecipesVersions = downloader.resolveAvailableVersions(
"io.quarkus",
"quarkus-update-recipes",
QUARKUS_FIRST_RECIPE_VERSION,
repos);

for (String[] camelQuarkusRecipeVersion : camelQuarkusRecipesVersions) {
String version = camelQuarkusRecipeVersion[0];
MavenArtifact artifact = downloader.downloadArtifact("io.quarkus",
"quarkus-update-recipes",
version);

try {
quarkusUpdateRecipes.addAll(getCamelQuarkusRecipesInJar(artifact.getFile()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
RecipeVersions recipesVersions = collectRecipesVersions(downloader);

return camelQuarkusRecipesVersions;
});

CompletableFuture<List<String[]>> qVersionsFuture
= CompletableFuture.supplyAsync(() -> downloader.resolveAvailableVersions(
"org.apache.camel.quarkus",
"camel-quarkus-catalog",
QUARKUS_FIRST_UPDATABLE_VERSION,
repos));

plainCamelRecipesVersionFuture.get()
// Convert recipes versions into Rows for table and json visualization
recipesVersions.plainCamelRecipesVersion()
.forEach(l -> rows
.add(new Row(l[0], "Camel", "", "Migrates Apache Camel 4 application to Apache Camel " + l[0])));
camelSpringBootRecipesVersionFuture.get().forEach(l -> {
String[] runtimeVersion = sbVersions.stream().filter(v -> v[0].equals(l[0])).findFirst().orElseThrow();
recipesVersions.camelSpringBootRecipesVersion().forEach(l -> {
String[] runtimeVersion
= recipesVersions.sbVersions().stream().filter(v -> v[0].equals(l[0])).findFirst().orElseThrow();

rows.add(new Row(
l[0], "Camel Spring Boot", runtimeVersion[1],
"Migrates Apache Camel Spring Boot 4 application to Apache Camel Spring Boot " + l[0]));
});
// Translate quarkus versions to Camel
camelQuarkusRecipesVersionsFuture.get();
quarkusUpdateRecipes.forEach(l -> {
List<String[]> runtimeVersions;
try {
runtimeVersions = qVersionsFuture.get().stream().filter(v -> v[1].startsWith(l.version()))
.collect(Collectors.toList());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
recipesVersions.camelQuarkusRecipesVersions();
recipesVersions.quarkusUpdateRecipes().forEach(l -> {
List<String[]> runtimeVersions = recipesVersions.qVersions().stream().filter(v -> v[1].startsWith(l.version()))
.collect(Collectors.toList());
runtimeVersions.sort(Comparator.comparing(o -> o[1]));
String[] runtimeVersion = runtimeVersions.get(runtimeVersions.size() - 1);
// Quarkus may release patches independently, therefore, we do not know the real micro version
Expand Down Expand Up @@ -226,6 +164,92 @@ public Integer doCall() throws Exception {
return 0;
}

/**
* Download camel, camel-spring-boot and quarkus upgrade-recipes dependencies and collect existing versions
*
* @param downloader
* @return
* @throws ExecutionException
* @throws InterruptedException
*/
private RecipeVersions collectRecipesVersions(MavenDependencyDownloader downloader)
throws ExecutionException, InterruptedException {
CompletableFuture<List<String[]>> plainCamelRecipesVersionFuture
= CompletableFuture.supplyAsync(() -> downloader.resolveAvailableVersions(
CAMEL_UPGRADE_GROUPID,
CAMEL_UPGRADE_ARTIFACTID,
FIRST_RECIPE_VERSION,
repos));

final List<String[]> sbVersions = new ArrayList<>();
CompletableFuture<List<String[]>> camelSpringBootRecipesVersionFuture = CompletableFuture.supplyAsync(() -> {
List<String[]> camelSpringBootRecipesVersion = downloader.resolveAvailableVersions(
CAMEL_UPGRADE_GROUPID,
CAMEL_SB_UPGRADE_ARTIFACTID,
FIRST_RECIPE_VERSION,
repos);
if (!camelSpringBootRecipesVersion.isEmpty()) {
// 4.8.0 is the first version with update recipes
sbVersions.addAll(
downloader.resolveAvailableVersions(
"org.apache.camel.springboot",
"camel-spring-boot",
FIRST_RECIPE_VERSION,
repos));
}

return camelSpringBootRecipesVersion;
});

final Set<QuarkusUpdates> quarkusUpdateRecipes = new LinkedHashSet<>();
CompletableFuture<List<String[]>> camelQuarkusRecipesVersionsFuture = CompletableFuture
.supplyAsync(() -> {
List<String[]> camelQuarkusRecipesVersions = downloader.resolveAvailableVersions(
"io.quarkus",
"quarkus-update-recipes",
QUARKUS_FIRST_RECIPE_VERSION,
repos);

for (String[] camelQuarkusRecipeVersion : camelQuarkusRecipesVersions) {
String version = camelQuarkusRecipeVersion[0];
MavenArtifact artifact = downloader.downloadArtifact("io.quarkus",
"quarkus-update-recipes",
version);

try {
quarkusUpdateRecipes.addAll(getCamelQuarkusRecipesInJar(artifact.getFile()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

return camelQuarkusRecipesVersions;
});

CompletableFuture<List<String[]>> qVersionsFuture
= CompletableFuture.supplyAsync(() -> downloader.resolveAvailableVersions(
"org.apache.camel.quarkus",
"camel-quarkus-catalog",
QUARKUS_FIRST_UPDATABLE_VERSION,
repos));

return new RecipeVersions(
plainCamelRecipesVersionFuture.get(),
sbVersions,
camelSpringBootRecipesVersionFuture.get(),
quarkusUpdateRecipes,
camelQuarkusRecipesVersionsFuture.get(),
qVersionsFuture.get());
}

record RecipeVersions(List<String[]> plainCamelRecipesVersion,
List<String[]> sbVersions,
List<String[]> camelSpringBootRecipesVersion,
Set<QuarkusUpdates> quarkusUpdateRecipes,
List<String[]> camelQuarkusRecipesVersions,
List<String[]> qVersions) {
}

record Row(String version, String runtime, String runtimeVersion, String description) {
}

Expand Down
Loading

0 comments on commit 2190cdc

Please sign in to comment.