持续集成 Jenkins REST API 多任务依赖实际场景应用案例

小背影 · 2019年01月21日 · 最后由 小背影 回复于 2019年04月04日 · 2199 次阅读

本文涉及:Jenkins 插件及使用、不同 job 间参数传递、Jenkins REST API、Shell 脚本

背景说明:

线上 API 可用性监控我们使用的是Postman+Newman+Jenkins+Git来实现和维护的。
有时会遇到一个问题:Newman 在 Jenkins 上执行时,有些异常情况会导致环境变量 Environment 文件(下一次脚本执行的数据来源)为空,导致后续数据加载出错,API 任务构建失败。

如上图所示流程中的红叉叉❌那里

出现上述异常后,有没有解决方案?

有,手动构建另一个 Jenkins Job,把备份的环境变量 cp 到指定目录下即可。
。。。要通过。。。手。。。工。。。发现,太 low 了,风险高,效率低,鬼知道什么时候会出现这个情况,如果我在睡觉,我可不愿意还要爬起来手动执行几行命令。

So,怎么办呢?(好想睡个好觉)

Jenkins 控制台输出打印了对应的错误日志error: Unexpected end of JSON input...
HA,解决方案有了:如果出现上述失败,通过检测控制台输出中的特殊字符串,然后执行环境变量 Environment 文件 cp 命令即可。

解决方案:

在脚本中,通过对 Jenkins 控制台的输出内容进行解析判断,再进行后续操作,比如是否执行后续命令或构建 Job 等。

解决过程

问题 1:

如何获取 Jenkins 控制台输出的内容?

curl -X GET http://Jenkins_URL:port/job/Job_Name/Build_ID/consoleText
上述链接最后加的 consoleText ,是为了获取控制台输出。

问题 2:

如果直接执行上面命令,会提示未登录错误。所以要先登陆到 Jenkins。

在 Jenkins 请求链接前加 user:password@ 即可直接登录 Jenkins。
如下:
curl -X GET http://user:password@Jenkins_URL:port/job/Job_Name/Build_ID/consoleText

问题 3:

如何获取其它 job 最新构建的任务编号?

Job_Name 后面添加 /lastBuild/buildNumber 即可。
curl -X GET http://user:password@Jenkins_URL:port/job/Job_Name/lastBuild/buildNumber

问题 4:

Jenkins 中如何在不同的 job 间传递参数?

首先 Jenkins 下载安装 Parameterized Trigger Plugin插件。

项目 A 设置:

增加构建后操作步骤 中选择 Trigger parameterized build on other projects
如下图:

自定义参数可以选择 Add Parameters -> Predefined parameters,按照 <key>:<value> 方式输入即可,支持多个参数。
如下图:

项目 B 设置:

一定首先选择 参数化构建过程 ,字段名称同项目 A;直接 $key 即可使用。
如下图:

实际应用:

#!/bin/bash

GIT_WORKSPACE_PATH="/var/lib/jenkins/workspace/Git_Script_Update/"
NEWMAN_WORKSPACE_PATH="/home/ubuntu1604/xxx/newman/scripts/"

JOB_NAME=$FAILED_JOB_NAME
BUILD_ID=$FAILED_JOB_ID

#BUILD_ID=$(curl -X GET http://user:password@Jenkins_URL:port/job/$JOB_NAME/lastBuild/buildNumber|awk -F'[%]' '{print $1}')

STR_ERROR=$(curl -X GET http://user:password@Jenkins_URL:port/job/$JOB_NAME/$BUILD_ID/consoleText|grep error|awk '{print $1,$2,$3,$4,$5,$6}')

if [ "$STR_ERROR"x = "error: Unexpected end of JSON input"x ]
then
    cp -r ${GIT_WORKSPACE_PATH}* ${NEWMAN_WORKSPACE_PATH}
    echo "Update scripts Success!"
else 
    echo "Environment is OK. Nothing need to Do."
fi

说明 1:

bash 中赋值等号前面要加 $ ,如下:
STR_ERROR=$(curl -X GET http://user:password@Jenkins_URL:port/job/$JOB_NAME/$BUILD_ID/consoleText|grep error|awk '{print $1,$2,$3,$4,$5,$6}')

说明 2:

if 判断时

  • 如果是数字比对,用 ==!=
  • 如果是字符串比对,用单引号 =,且等号两边各有一个空格

字符串比对,中括号两边各留一个空格,且字符串后面要加个字符 x
比对格式:[ “string1”x = “string2”x ],引用的字符也要加双引号
if [ "$STR_ERROR"x = "error: Unexpected end of JSON input"x ]

说明 3:

BUILD_ID 也可以通过 Jenkins url 获取,但最后会多一个%,如下图所示

awk 把纯数字的 buildNumber 过滤出来,去掉最后的百分号,如下命令
BUILD_ID=$(curl -X GET http://user:password@Jenkins_URL:port/job/$JOB_NAME/lastBuild/buildNumber|awk -F'[%]' '{print $1}')

方案不足:

项目 A 构建只要失败(不一定是环境变量为空导致),就会触发项目 B,因判断条件在项目 B shell 脚本中,导致了一些不必要的构建。

方案优化点:

项目 A 构建后续步骤中,增加本次构建的输出解析,若有关键字符串,再触发项目 B,否则什么也不做,这样就可以做到没有冗余的构建。

总结:

上述就是问题解决过程和遇到的问题,可以安心睡觉了。
仅供参考,共同学习。
参考链接

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 2 条回复 时间 点赞

文章不错,这个节点外面的人看不了,你可以重新发到外面去

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册