How to re-resolve dependencies after configuration phase?


(Doron Gold) #1

I’m encountering a similar issue to the one mentioned by @Peter_Niederwieser here:
Latest 2.5 nightly resolves all dependencies in configuration phase?

What I’m trying to achieve :
I have a gradle task which generates code. It generates a complete gradle project, then another task (of type GradleBuild) builds the generated project and installs it into ~/.m2.

The generated project is a client library for my main project.
I need my integration tests to use the generated client library. I have the following dependency:

dependencies {
  integrationTestCompile "com.mycompany.generated:my-client:+"
}
compileIntegrationTestJava.dependsOn(':client-generator:buildClientFromSwagger')

(The integrationTestCompile configuration and compileIntegrationTestJava task are there because I have a custom integrationTest sourceSet).

This dependency should resolve latest version. However, It resolves the latest version that existed before the build started and fails to pick up the artifact that is built and installed by the task :client-generator:buildClientFromSwagger (during execution phase).

I was wondering whether any of the potential solutions mentioned by @daz in the aforementioned discussion were actually implemented:

Is any of this implemented as of today? If so, how can I actually tell gradle to resolve a configuration during the execution phase?

For now, the only option I’m left with is running gradle :client-generator:buildClientFromSwagger and only afterwards, as a separate command, run gradle build integrationTest. This has to be configured on all our Jenkins jobs, which is less than ideal.


(Stefan Oehme) #2

Instead of installing into a local repository, the task can generate into the build directory of client-generator and it’s output added as an artifact of that project. The “client-generator” build could look something like this (untested pseudo code ahead :wink: )

apply plugin: 'base'

task generateStuff() {
...
}

artifacts {
  'default'(generateStuff.outputFile) {
    builtBy generateStuff
  }
}

Then you can replace

integrationTestCompile "com.mycompany.generated:my-client:+"

with

integrationTestCompile project(":client-generator")

and the artifact will be built when needed.

I don’t think we plan to allow re-resolving/changing repositories at runtime. There is usually a cleaner solution, as above.


(Doron Gold) #3

@st_oehme I’m not sure what generateStuff.outputFile represents in your suggestion.
I assume you meant outputFile to be a custom property that I add to the task generateStuff, whose value is the Jar file resulting from building the generated project.

Even if I do that, the new dependency you suggest:

integrationTestCompile project(":client-generator")

Will include the Jar built by the generated project but will miss all its transitive dependencies.

Note that the client-generator project itself does not declare any relevant dependencies, it only generates code and runs an external GradleBuild on the generated gardle project.
That GradleBuild task runs build install on the generated project in order to install it into the local repository. This has the effect of installing a pom.xml with all transitive dependencies into the local repository.

Therefore I see no way other than having a dependency on an artifact in a local repository (which means all necessary transitive dependencies will get resolved).

Please let me know if I’m missing something or if you have another idea.


(Stefan Oehme) #4

I’m not sure why it needs to run a new Gradle build and why it can’t know its dependencies up-front? Could you reduce this to a small example on GitHub?