Running the same task multiple times during execution in gradle - gradle

Is it possible to have some like the following in gradle
task enableMe() << {
println "Enable"
}
task disableMe() << {
shouldRunAfter 'taskAwork'
println "Disable"
}
task taskAwork(){
shouldRunAfter 'enableMe'
println "do work in A while disabled"
}
task taskA(dependsOn: disableMe, taskAwork, enableMe){
}
task taskBwork(){
shouldRunAfter 'enableMe'
println "do work in B while disabled"
}
task taskB(dependsOn: disableMe, taskBwork, enableMe){
}
task taskC(dependsOn: taskA, taskB){
}
So that when it runs the tasks are executed in the order
disableMe
taskAwork
enableMe
disableMe
taskBwork
enableMe
but currently, disableMe and enableMe only run once.. is there anyway to set there status so that they can run again.
The only way I can think to do this is to duplicate the tasks;
task enableMeA() << {
println "Enable"
}
task disableMeA() << {
shouldRunAfter 'taskAwork'
println "Disable"
}
task enableMeB() << {
println "Enable"
}
task disableMeB() << {
shouldRunAfter 'taskBwork'
println "Disable"
}
task taskAwork(){
shouldRunAfter 'enableMeA'
println "do work in A while disabled"
}
task taskA(dependsOn: disableMeA, taskAwork, enableMeA){
}
task taskBwork(){
shouldRunAfter 'enableMeB'
println "do work in B while disabled"
}
task taskB(dependsOn: disableMeB, taskBwork, enableMeB){
}
task taskC(dependsOn: taskA, taskB){
}

Seems, in your case, you have to implement TaskExecutionListener for your task and use it's beforeExecute and afterExecute methods to implement your logic.
This could look something like:
task taskAwork() << {
println "do work in A while disabled"
}
task taskBwork() << {
println "do work in B while disabled"
}
task doAllWorkTask(dependsOn: [taskAwork, taskBwork]){
}
gradle.taskGraph.addTaskExecutionListener new WorkTasksExecutionListener()
class WorkTasksExecutionListener implements TaskExecutionListener {
#Override
void afterExecute(final Task task, final TaskState state) {
if (task.name.contains('work')) {
println('Enabling smth before execution of work task')
}
}
#Override
void beforeExecute(final Task task) {
if (task.name.contains('work')) {
println('Disabling smth after execution of work task')
}
}
}
Here is specified 2 tasks, which do something and requires some common loigic to be run before and after each one. To implement this common logic, used WorkTasksExecutionListener implementing TaskExecutionListener interface and registered as a listener in the taskGraph.
WorkTasksExecutionListener implenets 2 methods of the TaskExecutionListener: beforeExecute and afterExecute. This methods are getting called before and after each tsk execution, so in it's implementation was added the condition to check whether the task do some work and if yes, then some additional logic executed.
Output in this case will be:
:taskAwork
Enabling smth after execution of work task
do work in A while disabled
Disabling smth before execution of work task
:taskBwork
Enabling smth after execution of work task
do work in B while disabled
Disabling smth before execution of work task
:doAllWorkTask

Gradle, by default, will not run a task which is up-to-date.
Task is considered up-to-date if it's TaskOutputs property hasn't been changed.
If you want to run a task several times during the same execution, you can use upToDateWhen property to define a predicate that will return false whenever you want the task to run again:
task myTask() {
outputs.upToDateWhen {some_condition}
// Do some stuff
}

Related

How to run certain task with gradle

I try to investigate a Gradle and follows some tutorials, but I have confused with the following:
I created are a couple of simple tasks:
task startProcess{
println 'startProcess'
}
task doStep2{
println 'Step2'
}
task doStep3{
println 'Step3'
}
task finishProcess{
println 'finishProcesss'
}
And try to execute one of them:
gradle finishProcess
Or with defaultTasks with command gradle build:
defaultTasks `finishProcess`
task startProcess{
println 'startProcess'
}
task doStep2{
println 'Step2'
}
task doStep3{
println 'Step3'
}
task finishProcess{
println 'finishProcesss'
}
In both options, I got the same result:
> Configure project :
startProcess
Step2
Step3
finishProcesss
BUILD SUCCESSFUL in 1s
How to execute exactly one of them?
You have to use register, I think if you did not use it, You're only asking Gradle to execute these tasks.
for example
tasks.register('startProcess') {
doLast {
println 'startProcess'
}
}
tasks.register('doStep2') {
doLast {
println 'Step2'
}
}
tasks.register('doStep3') {
doLast {
println 'Step3'
}
}
tasks.register('finishProcess') {
doLast {
println 'finishProcesss'
}
}
tasks.named("build") { finalizedBy("finishProcess") }
Registering these tasks, you will be able to call each one indivadually.
If you want to link a specific task, with a build task for example.
Then you can use finalizedBy like the following.
tasks.named("build") { finalizedBy("finishProcess") }
This will call the finishProcess task, whenever build is triggered.
I strongly recommend the official gradle documintation for more information about tasks.

Creating a task that runs before all other tasks in 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).

Gradle Task dependencies Execution issue

I am facing an issue related to gradle task dependencies. One of my gradle task is calling another task successfully but it is not executing dependencies on which my second task depends. Please go through the following code to understand the problem statement:
My code is:
task callGradleDeploy <<{
tasks.deployComp.execute()
}
task deployComp (dependsOn: ['setEnvParameter', 'installWeb', 'installService']) <<{
println "Deployment Done"
}
task setEnvParameter {
//parameter Setting for deployement
}
task installWeb {
//install Web Code
}
task installService {
//install Services Code
}
Now when I run task callGradleDeploy, it is calling deployComp task but it is not installing Web or Service content (Not doing anything with setEnvParameter, installWeb, installService ). and Just printing Deployment Done
Just to notify, when I am individually calling(running) deployComp task, it is installing Web and Service part without any issue.
Please help me to understand how to manage this dependsOn thing while calling a gradle task into another.
Second part:
*//******************* Edited part below, For clear understanding *****************//*
#Opal I have done configuration like below after your suggestion.
For the cases, where only deployService should work. It is still calling deployWeb and deployWebAndService both.
Code is here:
task deploy (dependsOn : ['deployWeb', 'deployService', 'deployWebAndService']) <<{
println "\n\tExecuting respective task"
}
task deployWeb (dependsOn : ['configureWebApp','stopWebApp','uninstallWebApp','installWebApp','startWebApp']) <<{
println "\n\tExecuting deploy for Web Content"
}
task deployService (dependsOn : ['configureService','stopService','uninstallService','installService','startService']) <<{
println "\n\tExecuting deploy for Service Content"
}
task deployWebAndService (dependsOn : ['configureWebApp','configureService','stopWebApp','uninstallWebApp','installWebApp','startWebApp','stopService','uninstallService','installService'/*,'startService'*/]) <<{
println "\n\tExecuting deploy for Web and Service Content"
}
deployWeb.onlyIf{
(WebContent.equals("Yes") && ServiceContent.equals("No")) //fetching "Yes"/"No" values from a separate function
}
deployService.onlyIf{
(WebContent.equals("No") && ServiceContent.equals("Yes"))
}
deployWebAndService.onlyIf{
(WebContent.equals("Yes") && ServiceContent.equals("Yes"))
}
TL;DR Your build.gradle should look as follows:
task callGradleDeploy(dependsOn: ['deployComp']) {
}
task deployComp (dependsOn: ['setEnvParameter', 'installWeb', 'installService']) <<{
println "Deployment Done"
}
task setEnvParameter{
//parameter Setting for deployement
}
task installWeb{
//install Web Code
}
task installService{
//install Services Code
}
First of all you should never call task's execute() method manually, since this highly discouraged and interferes gradle's internal logic (directed acyclic graph). To define dependencies between tasks the following methods should be used:
mustRunAfter
shouldRunAfter
dependsOn
In your particular case it's enough to substitute execute invocation with dependsOn and it works perfectly. Also please note the << to indicate action is deprecated and scheduled to be removed in version 5.0. Instead use doLast:
task callGradleDeploy {
doLast { println 'action' }
}
EDIT
See the solution below. The advantage is that you configure dependencies between tasks once. To check if it works correctly run gradle deploy -Pwc or gradle deploy -Psc
task explodeWarContent {
doLast {
println 'Code to explode war'
}
}
task configureWebApp(dependsOn: explodeWarContent) {
doLast {
println 'Code to configure web app'
}
}
task stopWebApp {
doLast {
println 'Code to stop web app'
}
}
task uninstallWebApp(dependsOn: stopWebApp) {
doLast {
println 'Code to uninstall web app'
}
}
task installWebApp(dependsOn: configureWebApp) {
mustRunAfter uninstallWebApp
doLast {
println 'Code to install web app'
}
}
task startWebApp(dependsOn: installWebApp) {
mustRunAfter stopWebApp
doLast {
println 'Code to start web app'
}
}
task deployWebApp(dependsOn: [uninstallWebApp, startWebApp]) {
onlyIf { project.hasProperty('wc')}
}
task configureService {
doLast {
println 'Code to configure service'
}
}
task stopService {
doLast {
println 'Code to stop service'
}
}
task uninstallService(dependsOn: stopService) {
doLast {
println 'Code to uninstall service'
}
}
task installService(dependsOn: configureService) {
mustRunAfter uninstallService
doLast {
println 'Code to install service'
}
}
task startService(dependsOn: installService) {
mustRunAfter stopService
doLast {
println 'Code to start service'
}
}
task deployService(dependsOn: [uninstallService, startService]) {
onlyIf { project.hasProperty('sc')}
}
task deploy {
dependsOn deployWebApp, deployService
}

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()

How to do something before Gradle task's dependencies are executed?

I have the following in build.gradle:
task aoeu << {
println "**************************** during"
}
tasks.publish.dependsOn(aoeu)
tasks.publish.doFirst {
println "************************* before"
}
tasks.publish.doLast {
println "************************* after"
}
Its output is:
:aoeu
**************************** during
:publish
************************* before
************************* after
But what I really need is for the 'during' to happen between 'before' and 'after'. How can this be done? Should 'publish' simply depend on 'before'? If so, how can I guarantee that it happen before other dependencies?
As far as I know your code should work propertly but it doesn't. doFirst should be executed in configuration phase which is run before doLast (execution phase). BTW this code works fine:
As Peter Niederwiser wrote here https://stackoverflow.com/a/9204159/2069368 doFirst run in execution phase as first statement (before doLast) so your code works fine. This example will show you execution order in gradle build:
task publish {
println "(1) before (run in configuration phase)" // this will run before gradle dependencies
}
task aoeu << {
println "(2) during (run in execution phase as last statement)"
}
tasks.publish.dependsOn(aoeu)
tasks.publish.doLast {
println "(4) after (run in execution phase as last statement)"
}
tasks.publish.doFirst {
println "(3) after (run in execution phase as FORST statement - before doLast/<<)"
}
It will return
C:\>gradle publish
(1) before (run in configuration phase)
:aoeu
(2) during (run in execution phase as last statement)
:publish
(3) after (run in execution phase as FORST statement - before doLast/<<)
(4) after (run in execution phase as last statement)
[UPDATE]
Here http://gradle.1045684.n5.nabble.com/task-run-order-lt-lt-syntax-doLast-doFirst-etc-td3337481.html is great question with great example which shows execution order.
Read this article about gradle lifecycle, it will help you understand it.
[UPDATE]
If you want to run task aoeu in publish execution phase you can call aoeu.execute in publish.doFirst. But as far as I know it shouldn't be done in that way.
task publish {
}
task aoeu << {
println "(2) during (run in execution phase as last statement)"
}
tasks.publish.doLast {
println "(3) after (run in execution phase as last statement)"
}
tasks.publish.doFirst {
println "(1) after (run in execution phase as FORST statement - before doLast/<<)"
aoeu.execute()
}
will return
C:\>gradle publish
:publish
(1) after (run in execution phase as FORST statement - before doLast/<<)
(2) during (run in execution phase as last statement)
(3) after (run in execution phase as last statement)
As I see you want to run aoeu in the middle of publish task. I think that the best way to do it will be to divide publish task into two separate tasks and use depends, mustRunAfter to control execution order. Look at this example:
task publishInit << {
println '(1)'
}
task aoeu << {
println '(2)'
}
task publish << {
println '(3)'
}
publish.dependsOn publishInit
publish.dependsOn aoeu
aoeu.mustRunAfter publishInit
It will return
C:\>gradle publish
:publishInit
(1)
:aoeu
(2)
:publish
(3)
task snth << {
println "************************* before"
}
task aoeu << {
println "**************************** during aoeu"
}
publish.dependsOn(aoeu)
task ueoa << {
println "**************************** during ueoa"
}
publish.dependsOn(ueoa)
publish.doLast {
println "************************* after"
}
publish.dependsOn.each { dependency ->
if (dependency instanceof Task) {
dependency.dependsOn(snth)
}
}
will output:
:snth
************************* before
:aoeu
**************************** during aoeu
:ueoa
**************************** during ueoa
:publish
************************* after
If you want the dependency added recursively:
def recursivelyAddDependsOn(Task parent, Task dependsOn) {
if (!parent.equals(dependsOn)) {
parent.dependsOn(dependsOn)
def tasks = parent.dependsOn.findAll { dependency ->
dependency instanceof Task
}
tasks.each { task ->
recursivelyAddDependsOn(task, dependsOn)
}
}
}
recursivelyAddDependsOn(publish, snth)
And a more functional solution is:
def recursivelyApplyToTaskDependencies(Task parent, Closure closure) {
closure(parent)
parent.dependsOn.findAll { dependency ->
dependency instanceof Task
}.each { task ->
recursivelyApplyToTaskDependencies(task, closure)
}
}
def recursivelyAddTaskDependency(Task parent, Task dependency) {
def addTaskDependency = { p ->
if (!p.name.equals(dependency.name)) {
p.dependsOn(dependency)
}
}
recursivelyApplyToTaskDependencies(parent, addTaskDependency)
}
recursivelyAddTaskDependency(publish, snth)
Ordering tasks is headache, and << is deprecated syntax.
I ended up to weave tasks as below.
task publish {
println "here we go"
}
task task1 {
println "first"
}
task task2 {
println "second"
}
task task3 {
println "third"
}
// task execution order. this executes bottom to top order.
publish.dependsOn task3
task3.dependsOn task2
task2.dependsOn task1
The publish task result is as below;
here we go
first
second
third

Resources