Consuming Jenkins API using Python

Lately I’ve been using Jenkins as a central hub for automated task across multiple machines, think a central cron system with a slick web interface.

In a nutshell Jenkins CI is the leading open-source continuous integration server. Built with Java, it provides over 400 plugins to support building and testing virtually any project.

One thing that is very nice about Jenkins is the easy to use REST JSON API .

Since our Jenkins system is used internally I’ve allowed the anonymous user full read access, this allows our API read call operations in without the need to use an API KEY.

Each Jenkins page has a REST API hyperlink at the bottom, this is because each page has its own endpoint.

I’ll go over getting a list of all Projects , this uses the end point of /api/json:

>>> from urllib2 import urlopen
>>> from json import loads
>>>
>>> req = urlopen('http://127.0.0.1:8080/api/json')
>>> res = req.read()
>>> data = loads(res)

At this point we have our JSON data loaded in to a Python dict (just like every other JSON API):

>>> data.keys()
[u'unlabeledLoad', u'jobs', u'description', u'views', u'quietingDown', u'assignedLabels',
u'nodeDescription', u'useCrumbs', u'numExecutors', u'mode', u'slaveAgentPort',
u'overallLoad', u'useSecurity', u'primaryView', u'nodeName']

We can go ahead and parse over these Jobs :

>>> for job in data['jobs']:
...   print job['name']
...
Pull Logs from Cloud
Jenkins Job Status Notify

Or we can look directly at the dict object of the first job:

>>> data['jobs'][0].keys()
[u'url', u'color', u'name']

This will give us the full url to the job, all we need to do is append api/json to get our object:

>>> req = urlopen('%s/%s' % (data['jobs'][0]['url'], 'api/json'))
>>> res = req.read()
>>> job = loads(res)

And again we have a Python dict object:

>>> job.keys()
[u'scm', u'color', u'lastSuccessfulBuild', u'actions', u'lastCompletedBuild',
u'lastUnsuccessfulBuild', u'upstreamProjects', u'lastFailedBuild', u'healthReport',
u'queueItem', u'lastBuild', u'lastStableBuild', u'description', u'downstreamProjects',
u'concurrentBuild', u'lastUnstableBuild', u'buildable', u'displayNameOrNull',
u'inQueue', u'keepDependencies', u'name', u'displayName', u'builds', u'url',
u'firstBuild', u'nextBuildNumber', u'property']

Let say for example we want to see if the last ran build for this job was success, to do that we use the lastCompletedBuild key:

>>> job['lastCompletedBuild'].keys()
[u'url', u'number']

And like last time lets make the API call:

>>> req = urlopen('%s/%s' % (job['lastCompletedBuild']['url'], 'api/json'))
>>> res = req.read()
>>> build = loads(res)

And yet again a Python dict:

>>> build.keys()
[u'building', u'changeSet', u'builtOn', u'description', u'artifacts', u'timestamp',
u'number', u'actions', u'id', u'keepLog', u'url', u'culprits', u'result', u'executor',
u'duration', u'fullDisplayName', u'estimatedDuration']

But from here we can see the build number and status:

>>> build['number'], build['result']
(16, u'SUCCESS')

I hope this was helpful.