How to use Gradle Wrapper to build project in TeamCity inside enterprise network

Gradle is a great tool for building projects. I’m using it to build Java and Groovy modules. TeamCity is a Continuous Integration server that many teams are using in RBS.

We have a rather large farm of build agents. Some of them are specifically build to suit various build requirements (for example OS, or Browser version). However, majority of the Agents are generic and could be used by any build and project.

By default we don’t have Gradle distribution installed on those TeamCity agents. TeamCity doesn’t come with bundled version of Gradle either. We could install versions of Gradle on the Agents, however it’s impractical due to the number of the Agents and the fact that there is many distributions of Gradle that could be required.

Solution to that problem could be Gradle Wrapper. Gradle Wrapper contains few files that you should include as a part of your project.

In this article I will introduce Gradle Wrapper, how to use it and how to set it up in TeamCity so it works behind firewall/proxy in enterprise network.

IntelliJ Project view with Gradle Wrapper files
IntelliJ Project view with Gradle Wrapper files

The main role of wrapper is to Download distribution of Gradle and execute the build independently of the platform.

The interesting bit is that you can use Gradle to generate those files.

Creating Gradle Wrapper files

The Gradle Wrapper files could be copied from another project or generated using Gradle Wrapper task.

task prepareWrapper(type: Wrapper) {
   gradleVersion = '1.4'
}

The above lines show how to create the wrapper task in your project build.gradle file. There are number of properties that you can set. I will discuss those further. Documentation for those properties can be find at Gradle documentation page: http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.wrapper.Wrapper.html

Results of Execting Prepare Wrapper
Results of executing Prepare Wrapper

The task will generate folders and files that could be seen in the top picture of this post.

Using Gradle Wrapper 

You should be able to use Gradle Wrapper in the same way you use Gradle from your command line.

Using gradle wrapper script to list the tasks.
Using Gradle wrapper script to list the tasks.

When you execute the Wrapper for the first time it will download the distribution first (just as you can see on the picture above).

You could face first problem if you are inside a corporate network, behind a firewall and proxy.

Setting Wrapper to work behind Proxy

There are two ways you can address the issue:

  1. Setup proxy details on your Gradle Wrapper Script
  2. Provide Wrapper Distribution URL somewhere reachable within your corporate network

To setup proxy details you could modify gradlew and gradlew.bat files. Top of both files contain DEFAULT_JVM_OPTS system variable that you could set. For example:

#!/usr/bin/env bash

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS="-Dhttp.proxyHost=proxy.host.net -Dhttp.proxyPort=8080 -Dhttp.proxyUser=proxy.user -Dhttp.proxyPassword='awesome-password"

To provide alternative Gradle Distribution URL you can set it up before you generate Gradle Wrapper files in your task of the build.gradle file.

task prepareWrapper(type: Wrapper) {
   gradleVersion = '1.4'
   distributionUrl = 'alternative.location'
}

Or alternatively you can modify the gradle/wrapper/gradle-wrapper.properties file.

#Wed Feb 27 11:54:01 GMT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http://some.location.net/gradle-distributions/gradle-1.4-bin.zip

The benefits of first approach is that you don’t need to host Gradle distribution anywhere within your network. The minus is when proxy requires authentication, you will need to put credentials in the file.

The benefits of a second approach is that you don’t need to modify gradlew script files and you don’t need to provide proxy user credentials. Also, distribution is hosted internally which potentially could mean faster downloads. The downside is the fact that you need to host it somewhere internally accessible via HTTP protocol.

Setting up TeamCity build

The task is relatively simple with only one hurdle to overcome. Once the Gradle Wrapped downloads the Gradle distribution, where does it actually put it, and where will the dependencies downloaded during build phase go.

TeamCity build setup page with Gradle Wrapper enabled
TeamCity build setup page with Gradle Wrapper enabled

Note that I’ve not declared where are those directories that the downloads (Gradle distributions and build dependencies) will go. We can set this up in two places:

  1. gradle-wrapper.properties file
  2. TeamCity system property for the build

Setting the Wrapper Properties file

The gradle/wrapper/gradle-wrapper.properties file could be modified directly or setup during the prepareWrapper phase.

The prepareWrapper task:

task prepareWrapper(type: Wrapper) {
    gradleVersion = '1.4'
    distributionUrl = 'alternative.location'
    distributionBase='/some/location/on/agent/gradle'
    zipStoreBase='/some/location/on/agent/gradle'
}

The properties file:

distributionBase=/some/location/on/agent/gradle
distributionPath=wrapper/dists
zipStoreBase=/some/location/on/agent/gradle
zipStorePath=wrapper/dists
distributionUrl=http://some.location.net/gradle-distributions/gradle-1.4-bin.zip

Benefits of this approach is that you don’t have to configure anything specific in TeamCity. The downside is that you need to know in your script the details of Agent file system.

Setting the TeamCity system property

The system property to set should be the one referenced by gradle-wrapper.properties which is GRADLE_USER_HOME.

Example of TeamCity system property setup
Example of TeamCity system property setup

At this point it is important to mention one thing: if the same GRADLE_USER_HOME is used within different builds, it could potentially save time on downloading Gradle distribution and build dependencies.

I wish you many happy builds.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s