2 minute read

We all know it’s important to be able to build your code in one step, but when I came to build a project I’m working on at home I found it was actually a bit of a faff. Gradle came to the rescue, and in 15 minutes we made steps towards having a 1-step setup and build.

The project in question is built in Grails but uses Bower to ensure we have the right versions of AngularJS, Bootstrap, etc. Once your development machine is setup it’s as “easy” as running bower install whenever the dependencies change, and otherwise using the standard grails commands.

When you come to a fresh machine there are a few more steps before you can get up and running:

  1. Have I got Grails installed?
  2. Have I got NodeJS installed?
  3. Have I installed Bower using NPM?
  4. Have I run Bower to install the dependencies?

This is already too much hassle! Grails makes life easier by generating a Grails wrapper, grailsw, so we don’t need to check that Grails is installed. So far, so good!

NodeJS is a requirement for development, so I made the assumption that any developer machine would have it present. From there I wanted to use NPM to install Bower and then run Bower to grab the dependencies. There were plenty of options but I’m keen to learn a bit more Gradle so this was a great opportunity. 15 minutes later and we’ve got a build file (thanks to Mr Haki for the OutputStream processing):

import org.gradle.api.tasks.Exec

defaultTasks 'bower'

// Get the path for the locally installed binaries
task npmBin << {
    new ByteArrayOutputStream().withStream { os ->
        def result = exec {
            executable = 'npm'
            args = ['bin']
            standardOutput = os
        }
        ext.binPath = os.toString().trim() + "/"
    }
}


// Install packages from package.json
task npm(type: Exec) {
    description = "Grab NodeJS dependencies (from package.json)"
    commandLine = ["npm", "install"]
    inputs.file "package.json"
    outputs.dir "node_modules"

    tasks.npmBin.execute()

}


// Install the bower components for front-end library management
task bower(dependsOn: 'npm', type: Exec){
    commandLine "${npmBin.binPath}bower", 'install'
}

There may well be a better way of doing this, but it worked for me on OSX. There was a path-related error when we tried to run it on Windows, and if anyone can point out why that would be great.

Once the Gradle build has completed you still need to run grailsw run-app but 2 steps is better than 4. A brief foray into building Grails with Gradle yielded spurious errors before my 15 minutes was up, but recent commits may well solve that. Grails is expected to move to Gradle for version 3, so soon we’ll be able to do our entire build process through a single click.