Gradle - Continuous Build

Back in 2015, Gradle introduced this feature which they called 'continuous build'. Those days, I was exploring Ratpack, and it was the first toolkit/ framework to leverage the continuous build feature.

The idea here is to rerun the tasks whenever there is a code change. Gradle will first run the given task and then wait for the file watcher to detect any changes in source code. Upon detecting a change, Gradle will rerun the given task. Let's explore this feature on a stand-alone Java application. You could create an application using Gradle's init command. The structure of my application looks as follows (generated using tree command). My application is in a directory named "continuousbuild".

➜  continuousbuild tree
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── nareshak
    │   │           └── demo
    │   │               └── App.java
    │   └── resources

Let's write our application code as follows.

App.java

package com.nareshak.demo;

import java.util.stream.IntStream;

public class App {

    private static final String MESSAGE = "Hello";


    private static void printMessage(int count) {
        sleep();
        System.out.println(count + ". " + MESSAGE);
    }

    private static void sleep() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        IntStream.range(1, 30)
                .forEach(App::printMessage);
    }
}

The code will print a message every second 29 times. Let's run the application (without using continuos build)

➜  continuousbuild ./gradlew run

> Task :run
1. Hello
2. Hello
3. Hello
4. Hello
5. Hello
6. Hello
7. Hello
8. Hello
9. Hello
10. Hello
11. Hello
12. Hello
13. Hello
14. Hello
15. Hello
16. Hello
17. Hello
18. Hello
19. Hello
20. Hello
21. Hello
22. Hello
23. Hello
24. Hello
25. Hello
26. Hello
27. Hello
28. Hello
29. Hello

BUILD SUCCESSFUL in 30s
2 actionable tasks: 2 executed

Now let's run the application by passing the continuous delivery flag. This is done by supplying -t or --continuous.

➜  continuousbuild ./gradlew run -t

> Task :run
1. Hello
2. Hello
3. Hello
<... removed for brevity>
28. Hello
29. Hello

BUILD SUCCESSFUL in 29s
2 actionable tasks: 1 executed, 1 up-to-date

Waiting for changes to input files of tasks... (ctrl-d to exit)
<-------------> 0% WAITING

Now, after printing the message 29 times, Gradle doesn't exit. It's waiting for the source code to change. Let's go ahead and modify the message from "Hello" to "Hi".

Waiting for changes to input files of tasks... (ctrl-d to exit)
modified: /Users/naresha/practice/gradle/continuousbuild/src/main/java/com/nareshak/demo/App.java
Change detected, executing build...


> Task :run
1. Hi
2. Hi
3. Hi
4. Hi
<... removed for brevity>

Now your application is running with the code changes you made. Note that Gradle will not stop the current task if you modify your source. It will wait until the tasks are complete before rerunning them, following a change. Also, for the run task, only changes to files under "src/main" are considered. If you change your tests at this point, you will notice that Gradle is not running run task again.

To stop the continuous build, press "CTRL+D", and you will notice Gradle exiting with the message "Build cancelled.".

Note that the performance of continuous build will vary based on your operating system. Refer to the documentation for the latest updates.

Show Comments