最近测试的一个系统模块较多,因此想每个模块的 Jenkins 成功构建之后,就自动把测试环境的改模块进行更新。各个模块的构建 Job 已经编写完了,由于我们的上线系统依赖于 Jenkins 的构建 Job,因此在能不修改各个模块的构建 Job 的前提下尽量不修改。
Jenkins 在构建触发器中提供了一种触发方式:指定一个或者多个上游 Job 构建后触发自身 Job 构建,在关注的项目添加希望触发的上游 Job 即可。
这里的问题在于,Job 编写的过程中往往希望可以获取一些上游 Job 的信息,以便做相应的流程处理,例如:根据上游的 Job 名字获取上游 Job 最新构建的产物,根据上游 Job 触发的参数做不同的动作。
但是目前 Jenkins 没有直接提供这个功能。该类需求通常的做法是,在上游 Job 中使用构建后操作添加Trigger parameterized build on other projects步骤来实现,此步骤可以配置相关的参数传递给下游 Job。
但是如前文所说,是否能在不修改上游 Job 的前提下完成我们的目标呢?
对于我们的目标 Job A,首先按照构建触发器中添加上游 Job 的思路完成配置,尝试触发上游 Job,成功构建后,可以看到 Job A 的控制台输出信息中有这样的输出:
日志中我们可以看到,上游触发 Job 的名字,build number 都包含在了输出中,甚至还包含了上游 Job 的触发人。
有了这些信息,剩下的事情就好办了,我们只需要根据日志输出使用正则批评获取相关信息即可。
下面 shell 为例展示获取上游 Job name 和 build number,里面 grep 的正则部分使用了零宽断言技巧,BUILD_URL 是 Jenkins 的环境变量,表示当前构建的 url。
log=$(curl -s ${BUILD_URL}consoleText | head -n 1)
p_job=$(echo $log | grep -oP '(?<=Started by upstream project ").*(?=")')
p_build_number=$(echo $log | grep -oP '(?<=build number ).*')
有同学会有疑惑,仅仅获取了上游 Job name 和 build number 有什么用呢?其实,到这一步,熟悉 Jenkins 的同学应该就想到了,利用 Jenkins 提供的 API,我们基本上可以获取上游 Job 的一切信息。
举几个例子:
获取上游 Job 的构建参数,我们根据 Jenkins 的 url 规则拼出 Json API 的接口地址,请求后解析 Json 抽取相关字段。
param=$(curl -s -X GET ${JENKINS_URL}/job/${p_job}/${p_build_number}/api/json | jq .actions[0].parameters[1].value)
其中 jq 是解析 json 的命令行工具。
获取上游 Job 的构建产物。
wget -q ${JENKINS_URL}/job/${p_job}/${p_build_number}/artifact/archive/deploy.tar.gz
获取上游 Job 的构建是否成功。
param=$(curl -s -X GET ${JENKINS_URL}/job/${p_job}/${p_build_number}/api/json | jq .result)
基于/api/json 这个接口,可以获取本次构建的大部分信息,而 config.xml 接口,可以获取 Job 本身的大部分配置信息。熟悉这两个接口,并灵活应用,基本上可以覆盖我们的绝大部分需求了。