init_file looks OK. You’re registering an output correctly and you’re doing work in a doLast; however, File initFile = new File("init.txt") isn’t enough to create a file.
So what probably happened, the first time you ran the build, Gradle recorded that the correct state of init.txt after running init_file is to not exist. Since the file doesn’t exist, the task is up-to-date.
You shouldn’t use new File("init.txt") since it will try to create a file relative to the current working directory of the JVM (which might not be in your project directory). You can use file("init.txt") like you used before (it returns a File too).
And then run Gradle with --rerun-tasks, that’ll force the task to re-run and it should behave properly after that (deleting init.txt will cause the task to run again).
I think, one has to note that “outputs.file” not strictly prevents execution. If properties of the task change, the task will be executed nevertheless.
One or more additional actions for task ‘xyz’ have changed.
As a consequence, for download tasks, it makes sense to do both: “outputs.file” AND “onlyIf … exists()”
Example
val file = layout.buildDirectory.file("resources/main/demo.csv")
outputs.file(file)
onlyIf {!file.get().asFile.exists()}
That’s probably not a good idea.
Well, depending on the concrete case.
Of course output file does not prevent the task from running.
If any input or output changed since last run, it is run again. The task implementation logic is also an input, if the implementation changes, the result might differ, so it is not up to date.
Another drawback of onlyIf is that the task is NOT (always) executed if the file does NOT exist. But this might correlate with the use of jbang gradle plugin.