I’m Using gradle 3.5.
I want to be able to have a “customization” on top of ResolutionStrategy’s failOnVersionConflict() - i’ll explain:
We have internal packages versioned x.y.z where a change in x is not backward compatible.
I want to do a check and fail if any of my transitive dependencies are using 2 versions of the same artifact in which the value of x is different.
In example:
group:artifact:1.0.0
group:artifact:2.0.0 --> this should fail the build
Of course the test needs to take transitive dependencies into account.
I looked at resolutionStrategy and did not find anything which will allow me to do that.
I also tried doing something like this:
You could use a dependency resolution rule to error if someone is asking for a version other than what you expect.
configurations {
compile.resolutionStrategy.eachDependency { details ->
if (details.requested.group == 'group' && details.requested.name == 'artifact' && details.requested.version != 'x.y.z') {
throw new RuntimeException("Someone is asking for a different version of my module than expected")
}
}
}
This would of course just notify you. If you want to simply avoid this situation altogether you could always just force the version you expect.
First - thanks for the reply, but I think it’s not what I’m looking for:
The code you posted does not run for me- I had to replace “eachDependency” with “dependencies.each” for it to run
This seems to be going over direct dependencies - not transitive ones
I have tens of artifacts and they are updated rapidly. For the dependency list I maintain - I wish to maintain it once and not in multiple places (as in not mention specific versions in more than one place).
Even if I could maintain the list once (pretty sure I can) and even if it was transitive - I still do not understand how that solves my issue - let’s imagine the following scenario:
I’m working on module A. A’s compile depends on artifacts B and C.
B depends on D [x.y.z] and C depends D [k.l.m] where k!=x. I as the developer of A - do not want to know I need D, let alone specify it’s specific version - because then it beats the whole purpose of transitive dependencies.
Like I mentioned - I’m looking to access the raw transitive dependencies before (or while) the resolution strategy takes place - something similar to the information available to task of type DependencyReportTask - it shows all version conflicts and how they were resolved (i.e lower version -> higher version).
I have tried using this but it either does nothing or I’m using it wrong.
I need to be able to compare 2 versions of the same artifact in the raw transitive dependencies before they are resolved. I DON’T want to restrict a specific version.
You can’t get this before resolution unfortunately. The report you referenced above is produced by resolving the dependency graph. You can get at that same information via the API though. If you want to know where all the conflicts are you can simply say “for all my resolved dependencies, where is the thing requested not the thing actually selected”. This basically tells you anywhere conflict resolution kicks in.
The source of this info is going to be aResolvedDependencyResult. You can get at this by doing something like:
Thanks - the last code you provided helped me get what I wanted.
p.s it needs to be allDependencies and not just dependencies (your original code did not compile)
Here is my code (working in gradle 3.5):
configurations.all {
incoming.afterResolve { resolveableDependencies ->
resolveableDependencies.resolutionResult.allDependencies.findAll { dep ->
(dep.requested instanceof ModuleComponentSelector ||
dep.requested instanceof ResolvedComponentResult) &&
dep.requested.group.equalsIgnoreCase("our_group_name")
}.each { /*DefaultResolvedDependencyResult*/ dep ->
def requestedMajor
def selectedMajor
if (dep.requested instanceof ResolvedComponentResult) {
requestedMajor = dep.requested.moduleVersion.version.tokenize('.')[0]
} else { //ModuleComponentSelector
requestedMajor = dep.requested.version.tokenize('.')[0]
}
if (dep.selected instanceof ResolvedComponentResult) {
selectedMajor = dep.selected.moduleVersion.version.tokenize('.')[0]
} else { //ModuleComponentSelector
selectedMajor = dep.selected.version.tokenize('.')[0]
}
if (requestedMajor != selectedMajor)
throw new Exception("requested=${dep.requested} and selected=${dep.selected} have different major versions")
}
}
}
Is there a simpler way (especially regarding ResolvedComponentResult vs ModuleComponentSelector)?
Thanks again,
Mor