Marcin Erdmann

Groovy, Grails, Geb...

My Gradle init script

Recently I started using Gradle more and more to initialize my test/example projects. The main advantage of doing so is the fact that Gradle allows you to manage dependencies of your project easily. So if for example you want to give some new library a go it's extremely easy to get it from maven central with Gradle. And thanks to Gradle's idea and eclipse plugins it's so easy to import the project with all the dependencies set up to your favourite IDE.

Two things I found myself doing all the time when initializing a new project was adding Gradle wrapper and manually initializing source directories. Some time ago Guillaume Laforge wrote a blog post that contains a wrapper task and a directory initialization task but one would still need to copy it into build.gradle when creating a new project - that's not automated enough!

Last week I watched Luke Daley's Gradle webinar on standardizing build environment and learned the concept of init scripts from it. Now I know that if I put the following in my ~/.gradle/init.gradle I will get the wrapper, directory initialization and idea plugin's tasks in all of my builds for free:

projectsEvaluated {
    rootProject.allprojects {
        apply plugin: 'idea'

        if (!tasks.findByName('initSourceDirs')) {
            task initSourceDirs(description : 'make all dirs for project setup') << { task ->
                def language = System.properties["${task.name}.only"] ?: 'allSource'
                sourceSets.all { 
                    it["${language}"].srcDirs.each { it.mkdirs() }   
                }   
            }   
        }   

        if (!tasks.findByName('wrapper') && !parent) {
            task wrapper(type: Wrapper) {
                gradleVersion = '1.2'
            }   
        }   
    }
}

rootProject {
    apply {
        plugin 'build-announcements'
    }       
}

Note that the tasks are added to the project only if the project doesn't define tasks with the exact same names. Applying a plugin is idempotent in Gradle so it doesn't need to be guarded by an if statement. You can also easily limit which source set types directories will be created using initSourceDirs.only system property. By default directories for all source sets (main, test, ...) and all source set types (java, resources, groovy, ...) will be generated so if your project defines an additional source sets, i.e. functionalTest, it will be picked up as well.

I also decided to apply build-announcements plugin to all of my projects which sends a desktop notification (notify-send for my OS) every time a build has finished with either a success and a failure. So if I have a long running build I can switch to doing something else instead of waiting for it to finish and I can come back to it as soon as it's done as I will be notified about the build completion.

So now to get a brand new Groovy, Gradle backed, project imported into IntelliJ I only need to create a short and simple build.gradle:

apply plugin: 'groovy'

repositories {
    mavenCentral()
}

dependencies {
    groovy 'org.codehaus.groovy:groovy:1.8.6'
}

And then execute the following commands:

  • gradle wrapper
  • ./gradlew initSourceDirs -DinitSourceDirs.only=groovy
  • ./gradlew idea