jenkins - 如何重播使用通用 webhook HTTP POST 内容的 Jenkins 管道作业?
问题描述
我有一个由 Bitbucket 通用 webhook 触发的 Jenkins Pipeline 作业。即 Jenkins 有 Generic Webhook Trigger:
...和 Bitbucket 项目通过添加一个 webhook 来触发这个 Jenkins 项目http://my_jenkins_server:8080/generic-webhook-trigger/invoke?token=foo
我的 Jenkinsfile 使用 HTTP POST 内容——它是 JSON 格式——随调用 webhook 一起提供。例如,我的 Jenkinsfile 有这样的部分:
pipeline {
agent any
triggers {
GenericTrigger (
genericVariables: [
[ key: "POST_actor_name", value: "\$.actor.name" ],
[ key: "POST_actor_email", value: "\$.actor.emailAddress" ],
[ key: "POST_ref_id", value: "\$.changes[0].refId" ],
[ key: "POST_ref_display_id", value: "\$.changes[0].ref.displayId" ],
[ key: "POST_commit", value: "\$.changes[0].toHash" ],
[ key: "POST_repo_slug", value: "\$.repository.slug" ],
[ key: "POST_project_key", value: "\$.repository.project.key" ],
[ key: "POST_clone_url", value: "\$.repository.links.clone[1].href" ],
[ key: "POST_pull_req_clone_url", value: "\$.pullRequest.fromRef.repository.links.clone[1].href" ],
[ key: "POST_pull_req_id", value: "\$.pullRequest.id" ],
[ key: "POST_pull_req_from_branch", value: "\$.pullRequest.fromRef.displayId" ],
[ key: "POST_pull_req_to_branch", value: "\$.pullRequest.toRef.displayId" ],
[ key: "POST_pull_req_repo_slug", value: "\$.pullRequest.toRef.repository.slug" ],
[ key: "POST_pull_req", value: "\$.pullRequest.links.self[0].href" ],
[ key: "POST_pull_req_url", value: "\$.pullRequest.links.self[0].href" ],
],
causeString: '$committer_name pushed ref $ref to $clone_url referencing $commit',
token: "foo",
printContributedVariables: true,
printPostContent: true,
)
}
...
问题:有人如何重放现有的构建?
如果我单击Replay
现有构建的按钮:
...构建失败,我在构建日志中得到这个小片段:
[Pipeline] readJSON (hide)
[Pipeline] readJSON
[Pipeline] error
我相信这表明 readJSON 错误,因为重播的作业不是由真正的 HTTP POST 触发的,因此该部分(上面发布)没有 JSON 内容triggers.GenericTrigger.genericVariables
可以解析。这是对构建错误的正确评估吗?
我想触发读取 HTTP POST 内容的 Jenkins 管道作业的通用 webhook 很常见。我还认为重播过去 Jenkins 构建的需求很常见。因此,我想知道是否有一种习惯用法或通用方法来提供一种方法来重新触发过去依赖于来自触发通用 webhook 的 HTTP POST 内容的 Jenkins 管道作业。我在这里太缺乏经验了,不知道是否有某种机制可以缓存原始 HTTP POST 内容并将其重新发送到重播作业。或者有没有办法在不推动虚拟更改的情况下从 Bitbucket 重新触发管道?(Git 活动,例如将新提交推送到 Bitbucket 存储库会触发存储库的 webhook)。
解决方案
解决方案:使用支持参数
然后,以您的示例的最小版本为例,我相信您需要类似下面的内容。我没有测试过这个确切的例子,但希望你能明白。
主要思想是:使用与您创建的通用变量键完全相同的名称创建支持参数。事实上,如果您从作业的“配置”页面查看通用 webhook 触发器,您会看到一条关于使用参数支持通用 webhook 变量的注释:
如果你的工作没有参数化,那么解析的变量只会被贡献到构建中。如果您的作业是参数化的,并且您解析与这些参数同名的变量,那么插件将在触发作业时填充参数。这意味着您可以将参数与 SCM 插件(如 GIT 插件)结合使用来选择分支。
关键要点:参数name
s 必须与key
泛型变量的 s 完全匹配。
pipeline {
agent any
//This is I believe the main bit you were missing
parameters{
//Note: you can also use choice parameters instead of string here.
string(name: 'committer_name', description: 'ENTER A DESCRIPTION FOR YOUR PARAMETER HERE'),
string(name: 'ref', description: 'ENTER A DESCRIPTION FOR YOUR PARAMETER HERE'),
string(name: 'clone_url', description: 'ENTER A DESCRIPTION FOR YOUR PARAMETER HERE'),
string(name: 'commit', description: 'ENTER A DESCRIPTION FOR YOUR PARAMETER HERE')
}
triggers {
GenericTrigger (
genericVariables: [
//Using single quotes for values because AFAIK they should just be strings corresponding to JSON path in JSON payload of POST request
[ key: 'committer_name', value: '$.actor.name' ],
[ key: 'ref', value: '$.changes[0].refId' ],
[ key: 'clone_url', value: '$.repository.links.clone[1].href' ],
[key: 'commit', value: '$.changes[0].fromHash'] ]
],
//Using single quotes to avoid interpolating the parameters here. In practice, I've observed that this sets the cause string after the parameters are read from the POST data. If you try to interpolate with double quotes, you either get a premature/default parameter value, or worse, if the parameter is unknown to Jenkins yet because you're running from SCM and the parameter isn't loaded yet, you can get a vicious circle where the job fails before the parameter even loads, and you then have to add it manually to get it to work
causeString: '$committer_name pushed ref $ref to $clone_url referencing $commit',
token: "foo",
printContributedVariables: true,
printPostContent: true,
)
}
...
//You can use the parameters in the rest of your job, and they will also be captured in the build so that you can replay the build - which is what this Q. asks
我的建议:将工作分成触发器/主力
这不是一个直接的答案——只是我自己的建议。我发现将工作分为两部分是一种更简洁的方法:
- 比方说,一项工作是“主力”,它需要一个参数列表并做一些工作
- 另一项工作是“触发”工作——这个工作的职责只是接收通用 webhook 请求,对参数进行任何验证/清理,然后将主力作为下游工作触发。我为此使用了“管道:构建步骤”插件。
这里的一个优点是关注点分离 - 主力不必担心或被通用 webhook 东西弄得一团糟,通用 webhook 可以专注于处理 webhook。
另一个好处是,触发器作业至少可以处理 webhook 参数的一些验证、清理它们,并在没有主力作业细节的情况下为人们提供关于 webhook 发生了什么的一个很好的详细视图。
在实践中,因为我以这种方式做事,所以我很少会最终重播触发器作业——我通常只是重播主力作业,该作业将所有参数传递给它。话虽如此,即使使用我的触发作业,如果我愿意,我也可以重播它们,因为我使用参数备份所有内容 - 根据上面介绍的解决方案。
笔记
- 不确定为什么要
POST_
在原始问题中为通用变量添加前缀 - 如前所述,所使用的键应该与参数名称完全匹配。 - 如果您从 SCM 脚本运行它,那么在您第一次运行作业时,或者如果您添加任何新参数或修改任何参数名称,它将没有参数 - 这是带有参数 AFAIK 的标准 Jenkins 行为,您只需需要重新运行该作业-第二次它将具有参数并且可以工作。
- 这个问题有点离题,但我从捕获 Bitbucket 推送事件中注意到它似乎是
fromHash
填充的。对我来说,我观察到toHash
它总是只是一串零。但我只是在查看推送事件 - 也许您正在这里处理其他事件。
推荐阅读
- python-3.x - 为 Django 项目运行 pipenv 安装时出现错误“找不到 django-supervisor==0.4.0 的匹配分发”
- javascript - jQuery:如何将特定 DIV 下的 3 个“h3”元素的最大高度设置为所有 h3 元素?
- reactjs - 如何添加与基础具有相同前缀的所有(*)路由?
- javascript - 读取每个上传文件的缓冲区属性,当有多个时
- javascript - ejs 不会呈现 Html 页面
- php - 注册登录用户,但登录不 Laravel
- python - 解释特征重要性图中的 F 分数
- google-cloud-platform - `gsutlis ls` 无法显示存储桶列表
- reactjs - 使用 React 状态使用数组更新对象
- microsoft-graph-api - 每次创建 Teams 在线会议时是否必须更新访问令牌?- Microsoft Graph 团队