From 6befa09323d4c0874cb177fe243a21ae31a49d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Champeau?= Date: Fri, 21 Jun 2024 17:06:40 +0200 Subject: [PATCH] Add option to select catalog to use as source for the BOM (#703) This commit introduces a new "catalogName" property to the BOM extension, which defaults to "libs", and tells the BOM plugin which catalog to use for the BOM generation. This is required for the use case where multiple BOMs have to be generated, but using a different TOML file as source. --- .../micronaut/build/MicronautBomPlugin.java | 34 +++++++++- .../build/pom/MicronautBomExtension.java | 7 ++ .../MicronautBuildSettingsExtension.java | 66 ++++++++++--------- 3 files changed, 74 insertions(+), 33 deletions(-) diff --git a/src/main/groovy/io/micronaut/build/MicronautBomPlugin.java b/src/main/groovy/io/micronaut/build/MicronautBomPlugin.java index 899b8016..06fe8ee5 100644 --- a/src/main/groovy/io/micronaut/build/MicronautBomPlugin.java +++ b/src/main/groovy/io/micronaut/build/MicronautBomPlugin.java @@ -64,10 +64,12 @@ import org.gradle.api.artifacts.VersionCatalog; import org.gradle.api.artifacts.VersionCatalogsExtension; import org.gradle.api.artifacts.VersionConstraint; +import org.gradle.api.artifacts.component.ComponentSelector; import org.gradle.api.artifacts.component.ModuleComponentIdentifier; import org.gradle.api.artifacts.result.ResolvedArtifactResult; import org.gradle.api.artifacts.result.ResolvedDependencyResult; import org.gradle.api.artifacts.result.ResolvedVariantResult; +import org.gradle.api.artifacts.result.UnresolvedDependencyResult; import org.gradle.api.attributes.Category; import org.gradle.api.attributes.Usage; import org.gradle.api.component.AdhocComponentWithVariants; @@ -92,6 +94,7 @@ import java.io.File; import java.io.FileInputStream; +import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Files; @@ -102,6 +105,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -154,6 +158,7 @@ public void apply(Project project) { bomExtension.getExcludedInlinedAliases().convention(Set.of()); bomExtension.getInlineRegularBOMs().convention(false); bomExtension.getInferProjectsToInclude().convention(true); + bomExtension.getCatalogName().convention("libs"); configureBOM(project, bomExtension); mavenModelResolver = new SimpleMavenModelResolver(project.getConfigurations(), project.getDependencies()); createHelperConfigurations(project); @@ -280,7 +285,7 @@ private void configureLate(Project project, MicronautBomExtension bomExtension, String group = String.valueOf(project.getGroup()); Optional versionCatalog = findVersionCatalog(project, bomExtension); final VersionCatalogConverter modelConverter = new VersionCatalogConverter( - project.getRootProject().file("gradle/libs.versions.toml"), + project.getRootProject().file("gradle/" + bomExtension.getCatalogName().get() + ".versions.toml"), project.getExtensions().findByType(CatalogPluginExtension.class) ); var libraryDefinitions = new ArrayList(); @@ -445,6 +450,31 @@ public void execute(Task task) { runtime.getAllDependencyConstraints().forEach(MicronautBomPlugin::checkVersionConstraint); maybeInlineNestedCatalogs(logFile, catalogArtifacts, bomArtifacts, builderState, inlineNestedCatalogs, inlineNestedBOMs, excludedInlinedAliases, includedAliases, inlinedPomProperties, inlinedMavenDependencies, project); performVersionInference(project, bomExtension, builderState, libraryDefinitions, inlinedPomProperties, inlinedMavenDependencies, project.getConfigurations().findByName(BOM_VERSION_INFERENCE_CONFIGURATION_NAME)); + try (var writer = new PrintWriter(new FileWriter(logFile.toFile(), true))) { + var unresolvedDependencies = new LinkedHashSet(); + catalogs.getIncoming() + .getResolutionResult() + .allDependencies(dep -> { + if (dep instanceof UnresolvedDependencyResult unresolved) { + unresolvedDependencies.add(unresolved.getRequested()); + } + }); + allBoms.getIncoming() + .getResolutionResult() + .allDependencies(dep -> { + if (dep instanceof UnresolvedDependencyResult unresolved) { + unresolvedDependencies.add(unresolved.getRequested()); + } + }); + if (!unresolvedDependencies.isEmpty()) { + writer.println("[WARNING] There were unresolved dependencies during inlining! This may cause incomplete catalogs!"); + for (ComponentSelector unresolvedDependency : unresolvedDependencies) { + writer.println(" " + unresolvedDependency); + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } }); projectDescriptors.get().forEach(p -> { String moduleGroup = p.getGroupId(); @@ -1062,7 +1092,7 @@ private static Optional findVersionCatalog(Project project, Micr return Optional.empty(); } VersionCatalogsExtension versionCatalogsExtension = project.getExtensions().findByType(VersionCatalogsExtension.class); - return Optional.ofNullable(versionCatalogsExtension).flatMap(e -> e.find("libs")); + return Optional.ofNullable(versionCatalogsExtension).flatMap(e -> e.find(bomExtension.getCatalogName().get())); } private void configureVersionCatalog(Project project, MicronautBomExtension bomExtension, String publishedName, String group, String mainProjectId) { diff --git a/src/main/groovy/io/micronaut/build/pom/MicronautBomExtension.java b/src/main/groovy/io/micronaut/build/pom/MicronautBomExtension.java index 7f193987..26f465fa 100644 --- a/src/main/groovy/io/micronaut/build/pom/MicronautBomExtension.java +++ b/src/main/groovy/io/micronaut/build/pom/MicronautBomExtension.java @@ -31,6 +31,13 @@ * Extension to configure BOM projects. */ public interface MicronautBomExtension { + /** + * Specifies the name of the catalog to use. + * Defaults to "libs" + * @return the catalog to use + */ + Property getCatalogName(); + /** * Excludes projects from the BOM. Any call to this * method will override the default spec which excludes diff --git a/src/main/java/io/micronaut/build/MicronautBuildSettingsExtension.java b/src/main/java/io/micronaut/build/MicronautBuildSettingsExtension.java index 6dc572f1..708f942b 100644 --- a/src/main/java/io/micronaut/build/MicronautBuildSettingsExtension.java +++ b/src/main/java/io/micronaut/build/MicronautBuildSettingsExtension.java @@ -142,15 +142,19 @@ private VersionCatalogTomlModel loadVersionCatalogTomlModel() { // Because we're a settings plugin, the "libs" version catalog // isn't available yet. So we have to parse it ourselves to find // the micronaut version! - File versionCatalog = new File(settings.getRootDir(), "gradle/libs.versions.toml"); - if (versionCatalog.exists()) { + File catalogsDir = new File(settings.getRootDir(), "gradle"); + if (catalogsDir.exists()) { LenientVersionCatalogParser parser = new LenientVersionCatalogParser(); - try (InputStream in = Files.newInputStream(versionCatalog.toPath())) { - parser.parse(in); - return parser.getModel(); - } catch (IOException e) { - throw new RuntimeException(e); - } + Arrays.stream(catalogsDir.listFiles()) + .filter(f -> f.getName().endsWith(".versions.toml")) + .forEach(f -> { + try (InputStream in = Files.newInputStream(f.toPath())) { + parser.parse(in); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + return parser.getModel(); } return null; } @@ -182,9 +186,9 @@ private String determineMicronautVersion(String moduleNameKebabCase) { if (!micronautVersion.isPresent()) { String capitalizedName = moduleNameKebabCase.charAt(0) + Arrays.stream(moduleNameKebabCase.split("-")) - .map(StringUtils::capitalize) - .collect(Collectors.joining()) - .substring(1) + .map(StringUtils::capitalize) + .collect(Collectors.joining()) + .substring(1) + "Version"; micronautVersion = Optional.ofNullable(getProviders().gradleProperty(capitalizedName).getOrNull()); } @@ -263,8 +267,8 @@ public void importMicronautCatalogFromGAV(String gavCoordinates) { artifactId = artifactId.substring(0, artifactId.length() - 4); } name += Arrays.stream(artifactId.split("-")) - .map(StringUtils::capitalize) - .collect(Collectors.joining()); + .map(StringUtils::capitalize) + .collect(Collectors.joining()); mgmt.getVersionCatalogs().create(name, catalog -> catalog.from(gavCoordinates)); } else { throw new IllegalStateException("Invalid version catalog GAV coordinates: " + gavCoordinates + ". Expected format: group:artifact:version"); @@ -289,22 +293,22 @@ public void importMicronautCatalog(String alias) { settings.dependencyResolutionManagement(mgmt -> { configureRepositories(mgmt); String gavCoordinates = versionCatalogTomlModel.getLibrariesTable() - .stream() - .filter(lib -> lib.getAlias().equals(alias)) - .findFirst() - .map(library -> { - String version; - if (library.getVersion().getReference() != null) { - version = versionCatalogTomlModel.findVersion(library.getVersion().getReference()) - .map(VersionModel::getVersion) - .map(RichVersion::getRequire) - .orElse(null); - } else { - version = library.getVersion().getVersion().getRequire(); - } - return library.getGroup() + ":" + library.getName() + ":" + version; - }) - .orElseThrow(() -> new IllegalStateException("Version catalog doesn't contain a library with alias: " + alias)); + .stream() + .filter(lib -> lib.getAlias().equals(alias)) + .findFirst() + .map(library -> { + String version; + if (library.getVersion().getReference() != null) { + version = versionCatalogTomlModel.findVersion(library.getVersion().getReference()) + .map(VersionModel::getVersion) + .map(RichVersion::getRequire) + .orElse(null); + } else { + version = library.getVersion().getVersion().getRequire(); + } + return library.getGroup() + ":" + library.getName() + ":" + version; + }) + .orElseThrow(() -> new IllegalStateException("Version catalog doesn't contain a library with alias: " + alias)); List parts = Arrays.asList(gavCoordinates.split(":")); String groupId = parts.get(0); String artifactId = parts.get(1); @@ -320,8 +324,8 @@ public void importMicronautCatalog(String alias) { artifactId = artifactId.substring(0, artifactId.length() - 4); } name += Arrays.stream(artifactId.split("-")) - .map(StringUtils::capitalize) - .collect(Collectors.joining()); + .map(StringUtils::capitalize) + .collect(Collectors.joining()); mgmt.getVersionCatalogs().create(name, catalog -> catalog.from(gavCoordinates)); } else { throw new IllegalStateException("Invalid version catalog GAV coordinates: " + gavCoordinates + ". Expected format: group:artifact:version");