Incorrect UP-TO-DATE with gradle copy task

I have copy task configured like this:

tmp = “$project.buildDir/tmp”
tmpClassesDir = “$tmp/WEB-INF/classes”

task copyFiles(type: Copy) {
from sourceSets.main.java.srcDirs
include ‘*properties’
into tmpClassesDir
}

After than clean task deletes build directory, if I run copyFiles once again it’s UP-TO-DATE
It works if I add --rerun-tasks or set outputs.dir to tmp, but when outputs.dir is set as tmpClassesDir gradle says it’s UP-TO-DATE

Any ideas what causes that strange behavior?

EDIT: Problem exists only on remote test servers - when running local it’s working well - any ideas?

How it is possible that copy results are different on other machines? I don’t know what to check

please run your gradle build with -i flag to enable info logging. Info logging tells you why a task is considered to be up-to-date.

Even in debug mode it doesn’t:

11:00:06.785 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter] Starting to execute task ':copyFiles'
11:00:06.788 [DEBUG] [org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter] Determining if task ':copyFiles' is up-to-date
11:00:06.822 [INFO] [org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter] Skipping task ':copyFiles' as it is up-to-date (took 0.033 secs).
11:00:06.823 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter] Finished executing task ':copyFiles'
11:00:06.823 [LIFECYCLE] [class org.gradle.TaskExecutionLogger] :copyFiles UP-TO-DATE
11:00:06.825 [INFO] [org.gradle.execution.taskgraph.AbstractTaskPlanExecutor] :copyFiles (Thread[main,5,main]) completed. Took 0.04 secs.

I have the same issue with Gradle 3.3 and with a different task, deleting the output directory of the task (more concise: deleting the whole build directory, and the input-directory of the combineCssForMe task is inside the build directory) and rebuilding leaves the task as “UP-TO-DATE”.

WIth -i there is no information why it is UP-TO-DATE:

:appweb3-gui-web:combineCssForMe (Thread[Daemon worker Thread 22,5,main]) started.
:appweb3-gui-web:combineCssForMe
Putting task artifact state for task ':appweb3-gui-web:combineCssForMe' into context took 0.0 secs.
:appweb3-gui-web:combineCssForMe UP-TO-DATE
:appweb3-gui-web:combineCssForMe (Thread[Daemon worker Thread 22,5,main]) completed. Took 0.0 secs.

I experienced this a lot, and there is really not really useful information as to why a task is UP-TO-DATE… in the case above, I end up with a runtime exception, because the CSS file is not part of the generated WAR, so this is really ugly. I rather have the task failed (because the input is not here but expected) than just silently ignoring it.

I would vote for more verbose output regarding to the various reasons why a task is UP-TO-DATE. Sometimes, with the -i command line options, the verbose is not bad and gives hints, e.g. like this:

gradlew -iPutting task artifact state for task ':mainproject:combinejsForMe' into context took 0.0 secs.
Skipping task ':mainproject:combinejsForMe' as it has no source files and no previous output files.

But this is not always the case, sometimes Gradle just “thinks” the task is up-to-date, and does not provide any information why it “thinks” this way.

PS:
I did some debugging for about 4 hours, and found out the issue with the above UP-TO-DATE message. But anyhow, I would like to propose some logging changes (LEVEL=DEBUG) for the class AbstractNamedFileSnapshotTaskStateChanges and method iterator(), because meaningful error messages really make sense and help to save time and effort of Gradle users. If the Gradle team is interested in this, I can contribute this, let me know.