A Tale of Two Build Tools: Integrating XL Release with Jenkins and Bamboo


Posted by
Julie d'ANTIN

April 27, 2015

This is a guest post from XebiaLabs, the makers of XL Release – an end-to-end pipeline orchestration tool for Continuous Delivery and DevOps teams. In this blog post, they explain how to integrate it with Jenkins and Bamboo. 

An integration story…

I discovered that XL Release does not have built-in support to integrate with the Bamboo build tool as it does for Jenkins. But I also discovered that XL Release’s extensibility makes it easy to configure a type definition and a script to enable an interface with Bamboo.

Let’s look at the support for Jenkins. XL Release provides a task definition:

xlr jenkins task

and an entry under the configuration tab:
xlr jenkins server

With these we can define one or more Jenkins servers and use them to execute the build jobs defined on them. Nice.

Bamboo doesn’t have such out-of-the-box support, so let’s take a look at how we could configure the objects we need.  Since Bamboo has a REST API, we can extend the HttpConnection object to provide us a Bamboo Server object by defining a type in xl-release-server/ext/synthetic.xml:

<type type="bamboo.Server" extends="configuration.HttpConnection" />

Now we need a task to call out to the API; let’s extend the PythonScript object for this so we can take advantage of Python tremendous versatility. The script will actually run under Jython, so we can utilize Java classes too if needed. Our input will be the project-plan key to identify the Bamboo plan, and let’s code a few output fields to return some information about the build after it completes.

<type type="bamboo.RunPlan" extends="xlrelease.PythonScript">
 <property name="bambooServer" category="input" label="Server" referenced-type="bamboo.Server" kind="ci" />
 <property name="projPlanKey" category="input" />
 <property name="buildNumber" category="output" />
 <property name="buildState" category="output" />
 <property name="state" category="output" />
</type>

Our next task is to write the Python script to call out to Bamboo. The namespace of the type, “bamboo” in this case, determines the script directory, and the type name determines the script name. So our script will be called RunPlan.py and will live in xl-release-server/ext/bamboo.

The script starts with some typical Python imports. We’ll use com.xhaus.jyson.JysonCodec for json since that’s included in the XL Release libraries. Next we set some variables for contentType and headers for all of our HTTP calls, and define some boolean and text fields from the build result.

Finally the main body of the code make a post request to Bamboo’s url using the built-in HttpRequest object. We supply the url, content type and headers. We could have added authentication here to override what’s defined on the Bamboo Server object, but let’s leave that for later. An empty set of curly braces is required for the JSON content body.

Then we use the JSON library module to parse two items out of the results: the build number and the build result key.

We store the latter in the variable brkey to keep it handy to pass to our helper methods. A simple while loop polls for a finished result every five seconds. That interval would be better as a configurable value; this is something else we’ll save for later.

When the loop ends, we query the job’s results (note the change in the query string from “queue” to “result”), print some messages and set the two state output variables so XL Release can use them to control future actions.  See the xlr-bamboo-plugin repo for future updates to the code.

import sys
import time
import com.xhaus.jyson.JysonCodec as json

print "Executing RunPlan.py\n"

if bambooServer is None:
 print "No server provided."
 sys.exit(1)

contentType = 'application/json'
headers = {'accept' : 'application/json'}

def finished(brkey):
 request = HttpRequest(bambooServer)
 response = request.get('/rest/api/latest/result/' + brkey, contentType=contentType, headers=headers)
 return json.loads(response.response)['finished']

def successful(brkey):
 request = HttpRequest(bambooServer)
 response = request.get('/rest/api/latest/result/' + brkey, contentType=contentType, headers=headers)
 return json.loads(response.response)['successful']

def getState(brkey):
 request = HttpRequest(bambooServer)
 response = request.get('/rest/api/latest/result/' + brkey, contentType=contentType, headers=headers)
 return json.loads(response.response)['state']

def getBuildState(brkey):
 request = HttpRequest(bambooServer)
 response = request.get('/rest/api/latest/result/' + brkey, contentType=contentType, headers=headers)
 return json.loads(response.response)['buildState']

def getPrettyBuildStartedTime(brkey):
 request = HttpRequest(bambooServer)
 response = request.get('/rest/api/latest/result/' + brkey, contentType=contentType, headers=headers)
 return json.loads(response.response)['prettyBuildStartedTime']

def getPrettyBuildCompletedTime(brkey):
 request = HttpRequest(bambooServer)
 response = request.get('/rest/api/latest/result/' + brkey, contentType=contentType, headers=headers)
 return json.loads(response.response)['prettyBuildCompletedTime']

request = HttpRequest(bambooServer)
response = request.post('/rest/api/latest/queue/' + projPlanKey, '{}', contentType=contentType, headers=headers)
result = json.loads(response.response)

buildNumber = result['buildNumber']
print 'Build number is ' + str(buildNumber) + '\n'
brkey = result['buildResultKey']

while (not finished(brkey)):
 time.sleep(5)

print "Build job started at " + getPrettyBuildStartedTime(brkey) + "\n"
prettyBuildCompletedTime = getPrettyBuildCompletedTime(brkey)

if successful(brkey):
 print "Build job completed successfully at " + prettyBuildCompletedTime + "\n"
else:
 print "Build job failed at " + prettyBuildCompletedTime + "\n"

buildState = getBuildState(brkey)
state = getState(brkey)

About XebiaLabs

XebiaLabs is the fastest-growing, leading global provider of automation software for DevOps and Continuous Delivery helping companies to accelerate the delivery of new software. XebiaLabs’ products provide the automation, efficiency and insight organizations need to meet the demand for faster software deployment cycles.

For more information, please visit www.xebialabs.com.