Get Jenkins Job Build ID from Queue ID

I chose Kdawg's answer, because it helped lead me in the direction that I needed. Thank you!

I'm also including my own answer, because the solution I implemented was different than Kdawg's answer, and I feel it will add value for other people.

First off, I'm new to Jenkins. So if I misspeak, please feel free to correct me. Second, I had a slight learning curve in that there is a difference between a Jenkins "queue item" and a Jenkins "build job". The instant that a "queue item" has been created, there is no "build job" ID, because no build job has started. Also, once a build job has started, the queue item has 5 minutes before it is deleted.

When I perform these tasks:

curl -X POST "http://jenkins_srv:8080/job/MY_JOB/buildwithParameters?this=1&that=2" --user name:pass
curl -X POST "http://jenkins_srv:8080/job/MY_JOB/buildwithParameters?this=1&that=2" --user name:pass
curl -X POST "http://jenkins_srv:8080/job/MY_JOB/buildwithParameters?this=1&that=2" --user name:pass

Jenkins will schedule 3 build jobs to be run in a queue. These will be "queue items". These "queue items" will have a "Queue ID". In the example given in my original question, lets suppose that these three curl commands create "queue items" with "Queue ID"s 121, 122, & 123.

Why is this important?

Because depending on the load of your Jenkins server, the item that was queued may or may not be run immediately. If it runs immediately, then Kdawg's answer is definitely correct. Running his commands:

curl -X GET http://jenkins_srv:8080/queue/item/121/api/json?pretty=true --user name:pass
curl -X GET http://jenkins_srv:8080/queue/item/122/api/json?pretty=true --user name:pass
curl -X GET http://jenkins_srv:8080/queue/item/123/api/json?pretty=true --user name:pass

This will get queue information about each "queue item", and in what returns, there is definitely a way to obtain a "build job" ID, if the build job has started. If a build job has not yet started, this information will be blank.

Here's the additional part that, I feel, adds value.

Once a build job has started, the information in Kdawg's answer will be populated in the response to the three curl -X GET commands. Also, by default, Jenkins is designed to scavenge (garbage collection, choose your own term) the "queue item"s every 5 minutes. So in other words, if all you have is a "queue item" ID and the 5 minute data retention window passes, then you need another mechanism in order to get a "build job" ID from a "queue item" ID.

So, in my case, I'm using Jenkins as a front end, and Ansible on the back end to perform server configuration and application deployments. Some of these application deployments can take 30 minutes or more, well beyond the 5 minute data retention period of the "queue items".

So the problem that I had to solve, if all I have is a "queue item" ID, then how do I find a "build job" ID, regardless of when I'm checking, seconds later or hours later?

Here was my solution (Note that I required XML output, FYI).

I ran this command:

curl -X POST "http://jenkins_srv:8080/job/MY_JOB/buildwithParameters?this=1&that=2" --user name:pass

This command would return this information:

Runtime responseHeaders Date: Day, ## Non Year xx:yy:zz GMT
X-Content-Type-Options: nosniff
Location: http://jenkins_srv:port/queue/item/123/
Content-Length: 0
Server: Jetty(9.4.z-SNAPSHOT)

From here, I can parse out 123 from the Location field.

I then slept for 10 seconds. After the sleep, I run this command on a 10 second loop:

curl -X GET http://jenkins_srv:8080/queue/item/123/api/xml

I did that until I either:

  1. I got a queue item return that included the xpath //executable/number that's shown in Kdawg's example, or
  2. I got HTML 404 status code for more than 10 minutes, meaning the job hasn't been queue'd yet or I passed the 5 minute data retention window.

The loop in this way handles a burdened Jenkins server that's sluggish on handling queue requests. So presumably if I get to the end of 10 minutes, then my approach will still handle the use case that my automation approach has successfully queue'd and run the job, but it's checking Jenkins outside the data retention window. In this case, I would run this command:

curl -X GET http://jenkins_srv:port/job/MY_JOB/api/xml?tree=builds[id,number,result,queueId]&xpath=//build[queueId=123]

This returns the XML info for any "build job" that also contains a queueId of 123, as shown below:

<?xml version="1.0"?>
    <build _class="hudson.model.FreeStyleBuild">
        <id>456</id>
        <number>456</number>
        <queueId>123</queueId>
        <result>SUCCESS</result>
    </build>

In this way, I was able to authoritatively get a "build job" ID while only having a "queue item" ID regardless of the time difference between when I started and when I checked back.


Assuming that you have a location of http://jenkins_srv:8080/queue/item/123/, you can GET http://jenkins_srv:8080/queue/item/123/api/json?pretty=true to return information about that queue item (you can also not include ?pretty=true if you don't care about formatting, or use api/xml if you want the results in XML).

I don't know if there's standard documentation on the queue API, but it appears that if the queue item has completed (maybe also if it's currently being built?) it will have an executable node. One for my server looked like this:

"executable" : {
    "_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun",
    "number" : 10,
    "url" : "http://192.168.99.100:32769/job/configure/10/"
}

You can then GET the API for the URL specified in executable.url. In my case, GET http://192.168.99.100:32769/job/configure/10/api/json?pretty=true. From there, you should have all the information you need, including whether or not the build is currently being built, how long the build took/has taken, the result, etc.

Also, if you want information on your entire build queue, you can GET http://jenkins_srv:8080/queue/api/json?pretty=true