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