ben-manes / gradle-versions-plugin

Gradle plugin to discover dependency updates
Apache License 2.0
3.86k stars 199 forks source link

Question: Display max minor and max overall versions? #841

Open LPmaverick opened 7 months ago

LPmaverick commented 7 months ago

For example, SpringBoot recommends updating to the latest 2.x version before making the jump to 3.x

So, say I have an application running SpringBoot 2.2.6. I would like a column to show 2.7.18 as the highest minor version and another column to show 3.2.2 as the highest overall version.

Is this at all possible with the current version of the library or would that be an enhancement?

ben-manes commented 7 months ago

It's a good idea that we never tried to implement. We discussed it in #69 as version breadcrumbs, e.g. org.mockito:mockito-all [1.10.18 -> 1.10.19 -> 1.11.5 -> 2.1.6]. I'd be open to a PR if interested, we just never got around to experimenting with the idea.

A concern is that unfortunately Gradle does not parallelize the dependency metadata requests (like Maven does), so those are sequentially evaluated. For large projects that is slow and this might require a few round trips if it looks at each pom.xml instead of only reusing the fetched maven-metadata.xml. That's not likely to be fixed soon (I opened a feature request over a decade ago), so it might have to be feature flagged if it incurs a performance penalty.

LPmaverick commented 7 months ago

I know nothing about the Gradle API so this question may be stupid, but is there an endpoint where you can provide group and name, and it give you the list of versions? My thinking is that if there is, can then run it through a function to obtain the Prod released versions and then run a version REGEX (based on the current version of a dependency) against the list and pull the highest minor version. Then of course, also pull the max version.

ben-manes commented 7 months ago

That would make sense if we inspected the versioning metadata directly. For example, if we looked at the maven-metadata.xml for a dependency. However, this plugin instead defers all of the resolution to Gradle since it has rich dependency management that we didn't want to reinvent. That let's us be consistent with resolution rules, constraints, security and proxying, etc. We resolve a copy of the source configuration using a dynamic version and compare the results. In this case we'd have to resolve +, 2.+, 2.2.+ to give you a breadcrumb of 2.2.6 -> 2.2.9 -> 2.7.9 -> 3.2.3. That would require two additional resolutions, or however many REGEX groups were found. Gradle would cache the top-level metadata but also will make a network call of the artifact's metadata (pom, module). Since they resolve metadata sequentially (but download jars in parallel) for large projects our scan could be slow. It is probably okay and I like this UX, but we never tried implementing the feature.

LPmaverick commented 6 months ago

Apologies for delayed response.

Coming back to this, wouldn't you only need to ask Gradle to resolve + (highest overall version) and 2.+ (highest minor of declared major)? I agree with handing it over to Gradle to do the heavy lifting.

ben-manes commented 6 months ago

Correct, but it would have to be resolved twice as two cloned configurations. If we added both dependency versions in a single configuration then it will always resolve to the latest once since you can't have duplicates of the same coordinate. In general we'd probably resolve the next major, next minor, next patch versions for 3x the number of resolutions. Since Gradle resolves sequentially, that might be slow for a large build as 3x the number of resolutions. However, since it is the same dependency, it might cache the metadata so the subsequent resolutions are instant. Therefore, I don't know if there is a performance penalty until we attempt this feature. As users often use --refresh-dependencies to disable the cache and query the repository for the latest updates, I don't know if it will cache within the run or those subsequent lookups will be equally slow.

LPmaverick commented 5 months ago

I swear I am not only responding once a month on purpose.

I have been thinking over this sporadically over the past month whenever the topic of dependency management comes up. As an alternative, what if I could provide this Gradle script a flag that would tell it that I want it to resolve the highest minor version instead? The default behavior of the script would continue as it currently is, finding the highest overall version. Could this approach solve the caching unknowns (and concern) of your last comment?

ben-manes commented 5 months ago

Yep. Those were the concerns / unknowns, but had we done the implementation work we’d know and could flag it if a concern. As a weekend project it’s open to PRs to anyone who has an itch as long as they don’t increase the plugin’s scope/burden substantially.