Supporting Feature Branch Deployments in Your Personal CI Server

DZone 's Guide to

Supporting Feature Branch Deployments in Your Personal CI Server

Update your personal Jenkins CI server to support side-by-side deployments of feature branches.

· DevOps Zone ·
Free Resource

In a previous article, I stepped you through the process of building a basic personal CI server with Jenkins. We got to a point where we could build a Java web application with Gradle and deploy it to WildFly. For those who are impatient, the exported VirtualBox image with Jenkins configured using these steps is available here. The username and password combination for Linux, Jenkins, and WildFly is myci and password.

There are plenty of opportunities to improve on this basic setup. In this article, we’ll update the Jenkins build process to support branch deployments.

Adding Support for GitFlow

GitFlow is all about working in isolated branches and merging back into a common branch like master once development is complete. This means that typically, you’ll want to be able to deploy branches side by side in your application server during development.

This is easy to accomplish with WAR files because the context that a WAR file is assigned is typically defined by the filename. WildFly does support defining context roots via the jboss-web.xml file, but renaming the WAR file is an easy solution for simple environments or for building projects you don't maintain the source code for.

We’ll rename the WAR file through an update to the Bash script that we use to find the WAR file while building the Maven deploy.xml file. Open up http://localhost:9080, select the Sample_Project_Build item, and click the Configure link. Note that we are configuring the parent item and not configuring the individual branches. By configuring the parent item, we are defining settings that will be inherited by all the child branches.

Scroll down to the Execute shell section and replace the script with the following code:

pushd build/libs
shopt -s nullglob
for file in *.war; do
  if [ "${BRANCH_NAME}" == "master" ]; then
          mv ${file} ${war_filename}

echo "<project><modelVersion>4.0.0</modelVersion><groupId>example.org</groupId><artifactId>wildfly-deploy</artifactId><version>1</version><build><plugins><plugin><groupId>org.wildfly.plugins</groupId><artifactId>wildfly-maven-plugin</artifactId><version>1.1.0.Alpha11</version><configuration><filename>build/libs/${war_filename}</filename><hostname>${wildfly_hostname}</hostname><port>${wildfly_port}</port><username>${wildfly_username}</username><password>${wildfly_password}</password><targetDir>.</targetDir><force>true</force></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><executions><execution><id>default-compile</id><phase>none</phase></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><executions><execution><id>default-compile</id><phase>none</phase></execution></executions></plugin></plugins></build></project>" > deploy.xml

This bash script searches the /build/libs directory for any WAR files and renames the WAR file to include the name of the Git current branch if the branch is not master.

What this means is that the WAR file build from the branch casper/new-feature-1 will have a filename gradle-sample-project-casper-new-feature-1.war. When deployed to Wildfly, this feature branch is accessible under the URL http://localhost:8080/gradle-sample-project-casper-new-feature-1/.

The master branch does not have any renaming done to the resulting WAR file, so it remains available under the default URL of http://localhost:8080/gradle-sample-project/.

In this way, we can deploy feature branches and the mainline branch side by side.

continuous integration, devops, feature branches, gitflow

Published at DZone with permission of Matthew Casperson , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}