我目前通过GitHub webhook触发我的Jenkins构建。我将如何解析JSON有效负载?如果我尝试参数化我的构建并使用$ payload变量,GitHub webhook将失败,并显示以下错误:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>Error 400 This page expects a form submission</title>
</head>
<body><h2>HTTP ERROR 400</h2>
<p>Problem accessing /job/Jumph-CycleTest/build. Reason:
<pre> This page expects a form submission</pre></p><hr /><i><small>Powered by Jetty://</small></i><br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
</body>
</html>
如何让我的GitHub webhook与参数化的Jenkins构建一起工作,然后如何解析webhook有效负载以使用某些行(例如提交者的用户名)作为构建中的条件?
答案 0 :(得分:42)
有一些技巧可以让它发挥作用,我发现(现已不存在的)chloky.com
博客文章对大部分内容都有帮助。既然听起来你至少已经与你的Jenkins实例进行了webhook通信,那么我现在就跳过这些步骤。但是,如果你想要更多的细节,只需滚动我的答案的末尾,看看我能够从chloky.com
打捞的内容 - 我不知道原作者和信息可能已经过时但我做了觉得有帮助。
总而言之,您可以执行以下操作来处理有效负载:
在github中设置webhook以使用 buildWithParameters 端点而不是 build 端点,即
http://<<yourserver>>/job/<<yourjob>>/buildWithParameters?token=<<yourtoken>>
将您的webhook配置为使用 application / x-www-form-encoded 而不是 application / json 。前一种方法将JSON数据打包在一个名为&#34; payload&#34;的表单变量中,这可能是Jenkins如何将其分配给环境变量。 application / json 方法只是POST原始JSON,它似乎不能映射到任何东西(我无法使它工作)。您可以通过将您的webhook指向类似requestbin的内容并检查结果来查看差异。
希望这有帮助!
编辑这里是我可以从http://chloky.com/tag/jenkins/
的原始博客文章中获取的内容,这篇博文已经死了一段时间。
希望这些内容对某人也有用。
Github提供了一种很好的方法,只要对存储库进行提交,就会向jenkins等CI系统发出通知。这对于在jenkins中启动构建作业以测试刚刚在repo上进行的提交非常有用。您只需要转到存储库的管理部分,单击左侧的服务挂钩,单击列表顶部的“webhook URL”,然后输入jenkins期望的webhook的URL(查看{{ 3}}用于设置jenkins从github接收这些钩子。
最近,我正在寻找一种方法来在针对回购提出拉取请求时发出webhook,而不是在对回购进行提交时。这样我们可以让jenkins在拉取请求上运行一堆测试,然后再决定是否合并拉取请求 - 当你有很多开发人员在他们自己的forks上工作并定期向主要提交拉取请求时很有用回购。
事实证明,这并不像人们希望的那样明显,并且需要对github API进行一些混乱。
默认情况下,当您配置github webhook时,它被配置为仅在针对repo进行提交时触发。在设置webhook时,没有简单的方法可以在github Web界面中查看或更改此内容。为了以任何方式操纵webhook,您需要使用API。
要通过github API对repo进行更改,我们需要授权自己。我们将使用curl,所以如果我们想每次都能传递我们的用户名和密码,就像这样:
# curl https://api.github.com/users/mancdaz --user 'mancdaz'
Enter host password for user 'mancdaz':
或者,这是一个更好的选择,如果你想编写任何这些东西的脚本,我们可以获取一个oauth令牌并在后续请求中使用它来节省必须继续输入我们的密码。这就是我们在示例中要做的事情。首先,我们需要创建一个oauth授权并获取令牌:
curl https://api.github.com/authorizations --user "mancdaz" \
--data '{"scopes":["repo"]}' -X POST
您将收到以下内容:
{
"app":{
"name":"GitHub API",
"url":"http://developer.github.com/v3/oauth/#oauth-authorizations-api"
},
"token":"b2067d190ab94698a592878075d59bb13e4f5e96",
"scopes":[
"repo"
],
"created_at":"2012-07-12T12:55:26Z",
"updated_at":"2012-07-12T12:55:26Z",
"note_url":null,
"note":null,
"id":498182,
"url":"https://api.github.com/authorizations/498182"
}
现在我们可以在后续的请求中使用此令牌来通过API操作我们的github帐户。因此,让我们查询我们的回购并找到我们之前在Web界面中设置的webhook:
# curl https://api.github.com/repos/mancdaz/mygithubrepo/hooks?access_token=b2067d190ab94698592878075d59bb13e4f5e96
[
{
"created_at": "2012-07-12T11:18:16Z",
"updated_at": "2012-07-12T11:18:16Z",
"events": [
"push"
],
"last_response": {
"status": "unused",
"message": null,
"code": null
},
"name": "web",
"config": {
"insecure_ssl": "1",
"content_type": "form",
"url": "http://jenkins-server.chloky.com/post-hook"
},
"id": 341673,
"active": true,
"url": "https://api.github.com/repos/mancdaz/mygithubrepo/hooks/341673"
}
]
注意json输出中的重要位:
"events": [
"push"
]
这基本上说这个webhook只会在对repo进行提交(推送)时触发。 github API文档描述了可以添加到此列表中的众多不同事件类型 - 为了我们的目的,我们想要添加pull_request,这就是我们的工作方式(注意我们从上面的json输出中获取webhook的id。如果你定义了多个钩子,你的输出将包含所有这些钩子,所以一定要得到正确的ID):
# curl https://api.github.com/repos/mancdaz/mygithubrepo/hooks/341673?access_token=b2067d190ab94698592878075d59bb13e4f5e96 -X PATCH --data '{"events": ["push", "pull_request"]}'
{
"created_at": "2012-07-12T11:18:16Z",
"updated_at": "2012-07-12T16:03:21Z",
"last_response": {
"status": "unused",
"message": null,
"code": null
},
"events": [
"push",
"pull_request"
],
"name": "web",
"config": {
"insecure_ssl": "1",
"content_type": "form",
"url": "http://jenkins-server.chloky.com/post-hook"
},
"id": 341673,
"active": true,
"url": "https://api.github.com/repos/mancdaz/mygithubrepo/hooks/341673"
}
请参阅!
"events": [
"push",
"pull_request"
],
只要对我们的回购提交或提出拉取请求,此webhook就会触发。你在jenkins /这个webhook中所做的正是取决于你。我们使用它来启动jenkins中的一系列集成测试来测试建议的补丁,然后实际上合并并关闭(再次使用API)拉取请求。很甜蜜。
在之前的帖子中,我谈到配置github webhook来触发pull请求,而不仅仅是提交。如上所述,github repo上发生了许多事件,并且根据github文档,其中很多都可以用来触发webhook。
无论你决定触发什么事件,当webhook从github触发时,它基本上对webhook中配置的URL进行POST,包括正文中的json有效负载。 json有效负载包含有关导致webhook触发的事件的各种详细信息。可以在此处看到在简单提交上触发的示例有效负载:
payload
{
"after":"c04a2b2af96a5331bbee0f11fe12965902f5f571",
"before":"78d414a69db29cdd790659924eb9b27baac67f60",
"commits":[
{
"added":[
"afile"
],
"author":{
"email":"myemailaddress@mydomain.com",
"name":"Darren Birkett",
"username":"mancdaz"
},
"committer":{
"email":"myemailaddress@mydomain.com",
"name":"Darren Birkett",
"username":"mancdaz"
},
"distinct":true,
"id":"c04a2b2af96a5331bbee0f11fe12965902f5f571",
"message":"adding afile",
"modified":[
],
"removed":[
],
"timestamp":"2012-09-03T02:35:59-07:00",
"url":"https://github.com/mancdaz/mygithubrepo/commit/c04a2b2af96a5331bbee0f11fe12965902f5f571"
}
],
"compare":"https://github.com/mancdaz/mygithubrepo/compare/78d414a69db2...c04a2b2af96a",
"created":false,
"deleted":false,
"forced":false,
"head_commit":{
"added":[
"afile"
],
"author":{
"email":"myemailaddress@mydomain.com",
"name":"Darren Birkett",
"username":"mancdaz"
},
"committer":{
"email":"myemailaddress@mydomain.com",
"name":"Darren Birkett",
"username":"mancdaz"
},
"distinct":true,
"id":"c04a2b2af96a5331bbee0f11fe12965902f5f571",
"message":"adding afile",
"modified":[
],
"removed":[
],
"timestamp":"2012-09-03T02:35:59-07:00",
"url":"https://github.com/mancdaz/mygithubrepo/commit/c04a2b2af96a5331bbee0f11fe12965902f5f571"
},
"pusher":{
"email":"myemailaddress@mydomain.com",
"name":"mancdaz"
},
"ref":"refs/heads/master",
"repository":{
"created_at":"2012-07-12T04:17:51-07:00",
"description":"",
"fork":false,
"forks":1,
"has_downloads":true,
"has_issues":true,
"has_wiki":true,
"name":"mygithubrepo",
"open_issues":0,
"owner":{
"email":"myemailaddress@mydomain.com",
"name":"mancdaz"
},
"private":false,
"pushed_at":"2012-09-03T02:36:06-07:00",
"size":124,
"stargazers":1,
"url":"https://github.com/mancdaz/mygithubrepo",
"watchers":1
}
}
这整个有效负载作为单个参数在POST请求中传递,具有富有想象力的标题payload
。它包含大量有关刚刚发生的事件的信息,当我们在触发后构建作业时,jenkins可以使用其中的全部或任何一个。为了在Jenkins中使用这个有效载荷,我们有几个选择。我在下面讨论一个。
在jenkins中,在创建新的构建作业时,我们可以选择指定我们希望传递给POST中触发构建的作业的参数名称。在这种情况下,我们将传递一个参数payload
,如下所示:
在作业配置中,我们可以指定我们希望能够远程触发构建(即,我们希望允许github通过使用有效负载发布到我们的URL来触发构建):
然后,当我们在我们的github仓库中设置webhook时(如第一篇文章中所述),我们给它jenkins告诉我们的URL:
你无法在screencap中看到它,但是我为webhook指定的URL是jenkins告诉我的那个:
http://jenkins-server.chloky.com:8080/job/mytestbuild//buildWithParameters?token=asecuretoken
现在,当我在jenkins中构建我的新工作时,为了这个测试的目的,我只是告诉它回应'payload'参数的内容(在paramterized构建中可用作同名的shell变量),使用一个简单的脚本:
#!/bin/bash
echo "the build worked! The payload is $payload"
现在要测试整个事情,我们只需要提交我们的回购,然后转到jenkins查看被触发的工作:
mancdaz@chloky$ (git::master)$ touch myfile
mancdaz@chloky$ (git::master) git add myfile
mancdaz@chloky$ (git::master) git commit -m 'added my file'
[master 4810490] added my file
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 myfile
mancdaz@chloky$ (git::master) git push
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 232 bytes, done.
Total 2 (delta 1), reused 0 (delta 0)
To git@github.com:mancdaz/mygithubrepo.git
c7ecafa..4810490 master -> master
在我们的jenkins服务器中,我们可以查看触发的作业的控制台输出,并且看到$ payload变量中包含我们的'payload'并且可以供我们使用:
太棒了,关于我们github活动的所有信息都在这里。并在我们的詹金斯工作中完全可用!真的,它是一个大json blob,但有一点狡猾的bash你应该很高兴去。
当然,这个例子使用了一个简单的提交来演示获取jenkins内部有效负载的原则。正如我们在前面的文章中所讨论的,提交是可以触发webhook的repo上的许多事件之一。一旦你触发了你在jenkins中所做的事情取决于你,但真正有趣的是当你开始与github交互以对repo采取进一步行动(发表评论,合并拉取请求,拒绝提交等)时,基于结果您的构建作业由初始事件触发。
请注意后续帖子,我将它们绑在一起并向您展示如何处理,运行测试,并在成功时合并拉取请求 - 所有这些都自动在jenkins中。自动化很有趣!
答案 1 :(得分:5)
有一个Generic Webhook Trigger插件可以提供从帖子内容到构建的值。
如果帖子内容是:
{
"app":{
"name":"GitHub API",
"url":"http://developer.github.com/v3/oauth/#oauth-authorizations-api"
}
}
当触发一些帖子内容时:
curl -v -H "Content-Type: application/json" -X POST -d '{ "app":{ "name":"GitHub API", "url":"http://developer.github.com/v3/oauth/" }}' http://localhost:8080/jenkins/generic-webhook-trigger/invoke?token=sometoken
它将解析变量并使它们在构建作业中可用。
{
"status":"ok",
"data":{
"triggerResults":{
"free":{
"id":2,
"regexpFilterExpression":"",
"regexpFilterText":"",
"resolvedVariables":{
"app_name":"GitHub API",
"everything_app_url":"http://developer.github.com/v3/oauth/",
"everything":"{\"app\":{\"name\":\"GitHub API\",\"url\":\"http://developer.github.com/v3/oauth/\"}}",
"everything_app_name":"GitHub API"
},
"searchName":"",
"searchUrl":"",
"triggered":true,
"url":"queue/item/2/"
}
}
}
}