When you create a Grails 3 plugin, and you want to share it with the world, wouldn’t it be great if building and deploying was taken care of by a CI server?
In this blog I will show you how to setup a Grails Plugin project that will be built and deployed on the Travis-CI infrastructure.
Let us start out by setting up the project, so that it can be deployed to Bintray, then we will add a Travis build to the mix. Finally we will explore how to handle snapshot deployment to JFrog’s open source repository.
How Travis-CI works
Travis-CI works by monitoring your GitHub repository, and whenever it sees changes, it will make a build of your project. The change can be a new commit pushed to GitHub, a new tag pushed to GitHub, or a pull request to your project on GitHub.
If you want a deeper knowledge on, how Travis-CI works, please see the documentation.
While you might have a plugin already, let us start this example by creating a plugin. The plugin will not have any functionality: it is only here to show the steps.
To get Travis-CI working the project has to live on GitHub.
Setting up a GitHub repository:
The first step is is to enable Git for the local repository, add the project files and commit it:
Now go to GitHub where we create a new repository:
And push the first commit to GitHub:
Publishing plugin to Bintray
Before configuring Travis, let us update the configuration to enable publishing the plugin to Bintray and the Grails Plugin Portal.
build.gradle already contains the building blocks for this:
As it can be seen there are some values that are not filled in like credentials and
githubSlug. Let us add those values in a way where credentials are not visible in the public GitHub repository.
My code snippet will contain two ways to fetch configuration values:
The configuration values are now read from either the running environment (this is where Travis will provide them, more on this later) or they will be taken from the project configuration or Gradle’s global configuration (
~/.gradle/gradle.properties) - and that is where I recommend storing these credentials.
The format for
~/.gradle/gradle.properties is like this:
With this in place, it is now possible to publish the plugin to Bintray. This can be done like this:
Before moving on to Travis, let me push this to GitHub
Setup Travis command line
Before we can use Travis, we need to install the Travis Command line. Travis Command line requires Ruby, and since my machine is a Mac, Ruby is included. For other OSes, please go here for more information.
Adding Travis to the project
The first thing we will do is initialize Travis for the project
Take a look in
.travis.yml. You should see one line of code:
Let us push this change to GitHub:
This will result in the first Travis build - a failed build. When Travis tries to run
gradle assemble it fails with the following error:
As we can see from the error it cannot find the
bintrayUser in the properties - since it is not defined yet together with the other credential properties.
Travis has the ability to set environment variables defined in .travis.yml, but we do not want credentials in clear text. Fortunately Travis support encrypting environment variables. It is important to understand that the variables added here will only work for the GitHub account associated with the project.
Adding environment variables to
Let us add four variables to the configuration under
.travis.yml looks like this:
and then commit and push to GitHub.
Now the build goes green on Travis but is is still not publishing the plugin to Bintray. That’s up next.
Publish to Bintray with Travis
Travis should test
master on GitHub every time code is committed. It should build pull-requests, but should only release the plugin to Bintray, when Git is tagged with a new version.
The developers of Travis have thought of this and allow us to use a bash script to make more fine grained logic. The basic script could look like this:
The script is currently a bit more advanced than it needs to be, that is because more functionality will be added later.
To execute the script on Travis-CI add these few lines to
I prefer them before the
env: block. To allow Travis to actually execute the script - it’s important that the script execute flag on
travis-build.sh is set:
Add, commit and push this to GitHub like before.
The result will be a successful build, but not a deployment to Bintray. This is of course due to the
if statement in the bash script which checks if a git tag is set. If it is the
master branch and if it’s not a pull-request.
Tag and release
I now want to make a release of my plugin. To do so, I need to bump the plugin version in
build.gradle, commit the change, tag the commit and push it to GitHub.
Let me start with
and the commit, tag and push:
Notice, that I added
--tags to the
git command to get tags pushed to GitHub.
That’s it. The build is automated, and a release can be created on Bintray by using Travis-CI and GitHub tagging.
Deploy snapshots to JFrog OSS Artifactory
To have snapshot published to a public repo for others to use it, we can resort to Jfrog OSS Artifactory oss.jfrog.org (OJO), since Bintray does not support snapshot builds. (This section is inspired by the blog post by Álvaro Sánchez). Before you can publish to OJO, please read this document.
Setup build scripts:
Let us start with
Since OJO and Bintray are tightly coupled, it is the same credentials used.
Commit and push to GitHub and go watch the build on Travis-CI. Notice, that the build ends with a push to OJO.
That’s it. Travis-CI will now publish both snapshot versions and tagged versions to OJO and Bintray.
But wait - there is a bit more.
Optimizing Travis-CI setup
Take a look at the log-output from Travis-CI and notice, that it downloads Gradle and all of the maven dependencies on each build.
Travis-CI supports caching of these artifacts and a couple of other options.
Add the following to
.travis.yml just below the
language: groovy block:
This will reduce downloads and build time on Travis-CI.
Travis-CI is a great tool to build and deploy your Grails plugin: it will help you maintain your code when receiving pull requests from the community. Happy CI’ing,