Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial work to modernize the Gradle build #6067

Merged
merged 5 commits into from
Sep 8, 2021

Conversation

melix
Copy link
Contributor

@melix melix commented Aug 27, 2021

This PR is work in progress and needs to be discussed with the team. I'm creating it now so that we can track progress and start discussion.

Please note that it requires changes to the micronaut-build project which I didn't include in this PR, so it will not build as is.

@melix melix force-pushed the cc/modernize-gradle branch from b4490ed to e8a320c Compare August 27, 2021 16:30
@donbeave
Copy link
Contributor

Do you have a plan to switch to Gradle Kotlin DSL?

@graemerocher
Copy link
Contributor

@donbeave no

@melix melix force-pushed the cc/modernize-gradle branch 2 times, most recently from 3ca3ded to 4f120da Compare August 31, 2021 16:39
@melix
Copy link
Contributor Author

melix commented Aug 31, 2021

This PR is now in a good shape, but depends on micronaut-projects/micronaut-build#187 first.

@melix
Copy link
Contributor Author

melix commented Sep 1, 2021

@alvarosanchez when refactoring this code, I had to update the bom checker. Do you remember why, for the BOMs which are imported, we check that their dependencies in the dependencyManagement have a group which starts with the group of the BOM? In other words, why do we check, say for org.testcontainers, that the dependencies in dependencyManagement of the test containers BOM, only have dependencies of the org.testcontainers group? Why do we need to check this? (off tipic, sorry for cross posting, wrong tab ;))

@graemerocher
Copy link
Contributor

@alvarosanchez answered in another thread but the reason was because some BOMs we imported were not "modules only" boms and included api dependencies in the BOMs which then overrode versions specified in our BOM when imported.

This was the case with the Oracle Cloud BOM. However since then we have moved to generating out own BOM for Oracle Cloud which works around this issue https://github.com/micronaut-projects/micronaut-oracle-cloud/blob/master/oraclecloud-bom/build.gradle

@melix
Copy link
Contributor Author

melix commented Sep 1, 2021

Thanks! Do you have the GAV coordinates of this BOM which was causing issues? I suppose it's the dreaded "parent POM published as BOM" issue.

@graemerocher
Copy link
Contributor

graemerocher commented Sep 1, 2021

Believe it was this one https://search.maven.org/artifact/com.oracle.oci.sdk/oci-java-sdk-bom/2.4.2/pom and the parent POM defines the conflicting dependencies

@melix melix force-pushed the cc/modernize-gradle branch 2 times, most recently from faee8ab to 6545bc7 Compare September 2, 2021 14:36
@ilopmar
Copy link
Contributor

ilopmar commented Sep 6, 2021

Another thing we need to change is the GitHub action we use to send PRs from modules and update versions in core: https://github.com/micronaut-projects/github-actions/tree/master/update-bom

@melix
Copy link
Contributor Author

melix commented Sep 6, 2021

Believe it was this one https://search.maven.org/artifact/com.oracle.oci.sdk/oci-java-sdk-bom/2.4.2/pom and the parent POM defines the conflicting dependencies

Alright so this is exactly the problem: a parent pom defines dependencies and then the BOM inherits from them.

Another thing we need to change is the GitHub action we use to send PRs from modules and update versions in core:

Thanks @ilopmar I'll take a look!

@melix melix force-pushed the cc/modernize-gradle branch 3 times, most recently from aec7bec to 177eb48 Compare September 7, 2021 14:59
@melix melix marked this pull request as ready for review September 8, 2021 09:04
@melix
Copy link
Contributor Author

melix commented Sep 8, 2021

This PR is ready for review. As discussed during the presentation of this work, we're going to publish a version catalog alongside the BOM. While we will probably not advertise this while the Gradle feature is in preview, it's worth discussing naming.

If you look at the libs.versions.toml file, some entries start with managed-, for example:

managed-azure-function = "1.4.2"

in the [versions] section or

managed-dekorate-jaeger-annotations = { module = "io.dekorate:jaeger-annotations", version.ref = "managed-dekorate" }

for the [libraries] section. Those names are not neutral. By convention in our build, anything which starts with managed- will appear in the BOM. In our build files, using a library such as the above means declaring:

implementation libs.managed.dekorate.jaeger.annotations

Note how the dashes are converted to dots in the DSL. This isn't neutral, as if you use the Kotlin DSL, completion is available, which means that if you start typing libs.managed.deko<CTRL+SPACE>, the IDE would complete to libs.managed.dekorate and show you the children of that node.

As I mentioned, we're going to publish a version catalog that users can import in their builds. If they do so, we remove all the "managed" parts, so for a user this would become:

implementation libs.dekorate.jaeger.annotations

Once published, it's a breaking change to rename the alias, so we must take particular care of naming. I would therefore suggest that we review carefully the libs.versions.toml file and make sure that all aliases make sense, and that their grouping makes sense. The advantage of dotted notations being that we can group libraries together.

This commit replaces the "dependencyVersion" and "dependencyModuleVersion"
calls with Gradle's version catalogs. In the process, I tried to clarify
what belongs to the BOM (as "managed" dependencies") vs what is not.

Currently this breaks BOM verification module, this will be fixed in
another commit. It will also probably break the automatic upgrading of
dependencies. However, the result is much cleaner: there are no duplicate
coordinates anymore in build files.
This commit introduces a new artifact published alongside the BOM:
a Gradle _version catalog_. A version catalog is not a replacement
for a BOM. It can be seen as an alternative, or a complement to a
BOM file.

For example, a user can import the Micronaut version catalog in
their settings file by doing:

```gradle
dependencyResolutionManagement {
    versionCatalogs {
        create("mn") {
            from("io.micronaut:micronaut-bom:3.0.1-SNAPSHOT")
        }
    }
}
```

Gradle will then generate _version accessors_, which allows
replacing dependency notations from:

```gradle
implementation "ch.qos.logback:logback-classic"
```

to:

```gradle
implementation mn.logback
```

Those accessors are _type safe_. Version catalogs should
really be seen as "recommendations". Without applying a
BOM in addition, the versions declared in a catalog have
_no impact_ on dependency resolution. Therefore, it is
often recommended to apply both the BOM _and_ use catalogs
to declare dependencies.

It comes with an advantage, which is that versions declared
in the BOM can be overridden by the user:

```gradle
dependencyResolutionManagement {
    versionCatalogs {
        create("mn") {
            from("io.micronaut:micronaut-bom:3.0.1-SNAPSHOT")
            version("snakeyaml") {
                strictly("1.28")
            }
        }
    }
}
```
It looks like it was a mistake that it wasn't present in the BOM already.
@melix melix force-pushed the cc/modernize-gradle branch from 304f603 to 21a0895 Compare September 8, 2021 16:17
@melix melix merged commit de34e4d into micronaut-projects:3.0.x Sep 8, 2021
@melix melix deleted the cc/modernize-gradle branch September 8, 2021 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants