web-dev-qa-db-ja.com

Jenkinsでgithub webhookペイロードを処理する方法は?

現在、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ペイロードを解析してビルドの条件としてコミッターのユーザー名などの特定の行を使用するにはどうすればよいですか?

14
Grant

これを機能させるにはいくつかのコツがありますが、ほとんどの場合、(現在は機能していません)chloky.comブログ投稿が役立つことがわかりました。少なくともJenkinsインスタンスと通信するwebhookを取得したように聞こえるので、ここではそれらの手順をスキップします。しかし、さらに詳細が必要な場合は、答えの最後までスクロールして、chloky.comから回収できたコンテンツを確認してください-元の著者がわからず、情報が古い可能性がありますが、役に立ちました。

要約すると、ペイロードを処理するために次のことができます。

  1. Jenkinsジョブで「ペイロード」という文字列パラメーターを設定します。ビルドを手動で実行することを計画している場合、ある時点でデフォルトのJSONドキュメントを提供することをお勧めしますが、今は必要ありません。このパラメーター名では大文字と小文字が区別されるようです(Linuxを使用しているので、驚くことではありません...)
  2. buildエンドポイントの代わりにbuildWithParametersエンドポイント、つまりhttp://<<yourserver>>/job/<<yourjob>>/buildWithParameters?token=<<yourtoken>>を使用するように、githubでwebhookをセットアップします

  3. application/jsonの代わりにapplication/x-www-form-encodedを使用するようにWebhookを設定します。前者のアプローチでは、JSONデータを「payload」と呼ばれるフォーム変数にパックします。これは、おそらくJenkinsがそれを環境変数に割り当てる方法です。 application/jsonアプローチは、何にもマッピングできないように見える生のJSONをPOSTするだけです(動作させることができませんでした)。 Webhookを requestbin のように指定し、結果を調べることで違いを確認できます。

  4. この時点で、ビルドを開始するときに$ payload変数を取得する必要があります。 JSONを解析するには、Jenkinsサーバーに jq をインストールし、解析構文 here を試してみることを強くお勧めします。 JQはクロスプラットフォームであるため特に優れています。
  5. ここから、JSONから必要なものを他の環境変数に解析するだけです。条件付きビルドステップと組み合わせると、これにより柔軟性が大幅に向上します。

お役に立てれば!


[〜#〜] edit [〜#〜]ここに、http://chloky.com/tag/jenkins/の元のブログ投稿から入手できるものがあります。しばらくの間。このコンテンツが誰かにも役立つことを願っています。


投稿#1-2012年7月

Githubは、リポジトリに対してコミットが行われるたびにjenkinsなどのCIシステムへの通知を起動する素晴らしい方法を提供します。これは、ジェンキンスでビルドジョブを開始して、レポジトリで行われたコミットをテストするのに非常に便利です。リポジトリの管理セクションに移動し、左側のサービスフックをクリックし、リストの上部にある「webhook URL」をクリックしてから、jenkinsが期待しているwebhookのURLを入力するだけです(見てください- このjenkinsプラグイン githubからこれらのフックを受け取るようにjenkinsをセットアップするため)。

Configure jenkins for webhook

しかし最近、私はリポジトリにコミットが行われたときではなく、リポジトリに対してプルリクエストが行われたときにwebhookを起動する方法を探していました。これは、プルリクエストをマージするかどうかを決定する前に、ジェンキンにプルリクエストのテストを実行させるためです。多くの開発者が自分のフォークで作業し、メインにプルリクエストを定期的に送信する場合に役立ちますレポ。

これは期待するほど明白ではなく、github APIを少しいじる必要があることがわかります。

デフォルトでは、github webhookを設定すると、リポジトリに対してコミットが行われたときにのみ起動するように設定されます。 webhookをセットアップするときに、github Webインターフェースでこれを確認または変更する簡単な方法はありません。 Webhookを何らかの方法で操作するには、APIを使用する必要があります。

Github APIを使用してレポに変更を加えるには、自分自身を認証する必要があります。 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アカウントを操作するための後続のリクエストでこのトークンを使用できます。それでは、レポジトリをクエリして、以前にウェブインターフェースで設定したウェブフックを見つけましょう。

# 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はレポジトリにコミット(プッシュ)が行われたときにのみトリガーされると言っています。 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は、コミットORリポジトリに対してプルリクエストが行われるたびにトリガーされます。ジェンキンスで行うこと/このwebhookで行うことはあなた次第です。キックオフに使用します。 jenkinsでの多数の統合テストにより、提案されたパッチをテストし、プルリクエストを(APIを使用して)自動的にマージして閉じます。

投稿#2-2012年9月

以前の投稿で、単なるコミットではなく、プルリクエストで起動するようにgithub webhookを構成することについて話しました。前述のように、GitHubリポジトリで発生するイベントは多数あり、GitHubのドキュメントによると、これらの多くはWebhookをトリガーするために使用できます。

トリガーすることを決定するイベントに関係なく、webhookがgithubから起動されると、本質的に、本体のjsonペイロードを含むwebhookで設定されたURLに対してPOSTを作成します。jsonペイロードwebhookを起動したイベントに関するさまざまな詳細が含まれています。単純なコミットで起動したペイロードの例は次のとおりです。

payload
{
   "after":"c04a2b2af96a5331bbee0f11fe12965902f5f571",
   "before":"78d414a69db29cdd790659924eb9b27baac67f60",
   "commits":[
      {
         "added":[
            "afile"
         ],
         "author":{
            "email":"[email protected]",
            "name":"Darren Birkett",
            "username":"mancdaz"
         },
         "committer":{
            "email":"[email protected]",
            "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":"[email protected]",
         "name":"Darren Birkett",
         "username":"mancdaz"
      },
      "committer":{
         "email":"[email protected]",
         "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":"[email protected]",
      "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":"[email protected]",
         "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でこのペイロードを使用するために、いくつかのオプションがあります。以下で説明します。

$ payloadを取得する

Jenkinsでは、新しいビルドジョブを作成するときに、ビルドをトリガーするPOSTでジョブに渡すことが期待されるパラメーターの名前を指定するオプションがあります。この場合、以下に示すように、単一のパラメーターpayloadを渡します。

Getting the payload

Jenkinsビルドジョブにパラメーターを渡す

ジョブ設定のさらに下で、リモートでビルドをトリガーできるように指定することができます(つまり、ペイロードを使用してURLに投稿することでgithubにビルドをトリガーさせたい)。

Passing parameters

次に、最初の投稿で説明したように、githubリポジトリでwebhookを設定するときに、jenkinsが次のように指示するURLを提供します。

Configuring URL in Github

すべてをスクリーンキャップで見ることはできませんが、webhookに指定したURLはジェンキンスが私に言ったものでした:

http://jenkins-server.chloky.com:8080/job/mytestbuild//buildWithParameters?token=asecuretoken今、私はジェンキンスで新しいジョブを作成したとき、このテストの目的のために、 'payload'パラメーター(パラメーター化ビルドでシェル変数として使用可能なパラメーター同じ名前)、シンプルなスクリプトを使用:

#!/bin/bash

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

すべてをテストするには、レポジトリにコミットし、ジェンキンスにポップしてトリガーされたジョブを確認するだけです。

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 [email protected]:mancdaz/mygithubrepo.git
 c7ecafa..4810490 master -> master

Jenkinsサーバーでは、トリガーされたジョブのコンソール出力を見ることができます。見れば、「payload」が$ payload変数に含まれており、消費できるようになっています。

Githubイベントに関するすべての情報はここにあります。ジェンキンスの仕事で完全に利用可能です!確かに、それは大きなjson blobにありますが、少し巧妙なbashを使用すれば、うまくいくはずです。

もちろん、この例では、単純なコミットを使用して、ジェンキン内部のペイロードを取得する原理を示しました。前の投稿で説明したように、コミットは、Webhookをトリガーできるレポ上の多くのイベントの1つです。トリガーした後のジェンキンスの内部で行うことはあなた次第ですが、実際の楽しみはgithubとのやり取りを開始して、レポでさらにアクションを実行することです(コメントの投稿、プルリクエストのマージ、コミットの拒否など)最初のイベントによってトリガーされたビルドジョブ。

それをすべて結び付けて、成功した場合はプルリクエストを処理し、テストを実行し、最後にプルリクエストをマージする方法を示します。これらはすべて自動的にジェンキン内で行われます。自動化は楽しいです!

44
killthrush

投稿コンテンツからビルドに値を提供できる Generic Webhook Trigger プラグインがあります。

投稿内容が次の場合:

{
   "app":{
      "name":"GitHub API",
      "url":"http://developer.github.com/v3/oauth/#oauth-authorizations-api"
   }
}

次のように設定できます: enter image description here

そして、いくつかの投稿コンテンツでトリガーする場合:

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/"
         }
      }
   }
}
5
Tomas Bjerre