How to ensure configuration avoidance with tasks.named

image

Considering the above code sample:

tasks.named('integrationTest', Test).configure ({
    def laJar = project(':some-other').tasks.named('bootJar').get()
    it.dependsOn laJar
    it.systemProperty('laJar', laJar.outputs.files.singleFile.path)
} as Action)

tasks.named('integrationTest', Test) {
    def laJar = project(':some-other').tasks.named('bootJar').get()
    it.dependsOn laJar
    it.systemProperty('laJar', laJar.outputs.files.singleFile.path)
}

my question is do we have to use the configure method explicitly, or is the bottom/second format sufficient?

Regarding named and configure, the second is sufficient for task-configuration avoidance.

But your snippets have other problems.
For example you should definitely not use tasks.named on another project, as that project might not yet be configured and it is highly problematic to reach into other project models like that.

And even worse, you break task configuration avoidance for that task by using get() on it and reach even further into the other projects model by accessing properties of that task which is also a very big no-go.

Read more about it and how to properly share things cross-project at Sharing outputs between projects.

the project(path: ':my-other-project', configuration: 'specificallyJustTheOneFileINeed') notation is really weird. seems to be able to get me my data, i wonder if this also works for copying around bundled javascript folder as well

implemented it this way - attempt to implement "Sharing outputs between projects" · alexanderankin/side-projects@aa06d05 · GitHub - curious to know if you would expect this part:

artifacts.add('la', bootJar)

to automatically add the bootJar task as a dependency to run when this configuration is consumed.

i wonder if this also works for copying around bundled javascript folder as well

it works for any files you can imagine

to automatically add the bootJar task as a dependency to run when this configuration is consumed.

Yes, you just do not consume it properly. :slight_smile:

If you would wire the la configuration to some input files property, the implicit task dependency would be effective.

But you only use the configuration at configuration time to get the path.
At that time you could not execute the task even if you would need to, as you are still in configuration phase, not yet at execution phase.

But even if you would use the la configuration at execution time it would not automatically trigger the necessary task, because now you are already at execution phase which is too late to schedule additional tasks, as the tasks to be executed in the execution phase are determined at the end of the configuration phase when the task graph is built.

How you do it in your concrete case depends mainly on one question. Should the integrationTest task rerun if that jar changes or not? If not, then you could simply do dependsOn(configurations.la) which would be an explicit depending on the implicit task dependencies of that configuration.

But usually and I strongly guess here too, the task should rerun if the file changes, so your configuration is erroneous anyway as you don’t declare the file as input file.
If you replace the dependsOn with inputs.files(configurations.la).withPropertyName('theTestedBootJar'), then you get the necessary implicit task dependency and have the file properly declared as input. You might actually want to also set the path sensitivity for potential cache hits across worktrees for example.

depending on the configuration works: dependsOn(configurations.la) (although went with inputs.files(configurations.la) to make re-running more reliable - didn’t even realize this doesn’t normally rerun on changes??).

marked as solution :tada:

1 Like