【GitHub Enterprise】Git Hub Enterpriseのwebhookが有効にならない【AWS CodeBuild】

##【事象】
AWSのサービスを利用し、デプロイメントパイプラインを作ろうとしていた際、Git Hub Enterprise(以後、GHE)とAWS CodeBuildのwebhook連携ができなくて辛かった。

##【解決】
GHEのwebhookの設定で、「Content-Type」を、[application/json]にすることで、webhook連携が有効になった。

**ヾ(ΦωΦ)/**

![01.変えた.jpg](https://qiita-image-store.s3.amazonaws.com/0/168731/f8466682-9e04-02f1-7afa-b36bba7423f6.jpeg)


##【詳細】
Git Hub/Labを使っていると、ビルド以外にもチケットと連携させたりで、
webhook/service hookを多用することになると思います。
今回、AWSのデプロイメントパイプラインを作成していましたが、
ビルド → デプロイのうち、ビルドの部分で躓きました。


GHEのmasterブランチにソースがpush → `pushを検知してwebhook連携`　→ AWS CodeBuildがビルドをする。
ここのwebhookがそもそもsucessしない!!GHEのコンソールで叱られる!!

##### GHEがおこな時のメッセージ

```
Invalid HTTP Response: 400
```

##GHEとAWS CodeBuildによるビルド自動化の流れ
AWS CodeBuildのビルドの流れとしては、下記のような感じになります。

1.ビルド対象のソースコードがGHEのとmasterブランチにpushされる
2.pushを検知し、GHEがwebhookを飛ばしてAWSCodeBuildに知らせる
3.AWS CodeBuildが、ビルド仕様ファイル(build spec.yml)を元にビルドを実行
4.ビルドで生成されたjarなりzipなりをS3バケットに放り込む

AWS CodeBuildは、ビルド仕様ファイル(build spec.yml)の書き方次第で
色々いじれるみたいですね。今度また学んだらQiita書きます。
どうやら、ビルドテストを、自前のコンテナ内で動作させたりとかもできる模様...。

さてさて、AWS CodeBuildのビルドの流れを大きく4つに分けました。僕はこの中で、
`2.pushを検知し、GHEがwebhookを飛ばしてAWSCodeBuildに知らせる`
で上手くいきませんでした。

###webhook連携失敗の詳細
今回はほぼGHEの話になります。
今一度AWS CodeBuild - GHE間のwebhook設定の流れをさらっと見てみましょう。
1.AWS CodeBuildでビルドプロジェクトを作成し、webhookのPOST先となる
  「Payload URL」と、AWSへアクセスする「Secretキー」を受け取る。
2.GHEプロジェクトの[Settings]-[Webhooks]から色々設定します。
　**設定内容**

| 項目       |       値 |
|:-----------------:|:------------------:|
| Payload URL              |              AWSから受けったペイロードURL  |
|  Content type |  Content-Typeヘッダー  |
|  Secret |  シークレットキー |
|  Which events |  トリガーイベント |


3.設定を反映
[Add webhook]で反映すると、GHEのコンソール画面にて疎通確認ができます。
![webhooks_recent_deliveries (1).png](https://qiita-image-store.s3.amazonaws.com/0/168731/b80af88a-b35b-af11-30c8-62d6b7634538.png)

Creating Webhooks
https://developer.github.com/webhooks/creating/
Testing Webhooks
https://developer.github.com/webhooks/testing/


**↑**設定がおかしいと、ここで<font color="Red">真っ赤っか</font>になって叱られます。
僕は、ここで<font color="Red">failed (red x)</font> になってしまいました。
Content typeを `application/x-www-form-urlencoded` から
 `application/json` へ変更することで無事SUCCESSしました。
payloadといえば、json payloadだと誰もがわかるそうなのですが、
僕は知識足りず、普通に調べるまでわかりませんでした...。
オンプレの古いところだと、jsonのapiダメだったりするしなぁ〜。

##さてさて
僕が今回失敗していたのは、Coontent-Typeヘッダーの設定でした。
では何故、 `application/json` だとうまくいって、
`x-www-form-urlencoded` では失敗したのか。

###そもそも
今回疎通ができていなかったwebhookは、 イベントが発生したのをきっかけにして、
HTTP通信でターゲットにデータを通知する仕組みのことを言います。

何かしらイベントが発生にあたるイベントは、「masterブランチへのpush」でしたね。
そして、「HTTP通信でターゲットにデータを通知」 これが、今回問題となった
`Coontent-Typeヘッダー` の設定に関係があります。


![IMG_1750.JPG](https://qiita-image-store.s3.amazonaws.com/0/168731/09096ece-d998-7c02-5a21-d3df7c756a6a.jpeg)
ターゲットとなるのは、PayloadURLで、データはPayloadURLへ `JSON形式でPOST`されていました。
(この画力でマスターヨーダを見抜いた人も居ました...。)


##webhookが使うHTTP通信のやりとり
masterブランチへのpushというイベントを受け取ったGHEは、
webhookを動かしHTTP通信でデータを送ります。
この際、送られるデータの中身は下記のような感じになっています。

○HTTPリクエストの中身
　・リクエストライン
　・HTTPヘッダー
　・メッセージボディ

それでは一つずつちょろっと見てみましょう〜。
**リクエストライン**は、「HTTP通信で何をどうしたいか。」を記述します。
　例えばデータを投入(POST)したいのか参照(GET)したいのかとかにあたりますね。
　今回の場合、データは、「PayloadURL(CodeBuildのビルドプロジェクト)へ向けて
 `JSON形式でPOST(投入)` 」されていました。

**HTTPヘッダー**、今回はここで躓きましたね。
　HTTPヘッダーは、読み込むリソースや、リクエスト送信者の情報のことを言います。
　Cookie持つ持たない、どこのプロキシを通った通ってないとかも書かれています。
　`Content-Typeヘッダー` というのは、データの形式を指定する記載でした。
　ターゲットのAWS CodeBuildは、 `json形式` でデータを欲しがっていました。
　そのため、webhookを定義する際、
　GHEのコンソールで `application/json` を選択せねばなりませんでした。

>どうやらAWSのwebhookでは、デフォルトではJson形式で情報を受け取る模様です。
AWSの公式にも載ってました〜！
CreateWebhook
Request Parameters
https://docs.aws.amazon.com/ja_jp/codebuild/latest/APIReference/API_CreateWebhook.html
The request accepts the following data in JSON format.


**メッセージボディ**
　実際のデータ内容


今回の場合は、データ形式が間違っていたんだということがわかりました〜。


##application/json と x-www-form-urlencoded 
今回の事象の原因となるHTTPヘッダーについても触りが理解できましたが、
`application/json` と `x-www-form-urlencoded` 
　二つの違い知りたくないですか？

###application/json
JSON形式を指定していますね。
JSON形式では、値(バリュー)と、値の名前のキーのペアをコロン「:」で対にして、
それらをコンマ「,」で区切り、全体を波かっこ「{...}」で括って表現する形式です。
こんな感じになりますね。江戸川乱歩めっちゃ好きなので、本の宣伝もしちゃう。

```
"book1":{ "title": "Phantom twenty face","year": 2005 ,"page": 350}
```

###application/x-www-form-urlencoded
この形式だと、キーバリューはキーとバリューを「=」で結合することで記述されます。
また、キーバリューセットがが複数ある場合は、「&」で区切られるそうです。
そして、dataはURLエンコードされるとありました。
URLエンコードというのは、表記できない文字の文字コードを16進数で表し、
「%」に続けて表記し、その文字を置き換える表記のことを言います。
そのため、パーセントエンコードとも呼ばれています。

　例えば、KINTAN表参道店だとこうかなぁ〜

```
データ形式の例：(Restaurant=KINTAN&where=Omotesando)
URLエンコードの例：焼肉 → %E7%84%BC%E8%82%89
```

>atwata developer blog
　http://blog.atwata.com/web/2017/04/20/http-request-content-type.html
HTTPリクエストのContent-typeについては、この方のブログが一番綺麗にまとまっていました。


##最後におまけ
HTTP通信を生で見ようかなと思って、curlして生で見てみました。
AbemaTVの「田端信太郎VS藤田孝典」面白かったですね〜。
田端さんがお話していた「全員気持ちよく金を使いたくなる社会」がいいと思いました。

そんなわけで、WEARにcurl (GETリクエスト) してHTTP通信を生で見てみました。
オプションが豊富で、いろんなプロトコルにも対応してくれてありがたいです。
HTTPメソッド のGET リクエストが送られていたり、TSL通信が始まったりするところも見れちゃいますね〜。

```
[root@cbbb33c66501 work]# curl --verbos https://wear.jp/ -o ./wear.txt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* About to connect() to wear.jp port 443 (#0)
*   Trying 175.111.83.51...
* Connected to wear.jp (175.111.83.51) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* 	subject: CN=wear.jp,O="START TODAY CO., LTD.",OU=System,L=CHIBA-SHI,ST=CHIBA,C=JP
* 	start date: Apr 26 03:11:04 2018 GMT
* 	expire date: Jul 01 23:59:59 2020 GMT
* 	common name: wear.jp
* 	issuer: CN=GlobalSign Organization Validation CA - SHA256 - G2,O=GlobalSign nv-sa,C=BE
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: wear.jp
> Accept: */*
> 
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Length: 141665
< Content-Type: text/html; Charset=UTF-8
< Set-Cookie: PreObjectID=; expires=Sat, 10-Nov-2018 15:00:00 GMT; domain=.wear.jp; path=/
< Set-Cookie: AF%5FPreObjectID=; expires=Sat, 10-Nov-2018 15:00:00 GMT; domain=.wear.jp; path=/
< Set-Cookie: AF%5FPreScreenID=; expires=Sat, 10-Nov-2018 15:00:00 GMT; domain=.wear.jp; path=/
< Set-Cookie: ObjectID=; expires=Sat, 10-Nov-2018 15:00:00 GMT; domain=.wear.jp; path=/
< Set-Cookie: PreScreenID=; expires=Sat, 10-Nov-2018 15:00:00 GMT; domain=.wear.jp; path=/
< Set-Cookie: ScreenID=; expires=Sat, 10-Nov-2018 15:00:00 GMT; domain=.wear.jp; path=/
< Set-Cookie: AF%5FScreenID=12; expires=Sun, 18-Nov-2018 15:00:00 GMT; domain=.wear.jp; path=/
< Set-Cookie: AF%5FObjectID=; expires=Sat, 10-Nov-2018 15:00:00 GMT; domain=.wear.jp; path=/
< Set-Cookie: LocaleID=MQ%3D%3D%2D%2D46be9f2f8609755b62badaba4488e04c3da0adf1237bddab7d78accebcadc3c8; expires=Tue, 18-Dec-2018 15:00:00 GMT; domain=.wear.jp; path=/
< Set-Cookie: ZOZO%5FUID=%3A65177467%3A595854930; expires=Thu, 30-Jul-2020 15:00:00 GMT; domain=.wear.jp; path=/
< Set-Cookie: ASPSESSIONIDQQRDQBRB=JGFICODAMLDKKLJENAKKCJFC; path=/
< Date: Sun, 18 Nov 2018 02:15:31 GMT
< Set-Cookie: BIGipServerIN51_wear.jp_Pool=1649482250.20480.0000; path=/; Httponly
< Set-Cookie: TS01145b15=0182a260475cac19114f0c5a22225c7a08322e320179019429bc3095c2da4cb67d9623533dc2dfd8f7a73be26886dd07b3e755506a; Path=/
< Set-Cookie: TS0148206c=0182a260475cac19114f0c5a22225c7a08322e320179019429bc3095c2da4cb67d9623533dc2dfd8f7a73be26886dd07b3e755506a; path=/; domain=.wear.jp
< 
{ [data not shown]
100  138k  100  138k    0     0   146k      0 --:--:-- --:--:-- --:--:--  146k
* Connection #0 to host wear.jp left intact
```

#<参考>
Webhookって何？を子どもでもわかるように描いてみた | kintone hive online 
https://kintone-blog.cybozu.co.jp/developer/000283.html
サイボウズめっちゃ好きだ〜。
くま、可愛いかよ。

Using application/x-www-form-urlencoded format
https://github.com/axios/axios#using-applicationx-www-form-urlencoded-format

Github Webhook Tutorial.md
https://gist.github.com/jagrosh/5b1761213e33fc5b54ec7f6379034a22

Web-hooks
https://developer.github.com/enterprise/2.10/webhooks/
https://developer.github.com/webhooks/

URLエンコード・デコード 日本語URLを扱う場合にどうぞ
https://tech-unlimited.com/urlencode.html

FormData オブジェクトの利用
https://developer.mozilla.org/ja/docs/Web/Guide/Using_FormData_Objects

MIME タイプ
https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types