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

Migrate dependencies.yml to Gradle's version catalogs #4353

Merged
merged 11 commits into from
Aug 1, 2022

Conversation

ikhoon
Copy link
Contributor

@ikhoon ikhoon commented Jul 15, 2022

Motivation:

We can declare dependency versions using dependencies.yml and share them
across multiple projects. It is useful to manage the versions of various
dependencies. However, we can't define different versions of a module.
Because the unique keys in dependencies.yml are moduleId:artifactId.

This limitation makes it difficult to manage compatibility between
different versions of a library. For example, okhttp v4 is required to
test it:okhttp and okhttp v3 is required to run retrofit2 module.

Gradle introduced a new way to share dependency versions between projects.
The unique key of version catalogs is a user-defined alias so we can
define multiple versions of a module using different aliases.

Version catalogs do not allow extra properties on libs.versions.toml.
It only allows some properties for versions and modules.
dependencies.yml not only manages versions but also manages metadata
for a module such as relocations, exclusions and Javadoc links.

I wanted to take advantage of both. We need a version manager that
supports version catalogs based on aliases, and the ability to add the
metadata. As a result, I implemented to add our own dependency mechanism
using dependencies.toml that is fully compatible with Gradle's version
catalogs and understands relocations, exclusions and Javadoc links
declarations.

Modifications:

  • Migrate dependencies.yml to dependencies.toml
  • Rename common-dependences.gradle to common-dependences-lagacy.gradle
    for backward compatibility with dependencies.yml
    • Newly added common-dependences.gradle handles the dependencies declared by dependencies.toml
  • Add version-catalog.gradle that parses dependencies.toml and builds:
    • Library and BOM version catalogs
    • relocations
    • exclusions
    • Javadoc links
  • Migrate all dependencies defined in build.gradle files to the new version catalog API.

Result:

Fixes #4120

Motivation:

We can declare dependency versions using `dependencies.yml` and share it
across multiple projects. It is useful to manage the versions of various
dependencies. However, we can't define different versions of a module.
Because the unique keys in `dependencies.yml` are `moduleId:artifactId`.

This limitation makes it difficult to manage compatibility between
different versions of a library. For example, okhttp v4 is required to
test `it:okhttp` and okhttp v3 is required to run `retrofit2` module.

Gradle introduced a new way to [share dependency version between projects](https://docs.gradle.org/current/userguide/platforms.html).
The unique key of version catalogs is a user-defined alias so we can
define multiple versions of a module using different aliases.

Version catalogs does not allow extra properies on `libs.versions.toml`.
It only allow some properties for versions and modules.
`dependencies.yml` not only manages versions, but also manages metadata
for a module such as relocations, exclusions and javadoc links.

I wanted to take advantage of both. We need a version manager that
supports version catalogs based on aliases, and ability to add the
metadata. As a result, I implmented to add our own dependency machanism
using `dependencies.toml` that is fully compatible with Gradle's version
catalogs and understands relocations, exclusions and javadoc links
declearations.

Modifications:

- Migrate `dependencies.yml` to `dependencies.toml`
- TBU

Result:

- Fixes line#4120
@ikhoon ikhoon added the cleanup label Jul 15, 2022
@codecov
Copy link

codecov bot commented Jul 15, 2022

Codecov Report

Merging #4353 (8e5d5bb) into master (7395a2e) will decrease coverage by 0.00%.
The diff coverage is n/a.

❗ Current head 8e5d5bb differs from pull request most recent head 6270b3d. Consider uploading reports for the commit 6270b3d to get more accurate results

@@             Coverage Diff              @@
##             master    #4353      +/-   ##
============================================
- Coverage     73.53%   73.52%   -0.01%     
+ Complexity    17648    17647       -1     
============================================
  Files          1500     1500              
  Lines         66010    66010              
  Branches       8328     8328              
============================================
- Hits          48540    48534       -6     
- Misses        13254    13265      +11     
+ Partials       4216     4211       -5     
Impacted Files Coverage Δ
...com/linecorp/armeria/common/metric/MoreMeters.java 78.75% <0.00%> (-8.75%) ⬇️
...m/linecorp/armeria/client/DecodedHttpResponse.java 80.00% <0.00%> (-5.00%) ⬇️
.../linecorp/armeria/client/retrofit2/PipeBuffer.java 84.44% <0.00%> (-4.45%) ⬇️
...meria/client/DefaultDnsQueryLifecycleObserver.java 76.81% <0.00%> (-2.90%) ⬇️
...easy/ResteasyAsynchronousExecutionContextImpl.java 53.48% <0.00%> (-2.33%) ⬇️
...rmeria/common/stream/ConcatArrayStreamMessage.java 82.22% <0.00%> (-2.23%) ⬇️
.../linecorp/armeria/client/Http2ResponseDecoder.java 68.05% <0.00%> (-2.09%) ⬇️
.../com/linecorp/armeria/server/docs/ServiceInfo.java 78.94% <0.00%> (-1.76%) ⬇️
...a/internal/common/stream/ByteBufsDecoderInput.java 84.89% <0.00%> (-1.44%) ⬇️
...com/linecorp/armeria/client/RedirectingClient.java 72.00% <0.00%> (-0.45%) ⬇️
... and 9 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7395a2e...6270b3d. Read the comment docs.

@ikhoon ikhoon marked this pull request as ready for review July 15, 2022 15:20
Copy link
Contributor

@minwoox minwoox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's way simpler! Looks great! 😄

annotation-processor/build.gradle Outdated Show resolved Hide resolved
build.gradle Show resolved Hide resolved
build.gradle Outdated Show resolved Hide resolved
compileOnly 'com.google.code.findbugs:jsr305'
compile 'com.google.guava:guava'
compileOnly libs.findbugs
implementation libs.guava
}
}

// In case you need to get the version number of an artifact:
println "Guava version: ${managedVersions['com.google.guava:guava']}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to use libs...get()?

dependencies.toml Outdated Show resolved Hide resolved
gradle/scripts/lib/java-alpn.gradle Show resolved Hide resolved
gradle/scripts/lib/scala.gradle Show resolved Hide resolved
gradle/scripts/version-catalogs.gradle Outdated Show resolved Hide resolved
Copy link
Contributor

@jrhee17 jrhee17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly looks good! Only left a few questions 👍

build.gradle Outdated
@@ -314,3 +310,32 @@ class TestsReportTask extends DefaultTask {
}
}
}

// Prints all versions registered through 'dependencies.toml'
tasks.register("printVersionCatalogs") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question) Would this task be useful for other gradle-script users as well?
(I think it's fine to leave here for now though)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is useful to debug some dependencies. Let me move it to version-catalogs.gradle

dependencies.toml Outdated Show resolved Hide resolved
dependencies.toml Show resolved Hide resolved
thrift0.16/build.gradle Show resolved Hide resolved
}
}

// In case you need to get the version number of an artifact:
println "Guava version: ${managedVersions['com.google.guava:guava']}"
// Note that it is not recommended to use `managedVersions` with the module defined multiple times with
// different aliases. Because if a module is declared with different versions, the version returned by
// `managedVersions` is determined by how the version catalogs are indexed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, so it is possible that the version returned by managedVersions isn't necessarily equal to the eventually resolved version. Am I understanding correctly?

Copy link
Contributor Author

@ikhoon ikhoon Jul 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

managedVersions can be safely used when a groupId:artifactId is declared only once in a whole dependencies.toml.

Let's say the following dependencies are defined.

[libraries.jsoup]
module = "org.jsoup:jsoup"
version = "1.15.1"

[libraries.thrift09]
module = "org.apache.thrift:libthrift"
version = "0.9.3-1"
[libraries.thrift012]
module = "org.apache.thrift:libthrift"
version = "0.12.0"

We can assume that managedVersions['org.jsoup:jsoup'] returns "1.15.1". However, we can't assert whether managedVersions['org.apache.thrift:libthrift'] returns "0.9.3-1" or "0.12.0".

Copy link
Contributor

@jrhee17 jrhee17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming the generated artifacts are the same before/after the change. Looks good to me 👍

@jrhee17 jrhee17 added this to the 1.18.0 milestone Jul 28, 2022
Copy link
Contributor

@minwoox minwoox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build script is much simplified! Thanks, @ikhoon!

tomcat9 = "9.0.62"

[boms]
brave = { module = "io.zipkin.brave:brave-bom", version = "5.13.9" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the convention of specifying version is that

  • the version is inlined if it's used only once.
  • the version is specified in [versions] section if it's used more than once.
    Is that correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. But we can freely change the convention anytime. 😆

@minwoox
Copy link
Contributor

minwoox commented Jul 29, 2022

We have to also check if https://github.com/line/armeria-examples/blob/master/update-examples.sh is working correctly before merging this. 😉

@ikhoon
Copy link
Contributor Author

ikhoon commented Aug 1, 2022

We have to also check if https://github.com/line/armeria-examples/blob/master/update-examples.sh is working correctly before merging this. 😉

update-examples.sh should not work at all. I'd like to fix it in the f/u PR before we release a new version.

@ikhoon
Copy link
Contributor Author

ikhoon commented Aug 1, 2022

Let me merge this PR without waiting for CI builds because the last commit only changed gradle/scritps/README.md.

@ikhoon ikhoon merged commit 0d3fa08 into line:master Aug 1, 2022
@ikhoon ikhoon deleted the gradle-catalog-depedencies branch August 1, 2022 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use version catalogs for dependency management
3 participants