Custom plugin to enforce major compatibility

Hi,

Im trying to write a plugin that does the same as failOnVersionConflict(), but only when the major version differs. To achieve this I am looking for a way to obtain the information that gradle dependencies gives us, for example: org.junit.jupiter:junit-jupiter-api:5.4.2 -> 5.7.1. Especially the fact that 5.7.1 was selected over 5.4.2. Do you have any pointers on how to obtain this information?

Kr
Frans

Hi, You can obtain this information using the command below.

tasks.create("example"){
  project.configurations.getByName("implementation").dependencies.forEach {
    println("${it.group} - ${it.name} - ${it.version}")
  }
}

Thanks!
I tried that, but it only gives me the dependencies I explicitly declared in my build.gradle. I also need all transitive dependencies and whether Gradle did some conflict resolution on them (and with which versions).

1 Like

I did a little more research and found this solution, but I still have doubts if this is the right strategy.

tasks.create("printAllDependencies"){

project.configurations
    .filter { it.isCanBeResolved }
    .forEach {
        println("Configuration : ${it.name}")
        it.resolvedConfiguration.firstLevelModuleDependencies.forEach { r ->
            println("Dependency : ${r.module.id.name} ${r.module.id.version}")
            r.children.forEach { m ->
                println("  - ${m.module.id.name} ${m.module.id.version}")
            }
        }
    }

}

Using rich version declarations/constraints (Declaring Rich Versions) might also be something you’re interested in, but here’s some code that may help:

dependencies {
    implementation 'junit:junit:4.+'
    implementation 'org.hamcrest:hamcrest-core:0.1'
}
configurations.all { conf ->
    conf.incoming.afterResolve { resolvableDeps ->
        resolvableDeps.resolutionResult.allDependencies.findAll {
            it instanceof ResolvedDependencyResult && it.requested instanceof ModuleComponentSelector
        }.each {
            def req = it.requested.version
            def res = it.selected.moduleVersion.version
            // compare version strings and throw exception as needed
            println "${req} -> ${res}"
        }
    }
}

Results:

$ ./gradlew build
...
> Task :compileJava UP-TO-DATE
4.+ -> 4.13.2
1.3 -> 1.3
0.1 -> 1.3
...
1 Like

Dependency/module substitutions might make things messy as well, so you might need to handle cases where the requested module is different than the selected. I didn’t test this out so I’m not sure how that impacts my code.

Thanks Chris, that’s exactly what I was looking for. I will also keep the dependency/module substitutions in mind!