Gradle is a magic box for me. I often don't get it and always do try and error. I use gradle 8.1 and groovy scripts. I have this small task
import java.time.Instant
tasks.register('continuous-build') {
dependsOn tasks.compileJava
onlyIf { !compileJava.state.upToDate }
logger.lifecycle("Job executed at " + Instant.now())
doLast {
def file = new File(projectDir, "build/classes/java/main/.reloadTrigger");
file.createNewFile();
file.setLastModified(Instant.now().toEpochMilli())
logger.lifecycle("This message is never seen")
}
}
I want this task to run with --continuous-build and just touch a file if it's done compiling.
this is what I do:
Run ./gradlew continuous-build --continuous
$ ./gradlew continuous-build --continuous
Reload triggered at 2023-11-10T11:48:50.446501720Z
BUILD SUCCESSFUL in 1s
6 actionable tasks: 1 executed, 5 up-to-date
Waiting for changes to input files... (ctrl-d to exit)
Make a small change to Main.java which compiles fine
modified: [...]Main.java
Change detected, executing build...
Reload triggered at 2023-11-10T11:49:02.870526619Z
BUILD SUCCESSFUL in 1s
6 actionable tasks: 1 executed, 2 from cache, 3 up-to-date
Waiting for changes to input files... (ctrl-d to exit)
After this the file timestamp is changed. That is what I want.
Make a small change to Main.java which compiles with error
modified: [...]Main.java
Change detected, executing build...
Reload triggered at 2023-11-10T11:49:09.303034432Z
> Task :compileJava FAILED
[...]Main.java:22: error: <identifier> expected
publi static final String ANSWER = "42";
^
1 error
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1s
3 actionable tasks: 2 executed, 1 up-to-date
Waiting for changes to input files... (ctrl-d to exit)
After this the file timestamp is NOT changed. That is what I want as it compiled with an error.
Make a small change to Main.java which compiles fine again
modified: [...]Main.java
Change detected, executing build...
Reload triggered at 2023-11-10T11:49:14.192599979Z
BUILD SUCCESSFUL in 1s
6 actionable tasks: 1 executed, 5 up-to-date
Waiting for changes to input files... (ctrl-d to exit)
After this the file timestamp is NOT changed anymore even the compilation succeeded. How can I achieve a file touch cmd if compileJava was successful.
And why is the second logging message never seen?
PS I have shortened the output a little bit to make it more readable
Few points to mention:
doLast
is an action to a task. It runs at the end of the task.
Your gradle task continuous-build
depends on the compileJava
task via this line dependsOn tasks.compileJava
which means that if compileJava
task fails, i.e, compilation of Java classes fail then doLast
task action will not be executed from your continuous-build
task. So, that's why the file is not created/updated.
This line onlyIf { !compileJava.state.upToDate }
from the continuous-build
gradle task tells that any task action will be executed only if the compileJava
task state is changed. In simple words, if you do a code change in your Java classes, then doLast
action will be executed from your continuous-build
task, otherwise it will be skipped from the execution.
So, your doLast
action depends on these two lines dependsOn tasks.compileJava
and onlyIf { !compileJava.state.upToDate }
completely.
To demonstrate, I have updated your gradle task a little bit to explain.
import java.time.Instant
tasks.register('continuous-build') {
dependsOn tasks.compileJava
onlyIf { !compileJava.state.upToDate }
logger.lifecycle("Job executed at " + Instant.now())
doLast {
def file = new File(projectDir, "build/classes/java/main/.reloadTrigger");
def created = file.createNewFile();
logger.lifecycle("File created status :" + created);
file.setLastModified(Instant.now().toEpochMilli())
logger.lifecycle("Last modified timestamp of the file: " + file.lastModified());
logger.lifecycle("This message is never seen")
}
}
First time Execution:
Second time Execution (with no change in Java classes):
doLast
task action will not be executed as explained in the point (because of this line onlyIf { !compileJava.state.upToDate }
).
Third Time Execution (with the modification in a Java class):
The doLast
task action will be executed and this will trigger the file to be updated instead of creation although the timestamp will be changed this time.
Fourth Time Execution (with the modification in a Java class with an error):
The doLast
task action will not be executed due to the compilation error in one of the Java classes detected by the compileJava
task and the continuous-build
task depends on compileJava
.
Fifth time Execution (with no error, i.e, reverted the changes): In this case, the third time execution scenario is repeated again.