远程触发构建后检查 Jenkins 作业状态

问题描述 投票:0回答:6

我有一个脚本可以使用令牌远程触发 Jenkins 上的作业。这是我的脚本:

JENKINS_URL='http://jenkins.myserver.com/jenkins'
JOB_NAME='job/utilities/job/my_job'
JOB_TOKEN='my_token'

curl "${JENKINS_URL}/${JOB_NAME}/buildWithParameters?token=${JOB_TOKEN}"

运行后,我得到以下响应:

* Hostname was NOT found in DNS cache
*   Trying 10.5.187.225...
* Connected to jenkins.myserver.com (10.5.187.225) port 80 (#0)
> GET /jenkins/job/utilities/job/my_job/buildWithParameters?token=my_token HTTP/1.1
> User-Agent: curl/7.37.1
> Host: jenkins.myserver.com
> Accept: */*
> 
< HTTP/1.1 201 Created
* Server nginx/1.6.2 is not blacklisted
< Server: nginx/1.6.2
< Date: Tue, 03 Feb 2015 23:40:47 GMT
< Content-Length: 0
< Location: http://jenkins.myserver.com/jenkins/queue/item/91/
< Connection: keep-alive
< Cache-Control: private
< Expires: Wed, 31 Dec 1969 16:00:00 PST
< 
* Connection #0 to host jenkins.myserver.com left intact

我注意到它在标头中返回队列 url:http://jenkins.myserver.com/jenkins/queue/item/91。但我不知道应该如何使用这个返回网址。

1)我想知道是否有人知道如何检查我刚刚创建的作业的状态?

2)由于上述响应没有返回作业#,我无法真正使用此 api 调用:

curl http://jenkins.myserver.com/jenkins/job/utilities/job/my_job/8/api/json

检查状态。那么从上面的响应中获取位置 url 后,我可以在哪里获取职位名称和职位编号呢?

谢谢

jenkins build jenkins-plugins jenkins-cli
6个回答
40
投票

我使用 Jenkins 服务器轮询解决了这个问题。当远程启动作业时,返回标头具有作业队列 URL。使用这个可以进行更多 API 调用来获取状态。

步骤:

  • 开始工作
  • 解析返回“位置”标头
  • 轮询队列寻找要开始的作业
    • 一旦启动,作业队列条目将在其 json 或 xml 中包含一个带有作业编号的“可执行”条目
  • 轮询作业状态等待结果

我使用 python 和 Requests 模块来做到这一点

#!/usr/bin/python

import requests
import re
import sys 
import json
import time

# secs for polling Jenkins API
#
QUEUE_POLL_INTERVAL = 2 
JOB_POLL_INTERVAL = 20
OVERALL_TIMEOUT = 3600 # 1 hour

# job specifics: should be passed in
auth_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)

输出:

Tue Jan 30 16:24:08 2018: Job rf_systest added to queue: http://buildmaster:[email protected]:8080/queue/item/164/api/json
Tue Jan 30 16:24:39 2018: Job rf_systest not started yet from queue/item/164
Tue Jan 30 16:25:00 2018: Job started URL: http://buildmaster:[email protected]:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:01 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:25:21 2018: Job started URL: http://buildmaster:[email protected]:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:21 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:25:41 2018: Job started URL: http://buildmaster:[email protected]:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:41 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:26:01 2018: Job started URL: http://buildmaster:[email protected]:8080/job/rf_systest/79/api/json
Tue Jan 30 16:26:01 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:26:21 2018: Job started URL: http://buildmaster:[email protected]:8080/job/rf_systest/79/api/json
Tue Jan 30 16:26:21 2018: Job: rf_systest Status: SUCCESS
工作开始后,来自 Jenkins 队列的 JSON:

{ "_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 }
    

7
投票
我也遇到了类似的问题,仅使用 REST API 获取状态。

这是我的解决方案(这是一个
弱且不稳定的解决方案!):

#Ex. http://jenkins.com/job/test JOB_URL="${JENKINS_URL}/job/${JOB_NAME}" #here you can ask for next build job number function getNextBuildNr(){ curl --silent ${JOB_URL}/api/json | grep -Po '"nextBuildNumber":\K\d+' } # this will request the Status of job function 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 second function waitForJob() { buildNr=$1 state="" while [ "${state}" == "" ] do sleep 1 state=$(getBuildState ${buildNr}) echo -n '.' done echo -e "\n" } #now you can run and build BUILD_NR=$(getNextBuildNr) # input here your code/function to trigger the job waitForJob ${BUILD_NR} BUILD_STATE=$(getBuildState ${BUILD_NR}) echo "$BUILD_STATE"
    

7
投票
您可以使用 Jenkins API 来实现此目的。 Python 脚本示例:

import json import requests import time job_name = "testjob" . #Give your job name here def 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 False if __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"
参考 

http://www.easyaslinux.com/tutorials/devops/how-to-check-build-status-of-jenkins-job-using-python-script/ 获取详细说明


5
投票
当您触发作业时,该作业将被放入队列中。实际的构建仅在它开始运行时才创建,此时构建会获得一个构建号。如果所有执行器都很忙,有时可能需要很长时间才能创建并开始运行构建。

触发作业时获取内部版本号的唯一方法是使用

Jenkins CLI 的“build”命令。如果您使用 -w 选项,该命令将在构建开始之前不会返回,然后它将打印“Started build #N”

您实际上并不需要 java cli.jar,只需一个 ssh 客户端就足够了。请参阅

https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+SSH

除此之外,没有已知的解决方案。您也许能够搜索构建并找到在触发作业时触发的构建,但这是一项艰巨的工作。


2
投票
对于那些需要从另一个 Jenkins 触发远程 Jenkins 作业的人来说,这是一个非常好的解决方案,允许触发远程作业并检查其状态:

https://github.com/jenkinsci/parameterized-remote-trigger-插件/blob/master/README_PipelineConfiguration.md

就这么简单:

def handle = triggerRemoteJob job: 'https://myjenkins:8080/job/JobWithoutParams', auth: TokenAuth(apiToken: '<theApiToken>', userName: '<userName>'), parameters: 'param1=abc\nparam2=xyz'


0
投票
完全启用 Groovy 的解决方案将类似于以下内容:

import groovy.json.JsonSlurper while(true){ sh """ curl -X POST -u "admin:xxx" "https://another-jenkins.com/job/jobName/build" """ def response = sh(script: """ curl -X GET -u "admin:xxx" "https://another-jenkins.com/job/jobName/lastBuild/api/json" """, returnStdout: true) def jsonSlurper = new JsonSlurper() def obj = jsonSlurper.parseText(response) if (!obj.building){ if(obj.result=="FAILURE"){ println("remote jenkins failing") //throw new Exception("QA JENKINS returns failure.") } break; } sleep(3000) }
    
© www.soinside.com 2019 - 2024. All rights reserved.