繁体   English   中英

如何在Jenkins中处理github webhook有效负载?

[英]How to process a github webhook payload in Jenkins?

我目前正在通过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有效负载以使用某些行(例如提交者的用户名)作为构建中的条件?

有一些技巧可以使这个工作,我发现(现已解散) chloky.com博客文章对大多数有用。 既然听起来你已经让webhook至少与你的Jenkins实例进行了沟通,那么我现在就跳过这些步骤。 但是,如果你想要更多的细节,只需滚动我的答案的末尾,看看我能够从chloky.com打捞的内容 - 我不知道原作者和信息可能已经过时但我找到了它很有帮助。

总而言之,您可以执行以下操作来处理有效负载:

  1. 在Jenkins作业中设置一个名为“payload”的字符串参数。 如果您计划手动运行构建,那么在某些时候给它一个默认的JSON文档可能是个好主意,但您现在不需要它。 此参数名称似乎区分大小写(我正在使用Linux,因此毫不奇怪......)
  2. 在github中设置webhook以使用buildWithParameters端点而不是构建端点,即http://<<yourserver>>/job/<<yourjob>>/buildWithParameters?token=<<yourtoken>>

  3. 配置您的webhook使用application / x-www-form-encoded而不是application / json 前一种方法将JSON数据打包在一个名为“payload”的表单变量中,这可能是Jenkins如何将其分配给环境变量。 应用程序/ json方法只是POST原始JSON,它似乎不能映射到任何东西(我无法让它工作)。 您可以通过将webhook指向requestbin并检查结果来查看差异。

  4. 此时,您应该在启动构建时获取$ payload变量。 为了解析JSON,我强烈建议在Jenkins服务器上安装jq在这里尝试一些解析语法。 JQ特别好,因为它是跨平台的。
  5. 从这里,只需将您需要的内容从JSON解析为其他环境变量。 结合条件构建步骤,这可以为您提供很大的灵活性。

希望这可以帮助!


编辑这里是我可以从http://chloky.com/tag/jenkins/的原始博客文章中获取的,已经死了一段时间。 希望这些内容对某些人也有用。


发布#1 - 2012年7月

Github提供了一种很好的方法,可以在对存储库进行提交时向jenkins等CI系统发出通知。 这对于在jenkins中启动构建作业以测试刚刚在repo上进行的提交非常有用。 您只需要转到存储库的管理部分,单击左侧的服务挂钩,单击列表顶部的“webhook URL”,然后输入jenkins期待的webhook的URL(看看这个jenkins用于设置jenkins以从github接收这些钩子的插件 )。

为webhook配置jenkins

最近,我正在寻找一种方法来在针对回购提出拉取请求时发出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​​)拉取请求。 很甜蜜。

帖子#2 - 2012年9月

在之前的文章中,我谈到配置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 ,如下所示:

获得有效载荷

将参数传递给jenkins构建作业

在作业配置中,我们可以指定我们希望能够远程触发构建(即,我们希望允许github通过使用有效负载发布到我们的URL来触发构建):

传递参数

然后,当我们在我们的github仓库中设置webhook时(如第一篇文章中所述),我们给它jenkins告诉我们的URL:

在Github中配置URL

你无法在screencap中看到它,但我为webhook指定的URL是jenkins告诉我的:

http://jenkins-server.chloky.com:8080/job/mytestbuild//buildWithParameters?token=asecuretoken现在,当我在詹金斯建立我的新工作时,为了这个测试的目的,我只是告诉它回应内容'payload'参数(在paramterized构建中可用作同名的shell变量),使用一个简单的脚本:

#!/bin/bash

echo "the build worked! The payload is $payload"

现在要测试整个事情我们只需要提交我们的repo,然后弹出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中。 自动化很有趣!

有一个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/"
         }
      }
   }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM