Jenkins REST API如何获取指定Job的构建状态

文章导读
遇到“获取指定Job的构建状态”这类需求,我通常会先确认两件事:这个Job在Jenkins里的实际URL路径是什么,以及“构建状态”是要轮询最新一次构建,还是按构建号查某一个历史记录。这两点没对齐,后面写多少代码都可能跑偏。
📋 目录
  1. 先确认路径与构建号
  2. 认证方式决定你能否读到数据
  3. 解析响应:先看building再看result
  4. 容易误判的边界情况
  5. 性能与维护建议
A A

遇到“获取指定Job的构建状态”这类需求,我通常会先确认两件事:这个Job在Jenkins里的实际URL路径是什么,以及“构建状态”是要轮询最新一次构建,还是按构建号查某一个历史记录。这两点没对齐,后面写多少代码都可能跑偏。

先确认路径与构建号

要获取指定Job的构建状态,最直接的方式是调用`/job/{jobName}/lastBuild/api/json`或`/job/{jobName}/{buildNumber}/api/json`。前者返回最后一次构建的信息,后者需要明确指定构建号。如果不知道构建号,可以先用`/job/{jobName}/api/json`获取`builds`数组中的`number`字段,再构造具体构建的查询URL。注意Job名称中如果包含空格或中文,必须进行URL编码,例如空格用`%20`替换。在Shell中使用`curl`时,建议加`--globoff`参数避免花括号解析干扰。

这里需要补充的是,`lastBuild` 在Job从未构建过时会返回404,所以如果你写的是自动化脚本,建议先从`/job/{jobName}/api/json`的`builds`数组判断是否为空,再去请求具体构建号。另外,URL编码不只影响命令行,在编程语言的HTTP客户端里同样要做,比如Python的`urllib.parse.quote`。

认证方式决定你能否读到数据

Jenkins REST API通常需要认证,推荐使用API Token代替用户密码。在Jenkins用户设置页面生成Token后,配合用户名作为Basic Auth的凭据。例如`curl -u username:api_token -s http://jenkins/job/myjob/lastBuild/api/json`。不要直接在命令行中明文输入密码,因为Token可以被吊销且只对读取操作有效。如果遇到403响应,先检查认证信息是否正确,再确认Jenkins是否启用了CSRF保护;对于GET请求一般不受影响,但若仍被拒绝,需要从`/crumbIssuer/api/json`获取Crumb并加入请求头。

我通常会在调用前先验证Token是否有效:不带参数请求一次,再带上Token请求一次,如果后者返回200而前者是401,说明Token有效。另外,这个Token是绑定到具体用户的,如果你在脚本里用了一个没有读取权限的用户,即使Token正确也可能看到的是空白列表。建议为这类脚本单独建一个只读用户,权限控制在`read`级别。

解析响应:先看building再看result

解析返回的JSON时,重点关注`building`和`result`字段。当`building`为`true`时,构建正在进行中,此时`result`为`null`或缺失,任何依赖结果的处理都需要等待。只有当`building`为`false`时,`result`才包含有效状态值,可能为`SUCCESS`、`FAILURE`、`UNSTABLE`、`ABORTED`或`NOT_BUILT`。在实际代码中,应先判断`building`,再读取`result`,避免对空值执行状态比较导致意外异常。

比如在Python里可以这样处理:

Jenkins REST API如何获取指定Job的构建状态
data = requests.get(url, auth=(user, token)).json()
if data.get('building'):
    status = 'BUILDING'
else:
    status = data.get('result')

注意`result`可能为`null`,所以不要直接和字符串比较。对于Pipeline构建,刚结束的一两秒内`result`可能还没有落盘,我会在`building`为`false`且`result`为空时,间隔1秒重试一次,最多3次。

容易误判的边界情况

除了上面这些,还有几个容易让脚本“看起来没问题实际结果不对”的地方。如果Job在文件夹里,API路径需要完整写出每一层,比如`/job/父Job/job/子Job/lastBuild/api/json`,但有时文件夹名或子Job名里含有空格,同样要URL编码。另外,当Job被重命名后,旧URL会失效,API可能返回403或301,脚本里最好跟随重定向,或者把Job路径维护在配置文件里,避免硬编码。

另一个常见问题是构建历史被清理。Jenkins默认按天数和数量保留构建日志,超过保留策略后,按构建号查询会得到404。如果查询历史构建是为了做展示或回填,最好在代码中捕获404,提示“构建已被清理”,同时可以兜底用`lastBuild`,但这时必须说明数据不是历史值。我在这类脚本里通常会加一个开关:如果指定构建号查不到,是返回空还是自动取最近一次。

性能与维护建议

性能上需要留意,如果外围程序每秒钟轮询一次Jenkins,即使单次请求不大,也会占用不必要的连接和线程。Jenkins API支持`tree`参数,可以只取需要的字段,比如`?tree=builds[number,status]`,这对历史记录多的Job尤为重要。另外,不要开`pretty=true`,那个格式化对阅读友好,但对程序解析没有好处。更合理的设计是让Jenkins在构建完成时通过Webhook主动通知,而不是让外部服务一直轮询。

如果让我梳理一个稳妥的处理顺序,我会这样走:先不带认证请求一次API,确认网络通不通;再加上Token请求,确认认证没问题;返回的JSON里先看`building`,再看`result`,如果异常就重试几次;最后把Job路径相关参数都抽成配置,避免URL编码和重命名带来的维护成本。整个排查过程不需要改Jenkins配置,只改调用端脚本,风险很小。