Continuous Delivery Pipeline with Jenkins, Gradle and Artifactory. (part 1 – commit stage)

In this series of articles I will share my experience building deployment pipeline or build pipeline with open source tools.
Deployment pipeline is an automated process that manage all software changes – from version control check-in to production.
Usually automated software delivery process consist of several stages. For this article, our pipeline will have following stages:

  1. Commit stage – responsible for delivering bad or good news for development team. Code is broken! Functions include code compilation, run suite of unit tests and code analysis.
  2. Automated qa stage – assert that systems work on functional level and meet specifications.
  3. Manual QA stage – testers trying to find any defects not caught during automated phase.
  4. UAT stage – deployment to stage environment for UAT and other non functional testing – load, stress, e.t.c
  5. Release stage – deployment to production environment

Creating commit stage with Jenkins, Artifactory and Gradle for Java application.
Commit stage is the first stage in deployment pipeline. The main goal of commit stage is to signal the team that build is broken or good as fast as possible.
When a developer commit change into version control, we want to check the latest version of software quickly. Commit stage usually include following tasks:
  • Compile Code
  • Run unit tests and some integration tests
  • Perform quality analysis of the code
  • Prepare artifacts to use in later stage of pipeline – binaries, databases.
  • Include version number into artifacts – war, jar files.
  • kick out next stages of pipeline if conditions are met, for example, automated acceptance tests

For build script that holds everything together we will be using gradle – the build tool that occupy unique position between ant and maven – combining ant flexibility, maven’s convention over configuration and groovy programming language – makes this  task easy to accomplish. The whole toolchain for commit stage are on picture below.

After you download and configure gradle, you will create build.gradle file. This is replacement for maven.pom and ant build file.

Compiling java and testing project:
Creating version number for our artifacts:

apply plugin: 'java'

check

Gradle java plugin have several lifecycle tasks, including check and build.
This will cover compilation and testing of our project. I would prefer to keep all test execution time under 10 min, so build process is fast.
One of the important consideration is tracking of version number – deployed version, war file version and so on. We will stick with Maven convention in file naming, for example 0.0.1-SNAPSHOT.
apply plugin: 'war'


group='org.myproject'
archivesBaseName = 'project_name'
// read environment variables, including variables passed by jenking continuous integration server
env = System.getenv()

// version object
// major, minor and releaseType properties from gradle.properties file
// env.BUILD_NUMBER - from Jenkins server
version = new Version(version_major: major as int, minor: minor as int, buildnumber: env.BUILD_NUMBER as int, releaseType:releaseType)
class Version {
int version_major
int minor
int buildnumber
String releaseType
String buildTime
 
String toString() {
"$version_major.$minor.$buildnumber-$releaseType"
}
}

// include version information into generated war file
war {
    archiveName="$baseName-$version.$extension"
    manifest {
        attributes 'Specification-Title': 'My Project ' ,'Implementation-Title': env.BUILD_TAG, 'Implementation-Version': version 
    }
}
// using ant, create a build.properties file with version information that can be later accessed by //java application.

ant.propertyfile(file:"src/main/resources/build.properties", comment:'Build Properties') {
  ant.entry(key:'version',value:version)
  ant.entry(key:'build_tag',value:env.BUILD_TAG)
  ant.entry(key:'buildTime', value:env.BUILD_ID)
}

Now let connect everything with Jenkins. In order to do it we will need to install Jenkins Gradle plugin and create free-style software project job. This job will be responsible for our commit stage.

To see all variables that jenkins make available for you build script you can create and execute following task in gradle:
task buildnumber << {
   env = System.getenv()

    env.each{
    key, value -> println "$key = $value";
}

The result of the job will be war file with file name as per Maven convention.

In next blog post we will be saving resulting myproject-0.0.1-SNAPSHOT.war file into Artifactory repository and deploy to our java server container.
Also we will configure static code quality analysis. We will be using Sonar as our quality control tool.

6 Comments

  1. Thank you for this helpful tips. Gradle seems to work great for defining build pipelines. What is your experience with the Jenkins Gradle plugin?

    Reply
  2. Very positive experience. I use it every day and never had any problem. It just works!

    Reply
  3. Eugene, you wrote some interesting articles, including this one. BUT you promised next parts, and I could not find them! :) Do you have plans to write next part for this post, and for Integration Testing with Gradle, Selenium and Spock for Java project ?

    Reply
    • I do have plan but could not find time to do it. Do you have any specific question?

      Reply
      • Hi, Also interested in future parts

        But for now I seem to be missing something – I can see how to integrate Gradle/Jenkins/Artifactory to get the assembled WAR files into Artifactory via a jenkins job but I can’t find out how to set Jenkins up to say :-
        For this Job get the latest artifact from Artifactory to be able to copy it over to the WAS server (set up as a Jenkins slave)

        Cheers for any help

        Keir

        Reply
        • What I did was quite simple: I use another, parameterized Jenkins job to download specified version of the war file into Jenkins and then deploy it using my server deployment procedure.
          In Gradle, create a job,
          task download << { def env = System.getenv() ant.get(src:”http://server/nexus/content/repositories/releases/${artifactId}/${env.VERSION}/${artifactId}-${env.VERSION}.war”, dest:”./${artifactId}-${env.VERSION}.war”) } Then use Jenkins to call this task, get the file and move downloaded file to location you need it or script whole deployment task. You use Jenkins variables to get what you need, including latest build from Nexus repository.

          Reply

Submit a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>