I have a linear chain of dependent tasks: consume
depends on generate
depends on download
. The download
task is slow and unreliable, but changes rarely, so we intend to produce generate
’s single output file once and store it in our source repository. We’d like to consider the generate
output as up-to-date if it exists at all. But if generate
’s output file is missing, then the download
should happen followed by generate
.
These three tasks are configured as follows, making full use of lazy configuration and task configuration avoidance:
final download = tasks.register('download') {
outputs.file layout.buildDirectory.file(name)
doFirst {
println "$it: run"
outputs.files.singleFile.text = ''
}
}
final generate = tasks.register('generate') {
inputs.files download
outputs.file layout.buildDirectory.file(name)
doFirst {
println "$it: run"
outputs.files.singleFile.text = ''
}
outputs.upToDateWhen { outputs.files.singleFile.exists() }
}
tasks.register('consume') {
inputs.files generate
outputs.file layout.buildDirectory.file(name)
doFirst {
println "$it: run"
outputs.files.singleFile.text = ''
}
}
Unfortunately, the outputs.upToDateWhen { outputs.files.singleFile.exists() }
directive in the generate
task is insufficient. If I remove build/download
, then running the consume
task causes the download
task to run as well, even though generate
’s own outputs are claimed to be up-to-date already. I have also tried adding onlyIf { !outputs.files.singleFile.exists() }
to generate
’s configuration, but that is likewise ineffective: removing build/download
still causes download
to rerun even if generate
’s output file already exists.
The only way I can think of to prevent unwanted download
task runs is to configure consume
in two different ways depending on whether generate
’s output file exists:
tasks.register('consume') {
final alreadyGenerated = generate.get().outputs.files.singleFile
inputs.files (alreadyGenerated.exists() ? alreadyGenerated : generate)
...
}
That will work, but having the task dependency graph change depending on build-time conditions feels sketchy. Is there a more elegant way to manage my situation?