Sunday, 28 December 2014

Skipping Gradle Tasks

Background

Gradle simply speaking is a build tool like Apache ant but it does more that that and in an efficient way. It handles dependency management as well. You can say -

Gradle = Apapch Ant + Apache Ivy

In the background Gradle is all Groovy.  So if you are aware of groovy writing tasks in gradle is no big deal.

Make sure you have JDK configured and gradle installed.



Gradle Task Build Life Cycle

Gradle has 3 distinct phases -
  1. Initialization
  2. Configuration
  3. Execution

For more details on each of the phases refer Gradle Build Life Cycle . To quickly understand this build life cycle put following code in build.gradle file and run it - 

logger.lifecycle("This is executed during configuration phase");
task A() {
    logger.lifecycle("This is also executed during configuration phase");
    doFirst {
      logger.lifecycle('In task A : This is executed first in the execution phase.')
    }
    doLast {
        logger.lifecycle("In task A :This is executed last in execution phase");
    }    
}


and the output is



Hope you got the idea. Configuration and Execution phases are what we are going to concentrate on.

Lets first see how to write dependents Tasks in gradle.

Writing Dependent Tasks in Gradle


Create a file build.gradle and copy following code in it.

task A(dependsOn: 'B') {
    
    doLast {
        logger.info("In task A");
    }    
}

task B(dependsOn: 'C') {
    doLast {
        logger.info("In task B");
    }
}

task C {

    doLast {
        logger.info("In task C");
    }

}


Above code essentially declares three gradle tasks - A, B and C. Also there are dependencies between them. Notices the dependsOn keyword in bracket. Task A depends on Task B which in turn depends on Task C. Now lets run this. Output is -



Note 1 :

You can also define type of a Task. There are various predefined tasks in gradle. Something like -

task copyFiles(type: Copy, dependsOn: 'SomeAnotherTask') {
    from 'src/main/documentation'
    into 'build/target/documentation'
}


Note 2 :

You can also simply say - 

task A << {
    logger.lifecycle("In task A : Execution phase");
}


The '<<' symbol you see is just a shortcut to execute thing is Execution phase. This defines a task called A with a single closure to execute.

Ok now lets come to the intended purpose of this post which is - how to skip tasks.

Skipping Tasks in Gradle

Goal : Goal is to skip task A and all subsequent tasks that A depends on. Lets say we decide this with a property that we provide to gradle from commandline. Lets call it 'skipA'. If 'skipA' is provided in command line arguments we do not execute any task.

For this lets use onlyIf first.

task A(dependsOn: 'B') {
    onlyIf {
        !project.hasProperty('skipA')
    }
   
    doLast {
        logger.lifecycle("In task A");
    }   
}

task B(dependsOn: 'C') {
    doLast {
        logger.lifecycle("In task B");
    }
}

task C {
    doLast {
        logger.lifecycle("In task C");
    }
}


and the output is




Lets analyze what happened here.Yes Task A was skipped as we intended but what about other tasks they were run.

Don't argue that you can put onlyIf and condition in all tasks :) you are smarter than that!

Note : One important point to note is onlyIf is executed during execution phase and by that time gradle has figured out what all tasks it needs to run. Skipping a single task will not skip the task the skipped task depends on. We need to add skipping logic in configuration phase.

There is another way to do this and that is to set enabled = false; inside a task. This will skip the given task. Also we need two other things.

  1. Implement skipping logic in Configuration phase.
  2. Remove all the tasks that the task to be skipped was depending on (This needs point 1.)

So lets see how can we do that. Copy following code in build.gradle file -

task A(dependsOn: 'B') {
    if(project.hasProperty('skipA')) {
        logger.lifecycle("Skipping Project : " + project.name);
        enabled = false;
        dependsOn = [];
    }
   
    doLast {
        logger.lifecycle("In task A");
    }   
}

task B(dependsOn: 'C') {
    doLast {
        logger.lifecycle("In task B");
    }
}

task C {
    doLast {
        logger.lifecycle("In task C");
    }
}


and the output is


Yes we got what we wanted. Now lets see how we did it.

  • First of all see the if statement in task A. It is outside any doFirst() or doLast() method. This ensures it will be run in configuration phase.
  • Then we checked out condition. If it is true then we set enabled  = false for the task. This will skip task A.
  • To stop other tasks from running that A depends on we removed all those tasks by saying dependsOn = []; Again note this worked because we did it in configuration phase.

Related Links

No comments:

Post a comment

t> UA-39527780-1 back to top