Check Jenkins job status after triggering a build remotely Check Jenkins job status after triggering a build remotely jenkins jenkins

Check Jenkins job status after triggering a build remotely


I solved this problem using polling of the Jenkins server. When a job is started remotely the return headers has the job queue URL. Using this one can make more API calls to get status.

Steps:

  • start the job
  • parse return 'Location' header
  • poll the queue looking for job to start
    • job queue entry will have an 'executable' entry in its json or xml with job number once it starts
  • poll the job status waiting for a result

I used python and the Requests module to do this

#!/usr/bin/pythonimport requestsimport reimport sys import jsonimport time# secs for polling Jenkins API#QUEUE_POLL_INTERVAL = 2 JOB_POLL_INTERVAL = 20OVERALL_TIMEOUT = 3600 # 1 hour# job specifics: should be passed inauth_token = 'buildmaster:173223588624f980c3AAA68d4d8efe0c'jenkins_uri = '192.168.115.187:8080'job_name = 'rf_systest'build_token = 'rf_systest_auth_token'# start the build#start_build_url = 'http://{}@{}/job/{}/build?token={}'.format(        auth_token, jenkins_uri, job_name, build_token)r = requests.post(start_build_url)# from return headers get job queue location#m = re.match(r"http.+(queue.+)\/", r.headers['Location'])if not m:    # To Do: handle error    print "Job starte request did not have queue location"    sys.exit(1)# poll the queue looking for job to start#queue_id = m.group(1)job_info_url = 'http://{}@{}/{}/api/json'.format(auth_token, jenkins_uri, queue_id)elasped_time = 0 print '{} Job {} added to queue: {}'.format(time.ctime(), job_name, job_info_url)while True:    l = requests.get(job_info_url)    jqe = l.json()    task = jqe['task']['name']    try:        job_id = jqe['executable']['number']        break    except:        #print "no job ID yet for build: {}".format(task)        time.sleep(QUEUE_POLL_INTERVAL)        elasped_time += QUEUE_POLL_INTERVAL    if (elasped_time % (QUEUE_POLL_INTERVAL * 10)) == 0:        print "{}: Job {} not started yet from {}".format(time.ctime(), job_name, queue_id)# poll job status waiting for a result#job_url = 'http://{}@{}/job/{}/{}/api/json'.format(auth_token, jenkins_uri, job_name, job_id)start_epoch = int(time.time())while True:    print "{}: Job started URL: {}".format(time.ctime(), job_url)    j = requests.get(job_url)    jje = j.json()    result = jje['result']    if result == 'SUCCESS':        # Do success steps        print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)        break    elif result == 'FAILURE':        # Do failure steps        print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)        break    elif result == 'ABORTED':        # Do aborted steps        print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)        break    else:        print "{}: Job: {} Status: {}. Polling again in {} secs".format(                time.ctime(), job_name, result, JOB_POLL_INTERVAL)    cur_epoch = int(time.time())    if (cur_epoch - start_epoch) > OVERALL_TIMEOUT:        print "{}: No status before timeout of {} secs".format(OVERALL_TIMEOUT)        sys.exit(1)    time.sleep(JOB_POLL_INTERVAL)

Output:

Tue Jan 30 16:24:08 2018: Job rf_systest added to queue: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/queue/item/164/api/jsonTue Jan 30 16:24:39 2018: Job rf_systest not started yet from queue/item/164Tue Jan 30 16:25:00 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/jsonTue Jan 30 16:25:01 2018: Job: rf_systest Status: None. Polling again in 20 secsTue Jan 30 16:25:21 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/jsonTue Jan 30 16:25:21 2018: Job: rf_systest Status: None. Polling again in 20 secsTue Jan 30 16:25:41 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/jsonTue Jan 30 16:25:41 2018: Job: rf_systest Status: None. Polling again in 20 secsTue Jan 30 16:26:01 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/jsonTue Jan 30 16:26:01 2018: Job: rf_systest Status: None. Polling again in 20 secsTue Jan 30 16:26:21 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/jsonTue Jan 30 16:26:21 2018: Job: rf_systest Status: SUCCESS

JSON from a Jenkins queue once its job has started:

{    "_class": "hudson.model.Queue$LeftItem",    "actions": [        {            "_class": "hudson.model.CauseAction",            "causes": [                {                    "_class": "hudson.model.Cause$RemoteCause",                    "addr": "10.20.30.60",                    "note": null,                    "shortDescription": "Started by remote host 10.20.30.60"                }            ]        }    ],    "blocked": false,    "buildable": false,    "cancelled": false,    "executable": {        "_class": "org.jenkinsci.plugins.workflow.job.WorkflowRun",        "number": 45,        "url": "http://192.168.115.187:8080/job/rf_systest/45/"    },    "id": 95,    "inQueueSince": 1517342648136,    "params": "",    "stuck": false,    "task": {        "_class": "org.jenkinsci.plugins.workflow.job.WorkflowJob",        "color": "blue_anime",        "name": "rf_systest",        "url": "http://192.168.115.187:8080/job/rf_systest/"    },    "url": "queue/item/95/",    "why": null}


I had similar problem to get state with rest api only.
this was my solution (it is a weak and not stable solution!):

#Ex. http://jenkins.com/job/testJOB_URL="${JENKINS_URL}/job/${JOB_NAME}"#here you can ask for next build job numberfunction getNextBuildNr(){  curl --silent ${JOB_URL}/api/json | grep -Po '"nextBuildNumber":\K\d+'}    # this will request the Status of jobfunction getBuildState(){  buildNr=$1  curl --silent ${JOB_URL}/${buildNr}/api/json | grep -Po '"result":\s*"\K\w+'}#this will wait for your Job state, by polling Jenkins every secondfunction waitForJob() {  buildNr=$1  state=""  while [ "${state}" == "" ]  do     sleep 1     state=$(getBuildState ${buildNr})     echo -n '.'  done  echo -e "\n"}#now you can run and buildBUILD_NR=$(getNextBuildNr)# input here your code/function to trigger the jobwaitForJob ${BUILD_NR}BUILD_STATE=$(getBuildState ${BUILD_NR})echo "$BUILD_STATE"


You can use Jenkins API for this. A sample Python script:

import jsonimport requestsimport timejob_name = "testjob" .  #Give your job name heredef jenkins_job_status(job_name):        try:                url  = "https://your_jenkins_endpoint/job/%s/lastBuild/api/json" %job_name   #Replace 'your_jenkins_endpoint' with your Jenkins URL                while True:                        data = requests.get(url).json()                        if data['building']:                                time.sleep(60)                        else:                                if data['result'] == "SUCCESS":                                        print "Job is success"                                        return True                                else:                                        print "Job status failed"                                        return False        except Exception as e:                print str(e)                return Falseif __name__ == "__main__":        if jenkins_job_status(job_name):                print "Put your autmation here for 'job is success' condition"        else:                print "Put your autmation here for 'job is failed' condition" 

Refer http://www.easyaslinux.com/tutorials/devops/how-to-check-build-status-of-jenkins-job-using-python-script/ for detailed explanation