If I re-run the same task again I get the same output. So far this would make sense that even though I am using the CC, Gradle found that my task is incompatible, so it is bypassing the cache and keeps re-evaluating the configuration every time. It is not efficient, but it gets the job done in that the date stays current. I have the same project cloned into 3 different directories and they all behaved this way…
Gradle does not have any detection like that I’m aware of.
I also did not find that message through Google or anywhere in the Gradle sources.
This behavior is only there if you define
notCompatibleWithConfigurationCache("Archive classifier uses current calendar date")
for that task.
Until last night, when I was poking around in one of these projects and suddenly Gradle switched to the behavior that I noticed on the other computer.
If this notCompatibleWithConfigurationCache is done in the build script, it should behave consistently across computers, so my guess here would have been, that you have an init script, for example in GRADLE_USER_HOME that does this notCompatibleWithConfigurationCache call only on your computer, which would explain that the same project behaves one way on your computer and different on your co-workers.
But if you say now that you have one project where it works and one where it does not on your computer, then this might also be unlikely.
Unless you have a condition in your init script that sometimes does that call and sometimes does not. Maybe check whether you have init scripts in your GRADLE_USER_HOME that causes this behaviour on your computer.
If you don’t find any, you should put a breakpoint inside the notCompatibleWithConfigurationCache call and then check with the debugger where this call is coming from for the project where CC is not reused.
It says that it is reusing the cache and none of the above plugin tasks get executed. And at the end I get this message:
This behavior is normal, the included build for build logic is part of the things the configuration cache can avoid if nothing changed.
So, now what do we say which one is the ‘correct’ behavior and why is the other one different?
That the CC is reused and uses the stale date is the correct behaviour if you do not manually say the task is incompatible (which should always just be a temporary measure until properly fixing it), or when you use a value source so that the calculated date is explicitly declared to be a CC input like I have shown.
For the archive classifier as it is a lazy property, the correct form would be
abstract class ArchiveClassifierWithDateValueSource : ValueSource<String, ValueSourceParameters.None> {
override fun obtain(): String = "Windows-${
ZonedDateTime
.now(ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
}"
}
tasks.register<Zip>("buildWindowsZip") {
archiveClassifier = providers.of(ArchiveClassifierWithDateValueSource::class) { }
from(layout.buildDirectory.dir("test-results"))
}
without the explicit get().
Thinking about it, even for the manifest the get() was majorly wrong.
It should be
abstract class BuiltOnValueSource : ValueSource<String, ValueSourceParameters.None> {
override fun obtain(): String = ZonedDateTime
.now(ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'00:00:00"))
}
tasks.withType<War>().configureEach {
manifest {
attributes(
mapOf(
"Built-On" to providers.of(BuiltOnValueSource::class) { }
)
)
}
}
because the manifest attribute values are even treated more lazy and only resolve at execution time.
So with this variant CC entry can be reused while still getting the current date written to the WAR.
In case of the archive classifier it is evaluated a bit earlier and thus does invalidate the CC entry, but Gradle then can decide properly.
I even would have thought for the manifest value part this should work as the value is only needed at execution time, but unfortunately, the provider seems to not be recognized as having a task dependency which usually causes it to not be stored to CC entry but evaluated at execution time:
tasks.withType<War>().configureEach {
manifest {
attributes(
mapOf(
"Built-On" to tasks.help.map {
ZonedDateTime
.now(ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'00:00:00"))
}
)
)
}
}