Search code examples
gradledependency-managementtransitive-dependency

How to mix ResolutionStrategies with Gradle


Let's say I have the following in my gradle build script:

configurations.all {
  resolutionStrategy {

    failOnVersionConflict()

    force 'com.google.guava:guava:18.0'
    }
}

This will fail if more than one version of a jar is found, except for guava where it will force to version 18.0.

Now let's imagine that I want to have failOnVersionConflict() for all external jars, and be forced to use the force clause (so I know what I'm doing), but I want to use the default resolutionStrategy (newest version) for some specific group, like com.mycompany.

Is such a thing possible?

I was looking at this documentation page:

https://gradle.org/docs/current/dsl/org.gradle.api.artifacts.ResolutionStrategy.html


Solution

  • I found my own answer... But it involves a bit of "hacking"... But, after all, that's just what gradle offers...

    def dependencyErrors = 0
    
    configurations.all {
      resolutionStrategy {
    
        def thirdPartyPackages = [:]
        def forced = [ 
            'com.google.guava:guava' : '18.0'
            //Here all forced dependencies...
        ]
    
    
         eachDependency { DependencyResolveDetails details ->
    
    
              if (!details.requested.group.startsWith('com.mycompany')) {
    
                    def key = details.requested.group + ":" + details.requested.name
                    if(!thirdPartyPackages.containsKey(key)) {
                        if(forced.containsKey(key)) {
                            details.useVersion forced.get(key)
                        }                   
                        else {
                            thirdPartyPackages.put(key, details.requested.version);
                        }
                    }
                    else {
                        def existing =  thirdPartyPackages.get(key);
                        if(existing != details.requested.version) {
                            logger.error "Conflicting versions for [$key]"
                            logger.error "    [$existing]"
                            logger.error "    [$details.requested.version]"
                            dependencyErrors++
                        }
                    }
              }
          }
    
      }
    }
    
    myTask.doFirst {
      //here it might also be doLast, or whatever you need. I just put it before a war task, but it might depend on each need. 
      if(dependencyErrors > 0) {
        ant.fail 'There are ' + dependencyErrors + ' conflicting jar versions in the build.'
      }
    }