jenkinsapi python - 如何触发和跟踪作业结果

6 python jenkins jenkins-api

我用来JenkinsAPI触发参数化作业。我知道 Jenkins 使用 REST API,但我们的设置不允许直接这样做;所以我触发工作的主要方式是通过这个库。

到目前为止,我在服务器上查找作业或触发作业没有任何问题,但我面临两个问题

1)当我触发一个作业时,我不知道它的结果。我假设运行该函数时会返回作业的输出build_job,但事实并非如此。我需要知道该作业是否通过或失败,但我找不到获取此信息的方法,因为当我触发它时我什至无法检索作业编号。

2)作业运行时出现错误,尽管作业确实顺利通过:

raise ValueError("Not a Queue URL: %s" % redirect_url)

我确实读了一点,似乎 Jenkins 正在 http 和 https url 之间切换,这使库感到困惑。如果我理解正确的话,这被认为是詹金斯问题,因此没有得到解决JenkinsAPI

这是到目前为止的代码,它确实连接到我的詹金斯服务器,检索作业列表,触发作业,但不允许我知道作业是通过还是失败,并且我收到了前面提到的错误。

有什么方法可以让它发挥作用,以便我可以获得我触发的作业的通过/失败结果?

jenkins_url = 'http://myjenkins_host:8080'   
# Create server
server = Jenkins(jenkins_url, username='user', password='123456789abcdef')
# Check job and print description
for job_name, job_instance in server.get_jobs():
    if job_name == "testjob":
        print('Job Name:%s' % job_instance.name)
        print('Job Description:%s' % (job_instance.get_description()))

# Trigger job
params = {'a':1, 'b':2, 'c': True}
server.build_job("testjob", params)
# HOW do I get the result of this job???
Run Code Online (Sandbox Code Playgroud)

Rao*_*zur 7

我不是 Jenkins Python API 的忠实粉丝,说实话,我什至没有使用过它一次。我个人更喜欢在 Python 中使用原始 JSON API,它更适合我(这就是为什么我的示例将使用 JSON API 来代替,但最终,目标仍然是通过 python 脚本实现的)。

现在回答您的问题,您可以通过 API 时不时地查询来跟踪作业状态和结果。但首先要说的是。

1.前提条件

安装了Python 2.7 或 3.x 和python requests库:

pip install requests

对于Python 3.x

pip3 install requests

另:如何安装 pip

2.Python脚本触发并跟踪结果

import requests
import time


jenkins_url = "http://localhost:8080"
auth = ("USERNAME", "PASSWORD")
job_name = "Dummy"
request_url = "{0:s}/job/{1:s}/buildWithParameters".format(
    jenkins_url,
    job_name,
)

print("Determining next build number")
job = requests.get(
    "{0:s}/job/{1:s}/api/json".format(
        jenkins_url,
        job_name,
    ),
    auth=auth,
).json()
next_build_number = job['nextBuildNumber']
next_build_url = "{0:s}/job/{1:s}/{2:d}/api/json".format(
    jenkins_url,
    job_name,
    next_build_number,
)

params = {"Foo": "String param 1", "Bar": "String param 2"}
print("Triggering build: {0:s} #{1:d}".format(job_name, next_build_number))
response = requests.post(request_url, data=params, auth=auth)

response.raise_for_status()
print("Job triggered successfully")

while True:
    print("Querying Job current status...")
    try:
        build_data = requests.get(next_build_url, auth=auth).json()
    except ValueError:
        print("No data, build still in queue")
        print("Sleep for 20 sec")
        time.sleep(20)
        continue

    print("Building: {0}".format(build_data['building']))
    building = build_data['building']
    if building is False:
        break
    else:
        print("Sleep for 60 sec")
        time.sleep(60)

print("Job finished with status: {0:s}".format(build_data['result']))
Run Code Online (Sandbox Code Playgroud)

上面的脚本适用于 python 2.7 和 3.x。现在稍微解释一下:

一开始,我们想要确定未来构建的编号,以便稍后查询。触发构建后,将检查响应是否有错误。4XX 客户端错误或 5XX 服务器错误响应将引发异常:requests.exceptions.HTTPError。最后一步就是查询触发构建的状态(只要它尚未完成)。但请注意,触发的构建可能会在队列中等待一段时间,从而try: except:导致代码阻塞。当然,您可以time.sleep()根据您的需要进行调整。

输出示例:

$ python dummy.py 
Determining next build number
Triggering build: Dummy #55
Job triggered successfully
Querying Job current status...
No data, build still in queue
Sleep for 20 sec
Querying Job current status...
Building: True
Sleep for 60 sec
Querying Job current status...
Building: True
Sleep for 60 sec
Querying Job current status...
Building: False
Job finished with status: SUCCESS
Run Code Online (Sandbox Code Playgroud)

!请注意!

根据您的 Jenkins 版本和安全设置,您可能会遇到以下错误:

requests.exceptions.HTTPError: 403 Client Error: No valid crumb was included in the request for url: ...
Run Code Online (Sandbox Code Playgroud)

Jenkins 默认启用CSRF 保护,可防止一键攻击

要解决此问题,您可以:

  1. 在 Jenkins 配置全局安全性中禁用防止跨站点请求伪造漏洞复选框(不推荐)
  2. 使用您的凭据获取碎屑/crumbIssuer/api/xml并将其包含到您的请求标头中。

上面的脚本只需要进行少量修改即可使用 jenkins crumb:

crumb_data = requests.get(
    "{0:s}/crumbIssuer/api/json".format(jenkins_url),
    auth=auth,
).json()
headers = {'Jenkins-Crumb': crumb_data['crumb']}
Run Code Online (Sandbox Code Playgroud)

并将这些标头传递给触发新构建的请求,如下所示:

print("Triggering build: {0:s} #{1:d}".format(job_name, next_build_number))
response = requests.post(
    request_url,
    data=params,
    auth=auth,
    headers=headers,
)
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案!正是我想要的 (2认同)