Creating a task that runs before all other tasks in gradle - gradle

I need to create an initialize task that will run before all other task when I execute it.
task A {
println "Task A"
}
task initializer {
println "initialized"
}
If I execute gradle -q A, the output will be:
>initialized
>Task A
Now if i'll add:
task B {
println "Task B"
}
Execute gradle -q B, and I get:
>initialized
>Task B
So it doesn't matter which task I execute, it always get "initialized" first.

You can make every Task who's name is NOT 'initializer' depend on the 'initializer' task. Eg:
task initializer {
doLast { println "initializer" }
}
task task1() {
doLast { println "task1" }
}
// make every other task depend on 'initializer'
// matching() and all() are "live" so any tasks declared after this line will also depend on 'initializer'
tasks.matching { it.name != 'initializer' }.all { Task task ->
task.dependsOn initializer
}
task task2() {
doLast { println "task2" }
}
Or you could add a BuildListener (or use one of the convenience methods eg: Gradle.buildStarted(...))

Seems like you aim execution phase, and you want a task precursing each task or just run as a first task in the execution phase?
If you want a task to always execute in every project before each other task after its being evaluated you can add a closure to he main build.gradle:
allprojects {
afterEvaluate {
for(def task in it.tasks)
if(task != rootProject.tasks.YourTask)
task.dependsOn rootProject.tasks.YourTask
}
}
or
tasks.matching {it != YourTask}.all {it.dependsOn YourTask}
You can also use the Task Execution Graph to define the lifecycle. There are few ways of achieving your goal, depending on your needs and a project structure.

The previously suggested solution with dependsOn works fine, but I don't like about it that it changes and clutters the task dependencies. The first solution coming to my mind is using Gradle Initialization Scripts. They are really cool. But, the usage is a bit tedious: currently there is no way to have a default project-local Gradle init script. You have to either explicitly specify the script(s) on command line, or place them in USER_HOME/GRADLE_HOME.
So another solution (already briefliy mentioned by #lance-java) which can be used to run some initialization, like a init task/script, is "build listeners". Depending on how early/late the initialization code should run, I use one of these two:
gradle.afterProject {
println '=== initialized in afterProject'
}
or
gradle.taskGraph.whenReady {
println '=== initialized in taskGraph.whenReady'
}
Here the docs of the Gradle interface and of BuildListener.
Note that some of the events occur very early, and you probably can't use them because of that, like e.g. beforeProject and buildStarted (explanations here and there).

Related

Error using dependsOn to call task from another gradle file

I am working with a build.gradle file that has multiple ways to specify executions for a task - setup. To call a task from another gradle file - runtests.gradle, I created a task - testTask and added task dependency using dependsOn, but this implementation does not seem to work and giving out an error like :
Could not find property 'testTask' on root project 'GradleFile
My build file looks like this :
build.gradle
task setup(dependsOn: testTask) <<
{
println "In main execution"
}
// new task
task testTask(type: GradleBuild) {
if (getEnvironmentVariable('RUN_TEST').equalsIgnoreCase("true")) {
buildFile = "../Behave/runtests.gradle"
tasks = ['mainTask']
}
else {
println "Exiting runTests Task"
}
}
setup.doFirst {
println "In first execution"
}
setup.doLast {
println "In last execution"
}
D:\>gradle -q GradleFile/build.gradle setup
I am not looking to make much changes to existing tasks, so is there any other workaround I should try?
I have been through many links but could not find anything that suits this scenario. Looking for suggestions please.
Gradle is sensitive to the ordering of tasks in the build script if a task instance is given in the dependsOn. The task setup depends on task (instance) testTask which, at the moment the build script is compiled, doesn't exist yet. The most common options to solve the issue are:
Define task setup below testTask:
task testTask(type: GradleBuild) {
}
task setup(dependsOn: testTask) {
}
Use a relative path to the task, i.e. the task's name, in the dependsOn
task setup(dependsOn: 'testTask') {
}
task testTask(type: GradleBuild) {
}
Please find more details in Javadoc of Task.

How to execute 'clean' task in the end of my custom task?

I've create my own simple task so I want to clean before test
task cleanTest (group: 'test setup', description: 'clean then test.'){
dependsOn 'clean'
dependsOn 'test'
tasks.findByName('test').mustRunAfter 'clean'
}
After my task is finished I want to run clean task
Iv'e tried
configure(subprojects) {
task clean << {
println "Do clean " + project.name
}
task test(dependsOn: clean)<<{
println 'test ' + project.name
}
task cleanTest(dependsOn: cleanTest)<<{
parent.cleanTest.execute()
}
}
All I want is to run 'clean task in the end of my custom task
This is not possible. You cannot run a task multiple times in one Gradle run. So if you want to do the same actions before and after your task, define a method that you run before and after the task. Using Task.execute() is not cleanly possible. Never ever do or even try this. It is a purely internal method that should never-ever-ever be called directly by any build ever. It is prone to produce strange and unpredictible results.
What you want is probably something around the lines of
subprojects {
def cleanIt = {
println "Do clean " + project.name
}
clean.doLast {
cleanIt()
}
task test(dependsOn: clean) {
doLast {
println 'test ' + project.name
}
}
task cleanTest(dependsOn: cleanTest) {
doLast {
cleanIt()
}
}
}
If you want to clean before test then simply make test depend on clean. That makes sure that before every test, clean is executed. This is how gradle does stuff.
task clean() {}
task test(dependsOn: clean) {}
There is also question how to run clean after mytask.. To run clean task after mytask you can use thirdtask depending on both and specify forced order between clean and mytask
task clean() {}
task mytask() {}
task thirdtask(dependsOn: [clean, mytask]){}
clean.mustRunAfter mytask
If the question was whether you can run clean task multiple times in a single build then that is not possible and see answer from Vampire to share the code.

Gradle - How to set dependency tasks for Exec-type tasks?

Say, you have following task:
task commandA() {
doLast {
project.ext.ping = 'PING'
}
}
This will work:
task commandB() {
dependsOn commandA
doLast {
println ping
}
}
This will fail:
task commandC(type: Exec) {
dependsOn commandA
commandLine "echo", ping
}
With Could not find property 'ping' on task 'commandC'. error message.
So, how one can declare dependency for an exec-type task and set some variable in that dependency?
Just don't initialize the variable within the doLast block, since it's getting initialized at the execution phase, but commandLine "echo", ping is trying to get it at the configuration phase of the build.
So, you need something like that:
task commandA() {
project.ext.ping = 'PING'
}
Or even without task, as follows:
project.ext.ping = 'PING'
Because configuration of any task is always executed, even if the task's action won't be executed.
Another solution is to use exec-action, not exec-task, something like this:
task commandA() {
doLast {
project.ext.ping = 'PING'
}
}
task commandC {
dependsOn commandA
doLast {
exec {
commandLine ping, "192.168.100.1"
}
}
}
In this case, exec-closure will be done during execution phase wuth the ping variable already available.
You can read about build lifecycle in the official Gradle user guide

skipping tasks in gradle during runtime

I've got two simple tasks
task initdb { println 'database' }
task profile(dependsOn: initdb) << { println 'profile' }
During runtime the result in console looks like this
When my tasks looks like this
task initdb { println 'database' }
task profile() << { println 'profile' }
the result in console is
How to skip initdb task when it's not used in the task profile in runtime? (without using -x)
The reason for this behavior is that initDb isn't declared correctly. It's missing a <<, and hence the println statement gets run at configuration time rather than execution time. This also means that the statement always gets run. This doesn't mean that the task gets executed (in the second example it doesn't).
To avoid such mistakes, I recommend to use the more explicit and regular doLast syntax in favor of <<:
task profile {
// code in here is about *configuring* the task;
// it *always* gets run (unless `--configuration-on-demand` is used)
dependsOn initdb
doLast { // adds a so-called "task action"
// code in here is about *executing* the task;
// it only gets run if and when Gradle decides to execute the task
println "profile"
}
}

How to create gradle task which always runs?

I'm likely overlooking something pretty core/obvious, but how can I create a task that will always be executed for every task/target?
I can do something like:
task someTask << {
println "I sometimes run"
}
println "I always run"
But it would be much more desirable to have the always running part in a task.
The closest I've come is:
task someTask << {
println "I sometimes run"
}
println "I always run"
void helloThing() {
println "I always run too. Hello?"
}
helloThing()
So, using a method is an 'ok' solution, but I was hoping there'd be a way to specifically designate/re-use a task.
Hopefully somebody has a way to do this. :)
Assuming the goal is to print system information, you could either just always print the information in the configuration phase (outside a task declaration), and have a dummy task systemStatus that does nothing (because the information is printed anyway). Or you could implement it as a regular task, and make sure the task always gets run by adding ":systemStatus" as the first item of gradle.startParameter.taskNames (a list of strings), which simulates someone always typing gradle :systemStatus .... Or you could leverage a hook such as gradle.projectsLoaded { ... } to print the information there.
This attaches a closure to every task in every project in the given build:
def someClosure = { task ->
println "task executed: $task"
}
allprojects {
afterEvaluate {
for(def task in it.tasks)
task << someClosure
}
}
If you need the function/closure to be called only once per build, before all tasks of all projects, use this:
task('MyTask') << {
println 'Pre-build hook!'
}
allprojects {
afterEvaluate {
for(def task in it.tasks)
if(task != rootProject.tasks.MyTask)
task.dependsOn rootProject.tasks.MyTask
}
}
If you need the function/closure to be called only once per build, after all tasks of all projects, use this:
task('MyTask') << {
println 'Post-build hook!'
}
allprojects {
afterEvaluate {
for(def task in it.tasks)
if(task != rootProject.tasks.MyTask)
task.finalizedBy rootProject.tasks.MyTask
}
}
What's wrong with invoking it straight from the root build.gradle?
task init << {
println "I always run"
}
tasks.init.execute()

Resources