From e9cf48bbe8a84953e2e000fb9711fe1a0ee0cfe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Champeau?= Date: Wed, 9 Mar 2022 12:04:46 +0100 Subject: [PATCH] Use a single version for all project properties in BOM/catalog (#285) This commit updates the BOM/catalog file generation, so that instead of generating a distinct property name for each project of a multi-project build, we generate a single property. For example, before if a project `europe` had `europe-france` and `europe-ukraine` as subprojects, then the generated BOM/catalog would contain properties/versions named `micronaut.europe.france` and `micronaut.europe.ukraine`. Now, the only generated property would be `micronaut.europe`. The name of the property to use is derived from the root project name. It handles the case where the root project name contains `-parent`. If the automated property isn't derived properly, it is possible to explicitly configure it via the `micronautBom` extension. In the example above, one could write: ```gradle micronautBom { propertyName = 'supports' } ``` then the generated property names would become: `micronaut.supports.france` and `micronaut.supports.ukraine`. Fixes #284 --- .../multi-project-bom/build.gradle | 4 + .../freedom-bar/build.gradle | 3 + .../freedom-bom/build.gradle | 3 + .../freedom-foo/build.gradle | 3 + .../multi-project-bom/gradle.properties | 20 +++ .../multi-project-bom/settings.gradle | 5 + .../build/AbstractFunctionalTest.groovy | 7 ++ .../BomGenerationFunctionalTest.groovy | 118 +++++++++++++++++- .../micronaut/build/MicronautBomPlugin.java | 19 +-- .../build/pom/MicronautBomExtension.java | 7 ++ 10 files changed, 180 insertions(+), 9 deletions(-) create mode 100644 src/functionalTest/gradle-projects/multi-project-bom/build.gradle create mode 100644 src/functionalTest/gradle-projects/multi-project-bom/freedom-bar/build.gradle create mode 100644 src/functionalTest/gradle-projects/multi-project-bom/freedom-bom/build.gradle create mode 100644 src/functionalTest/gradle-projects/multi-project-bom/freedom-foo/build.gradle create mode 100644 src/functionalTest/gradle-projects/multi-project-bom/gradle.properties create mode 100644 src/functionalTest/gradle-projects/multi-project-bom/settings.gradle diff --git a/src/functionalTest/gradle-projects/multi-project-bom/build.gradle b/src/functionalTest/gradle-projects/multi-project-bom/build.gradle new file mode 100644 index 00000000..45d7dee3 --- /dev/null +++ b/src/functionalTest/gradle-projects/multi-project-bom/build.gradle @@ -0,0 +1,4 @@ +allprojects { + group = 'io.micronaut.freedom' + version = projectVersion +} diff --git a/src/functionalTest/gradle-projects/multi-project-bom/freedom-bar/build.gradle b/src/functionalTest/gradle-projects/multi-project-bom/freedom-bar/build.gradle new file mode 100644 index 00000000..401cfa3c --- /dev/null +++ b/src/functionalTest/gradle-projects/multi-project-bom/freedom-bar/build.gradle @@ -0,0 +1,3 @@ +plugins { + id 'io.micronaut.build.internal.module' +} diff --git a/src/functionalTest/gradle-projects/multi-project-bom/freedom-bom/build.gradle b/src/functionalTest/gradle-projects/multi-project-bom/freedom-bom/build.gradle new file mode 100644 index 00000000..a2429aa5 --- /dev/null +++ b/src/functionalTest/gradle-projects/multi-project-bom/freedom-bom/build.gradle @@ -0,0 +1,3 @@ +plugins { + id 'io.micronaut.build.internal.bom' +} diff --git a/src/functionalTest/gradle-projects/multi-project-bom/freedom-foo/build.gradle b/src/functionalTest/gradle-projects/multi-project-bom/freedom-foo/build.gradle new file mode 100644 index 00000000..401cfa3c --- /dev/null +++ b/src/functionalTest/gradle-projects/multi-project-bom/freedom-foo/build.gradle @@ -0,0 +1,3 @@ +plugins { + id 'io.micronaut.build.internal.module' +} diff --git a/src/functionalTest/gradle-projects/multi-project-bom/gradle.properties b/src/functionalTest/gradle-projects/multi-project-bom/gradle.properties new file mode 100644 index 00000000..2bceefc8 --- /dev/null +++ b/src/functionalTest/gradle-projects/multi-project-bom/gradle.properties @@ -0,0 +1,20 @@ +projectVersion=1.2.3 +projectGroup=io.micronaut.freedom +micronautDocsVersion=2.0.0.RC1 +micronautVersion=3.2.0 +micronautTestVersion=2.3.7 +groovyVersion=3.0.8 +spockVersion=2.0-groovy-3.0 +title=Micronaut BOM test module +projectDesc=BOM and version catalogs +projectUrl=https://micronaut.io +githubSlug=micronaut-projects/micronaut-bom-test-module +developers=Graeme Rocher + +# Micronaut core branch for BOM pull requests +githubCoreBranch=3.2.x + +bomProperty=micronautBomVersion + +org.gradle.caching=true +org.gradle.parallel=true diff --git a/src/functionalTest/gradle-projects/multi-project-bom/settings.gradle b/src/functionalTest/gradle-projects/multi-project-bom/settings.gradle new file mode 100644 index 00000000..26ec86b1 --- /dev/null +++ b/src/functionalTest/gradle-projects/multi-project-bom/settings.gradle @@ -0,0 +1,5 @@ +rootProject.name = "freedom" + +include "freedom-bom" +include "freedom-foo" +include "freedom-bar" diff --git a/src/functionalTest/groovy/io/micronaut/build/AbstractFunctionalTest.groovy b/src/functionalTest/groovy/io/micronaut/build/AbstractFunctionalTest.groovy index d808736a..e2e4547a 100644 --- a/src/functionalTest/groovy/io/micronaut/build/AbstractFunctionalTest.groovy +++ b/src/functionalTest/groovy/io/micronaut/build/AbstractFunctionalTest.groovy @@ -22,6 +22,7 @@ import org.gradle.util.GFileUtils import spock.lang.Specification import spock.lang.TempDir +import java.nio.file.Files import java.nio.file.Path abstract class AbstractFunctionalTest extends Specification { @@ -174,4 +175,10 @@ abstract class AbstractFunctionalTest extends Specification { } } } + + protected void dumpRepoContents() { + Files.walk(file("build/repo").toPath()).forEach { + println(it.toString()) + } + } } diff --git a/src/functionalTest/groovy/io/micronaut/build/catalogs/BomGenerationFunctionalTest.groovy b/src/functionalTest/groovy/io/micronaut/build/catalogs/BomGenerationFunctionalTest.groovy index 9bba37a7..d617b80c 100644 --- a/src/functionalTest/groovy/io/micronaut/build/catalogs/BomGenerationFunctionalTest.groovy +++ b/src/functionalTest/groovy/io/micronaut/build/catalogs/BomGenerationFunctionalTest.groovy @@ -1,6 +1,7 @@ package io.micronaut.build.catalogs -import io.micronaut.build.AbstractFunctionalTest +import io.micronaut.build.AbstractFunctionalTest +import spock.lang.Issue class BomGenerationFunctionalTest extends AbstractFunctionalTest { def "inlines Micronaut catalogs into the generated catalog"() { @@ -99,4 +100,119 @@ micronaut-function-client-aws = {group = "io.micronaut.aws", name = "micronaut-f micronaut-test-bom-module = {group = "io.micronaut.dummy", name = "micronaut-test-bom-module", version.ref = "micronaut-test-bom-module" } """.trim() } + + @Issue("https://github.com/micronaut-projects/micronaut-build/issues/284") + def "uses a single version for all subprojects"() { + withSample("multi-project-bom") + settingsFile.text += """rootProject.name = '$rootName' """ + + when: + run 'publishAllPublicationsToBuildRepository' + + then: + def moduleDir = file("build/repo/io/micronaut/freedom/micronaut-freedom-bom/1.2.3") + def catalogFile = new File(moduleDir, "micronaut-freedom-bom-1.2.3.toml") + moduleDir.exists() + catalogFile.exists() + println catalogFile.text + catalogFile.text.trim() == """# +# This file has been generated by Gradle and is intended to be consumed by Gradle +# +[metadata] +format.version = "1.1" + +[versions] +micronaut-freedom = "1.2.3" + +[libraries] +micronaut-freedom-bar = {group = "io.micronaut.freedom", name = "micronaut-freedom-bar", version.ref = "micronaut-freedom" } +micronaut-freedom-bom = {group = "io.micronaut.freedom", name = "micronaut-freedom-bom", version.ref = "micronaut-freedom" } +micronaut-freedom-foo = {group = "io.micronaut.freedom", name = "micronaut-freedom-foo", version.ref = "micronaut-freedom" } +""".trim() + + and: + def pomFile = new File(moduleDir, "micronaut-freedom-bom-1.2.3.pom") + pomFile.exists() + println pomFile.text + pomFile.text.contains """ + 1.2.3 + """ + pomFile.text.contains """ + + + io.micronaut.freedom + micronaut-freedom-bar + \${micronaut.freedom.version} + + + io.micronaut.freedom + micronaut-freedom-foo + \${micronaut.freedom.version} + + + """ + + where: + rootName << ['freedom', 'freedom-parent'] + } + + @Issue("https://github.com/micronaut-projects/micronaut-build/issues/284") + def "can explicitly define the main property name"() { + withSample("multi-project-bom") + settingsFile.text += """rootProject.name = '$rootName' """ + file("freedom-bom/build.gradle") << """ +micronautBom { + propertyName = 'democracy' +} + """ + + when: + run 'publishAllPublicationsToBuildRepository' + + then: + def moduleDir = file("build/repo/io/micronaut/freedom/micronaut-freedom-bom/1.2.3") + def catalogFile = new File(moduleDir, "micronaut-freedom-bom-1.2.3.toml") + moduleDir.exists() + catalogFile.exists() + println catalogFile.text + catalogFile.text.trim() == """# +# This file has been generated by Gradle and is intended to be consumed by Gradle +# +[metadata] +format.version = "1.1" + +[versions] +micronaut-democracy = "1.2.3" + +[libraries] +micronaut-freedom-bar = {group = "io.micronaut.freedom", name = "micronaut-freedom-bar", version.ref = "micronaut-democracy" } +micronaut-freedom-bom = {group = "io.micronaut.freedom", name = "micronaut-freedom-bom", version.ref = "micronaut-democracy" } +micronaut-freedom-foo = {group = "io.micronaut.freedom", name = "micronaut-freedom-foo", version.ref = "micronaut-democracy" } +""".trim() + + and: + def pomFile = new File(moduleDir, "micronaut-freedom-bom-1.2.3.pom") + pomFile.exists() + println pomFile.text + pomFile.text.contains """ + 1.2.3 + """ + pomFile.text.contains """ + + + io.micronaut.freedom + micronaut-freedom-bar + \${micronaut.democracy.version} + + + io.micronaut.freedom + micronaut-freedom-foo + \${micronaut.democracy.version} + + + """ + + where: + rootName << ['freedom', 'freedom-parent'] + } } diff --git a/src/main/groovy/io/micronaut/build/MicronautBomPlugin.java b/src/main/groovy/io/micronaut/build/MicronautBomPlugin.java index a5051a1c..a8cea1ab 100644 --- a/src/main/groovy/io/micronaut/build/MicronautBomPlugin.java +++ b/src/main/groovy/io/micronaut/build/MicronautBomPlugin.java @@ -184,6 +184,7 @@ private void configureBOM(Project project, MicronautBomExtension bomExtension) { } private void configureLate(Project project, MicronautBomExtension bomExtension, PublishingExtension publishing, TaskContainer tasks) { + String mainProjectId = bomExtension.getPropertyName().getOrElse(project.getRootProject().getName().replace("-parent", "").replace('-', '.')); String publishedName = "micronaut-" + project.getName(); String group = String.valueOf(project.getGroup()); Optional versionCatalog = findVersionCatalog(project, bomExtension); @@ -193,7 +194,7 @@ private void configureLate(Project project, MicronautBomExtension bomExtension, ); tasks.named("generateCatalogAsToml", task -> modelConverter.populateModel()); if (bomExtension.getPublishCatalog().get()) { - configureVersionCatalog(project, bomExtension, publishedName, group); + configureVersionCatalog(project, bomExtension, publishedName, group, mainProjectId); } publishing.getPublications().named("maven", MavenPublication.class, pub -> { pub.setArtifactId(publishedName); @@ -226,7 +227,7 @@ private void configureLate(Project project, MicronautBomExtension bomExtension, // Add individual module versions as properties forEachProject(bomExtension, project, p -> { - String propertyName = "micronaut." + p.getName().replace('-', '.') + ".version"; + String propertyName = "micronaut." + mainProjectId + ".version"; String projectGroup = String.valueOf(p.getGroup()); Optional pomDep = forEachNode(node, DEPENDENCY_PATH) .filter(n -> childOf(n, "artifactId").text().equals("micronaut-" + p.getName()) && @@ -249,7 +250,7 @@ private void configureLate(Project project, MicronautBomExtension bomExtension, })); forEachProject(bomExtension, project, p -> { project.evaluationDependsOn(p.getPath()); - String propertyName = "micronaut." + p.getName().replace('-', '.') + ".version"; + String propertyName = "micronaut." + mainProjectId + ".version"; pom.getProperties().put(propertyName, assertVersion(p)); }); }); @@ -288,8 +289,9 @@ private void configureLate(Project project, MicronautBomExtension bomExtension, .create(moduleGroup + ":" + moduleName + ":" + moduleVersion) ); - modelConverter.getExtraVersions().put(moduleName, moduleVersion); - modelConverter.getExtraLibraries().put(moduleName, VersionCatalogConverter.library(moduleGroup, moduleName, moduleName)); + String mainModuleName = "micronaut-" + mainProjectId.replace('.', '-'); + modelConverter.getExtraVersions().put(mainModuleName, moduleVersion); + modelConverter.getExtraLibraries().put(moduleName, VersionCatalogConverter.library(moduleGroup, moduleName, mainModuleName)); }); } @@ -352,12 +354,13 @@ private static Optional findVersionCatalog(Project project, Micr return Optional.ofNullable(versionCatalogsExtension).map(e -> e.named("libs")); } - private void configureVersionCatalog(Project project, MicronautBomExtension bomExtension, String publishedName, String group) { + private void configureVersionCatalog(Project project, MicronautBomExtension bomExtension, String publishedName, String group, String mainProjectId) { if (bomExtension.getIncludeBomInCatalog().get()) { CatalogPluginExtension catalog = project.getExtensions().getByType(CatalogPluginExtension.class); catalog.versionCatalog(vc -> { - String versionName = publishedName.replace('-', '.'); - vc.alias(publishedName).to(group, publishedName).versionRef(versionName); + String mainModuleName = "micronaut-" + mainProjectId; + String versionName = mainModuleName.replace('-', '.'); + vc.library(publishedName, group, publishedName).versionRef(versionName); vc.version(versionName, String.valueOf(project.getVersion())); }); } diff --git a/src/main/groovy/io/micronaut/build/pom/MicronautBomExtension.java b/src/main/groovy/io/micronaut/build/pom/MicronautBomExtension.java index 1ff4d953..6fa360c3 100644 --- a/src/main/groovy/io/micronaut/build/pom/MicronautBomExtension.java +++ b/src/main/groovy/io/micronaut/build/pom/MicronautBomExtension.java @@ -94,4 +94,11 @@ public interface MicronautBomExtension { * @return the ignored aliases */ SetProperty getExcludedInlinedAliases(); + + /** + * Defines the property name of the version of project dependencies, + * in case it cannot be deduced properly from the root project name + * @return the property name + */ + Property getPropertyName(); }