There are basically three ways of chaining tasks in Gradle.
For you, the TL;DR is probably
val runTestBukkit by tasks.registering(JavaExec::class) {
dependsOn(tasks.shadowJar)
// to run an executable jar with flags, see https://docs.gradle.org/current/dsl/org.gradle.api.tasks.JavaExec.html
}
See the documentation https://docs.gradle.org/current/userguide/more_about_tasks.html for more details
doLast { ... } & doFirst { ... } - Adding actions to an existing task
Docs: Manipulating existing tasks
You can amend an existing task to perform additional actions before or after its execution...
tasks.shadowJar {
doFirst {
logger.lifecycle("I'm an extra action!")
}
doLast {
copy {
from([email protected])
into(project.buildDirectory.dir("copied-shadow-jar"))
}
}
}
These additional actions will be performed whenever tasks.shadowJar runs. They are executed in the order they are defined in the code.
This can be really handy for adding small additional tasks, like cleaning up directories, or copying task outputs. More complicated tasks can be a bit more tricky though, so for that it's best to use dependsOn(...)...
dependsOn(...) Adding task dependencies
Docs: Adding dependencies to a task
Sometimes you want tasks that depend on other tasks running successfully. Maybe because they need to succeed, or because they produce an artifact that you want to consume.
You can also create a new task that either depends on other tasks...
val runTestBukkit by tasks.registering {
dependsOn(tasks.shadowJar)
}
Using dependsOn means shadowJar must run successfully before runTestBukkit runs, but runTestBukkit won't run unless it is specifically requested
(either with ./gradlew :runTestBukkit, or if another task depends on it). If shadowJar fails, then runTestBukkit won't run.
dependsOn can be really handy if the shadowJar produces an artifact, and Gradle caches the input and output. No matter how many times you run runTestBukkit, shadowJar will only run if necessary!
finalizedBy(...)
Docs: Finalizer tasks
Sometimes you always want a task to run after another task. For that you can use finalizedBy(...). You'll often see it when it comes to test report generation - For example, I always want the test report to be generated, even if the test task fails.
tasks.test {
finalizedBy(tasks.jacocoTestReport)
}