The example contains two tasks that output to the same folder, but only one task correctly declares that folder as an output. The stale output cleanup for the second task removes the output of the first task because Gradle has not been configured to treat the folder as an output for the first task. Under these circumstances, the second task should be creating everything in the output folder. Anything already there should be safe to delete.
Marking the directory as an output of a task does not prevent Gradle from deleting it. Gradle will delete the contents of the output directory before any task that declares it writes to it, but not after. Therefore, it is important that all tasks that write to same output directory declare it as an output, but it is more preferable an output directory is not shared between tasks. Most importantly, output directories should not also be source directories.
The first paragraph is not about your build. It’s about the tasks in your “by example” reference (https://github.com/gradle/gradle/issues/3249). That example did contain two tasks that output to the same folder, and caused undesired deletion of the first task’s outputs by the second task. The solution was to make sure both the first and second properly declared the output, which prevents the second task from deleting the contents after the first task has already run.
Your post seemed to indicate that you expect that properly declaring the outputs would prevent Gradle from ever deleting the contents of the output directory. This is not the case. Gradle will delete the contents when necessary for build correctness (even without running clean).
The deletion shouldn’t be unexpected with what you’ve provided. However, if this deletion causes an issue for the build, you will need to provide additional information about the source of these files to help with additional configuration:
The purpose of declaring inputs and outputs is to allow Gradle to determine if the task is UP-TO-DATE. If the inputs have not changed and the outputs have not been tampered with, there is no need to do the work again. This works by snapshotting the input files and output files. Gradle only considers a file in the output directory to be an output of the task if is created or modified by the task. This makes sure that if two tasks write a different file into the same directory, deleting one file does not force the other task to run.
When you declare that clean should delete the ext folder, you are informing Gradle that everything contained in ext is safe to delete. You wouldn’t allow clean to delete a folder if it’s not something that can be recreated by the build. Since sencha_init is the only task with ext declared as an output folder, the sencha_init task should be creating absolutely everything that is contained in the ext folder.
If you have any files in ext before Gradle has been able to snapshot it, either due to a change in output folders, a Gradle upgrade, or even deletion on the .gradle folder, Gradle cannot accurately determine whether the file in the output folder would have been created by running the task and should be snapshotted. Therefore, to make sure this build and future builds are accurate, it does not run clean, but it removes the stale outputs of that task before running the task the first time. It should not be a problem to remove the exclusive outputs of sencha_init because the execution of sencha_init should immediately recreate everything that is actually required.
If after stale outputs are removed for sencha_init, the sencha_init task does not create all of the files that you need for sencha_refresh, this suggests that there is something other than sencha_init that is creating some of the required files in the ext folder or impacting how sencha_init works. You would need to know what that is in order to address the issue.
In any case, the lines Deleting stale output file: ... are not the problem. Rather, the problem would be in whatever should be recreating non-stale versions of those files that are removed.