GitHubのプルリクエストをAmazon SNSに通知する

github

はじめに

好物はインフラとフロントエンドのかじわらゆたかです。

GitHubのIntegration & serviceを用いることで、Amazon SNSとGitHubを連携させることができます。
Amazon SNSはAWS Lambdaと連携させることも可能なため、通知されたSNSを元にAWS Lambdaで処理を行うと言った事が可能です。

ですがデフォルトの設定のままでは、プルリクエストが作成されたイベントをAWS Lambdaで処理させるといったことが出来ません。
デフォルトのAmazon SNSとGitHubとの連携ではGitHubのPushのみが対応となっているためです。
そのため別途GitHubnの通知設定を行うことで、プルリクエストをAmazon SNSに通知させることができます。

下準備

GitHubリポジトリとAmazon SNSの連携設定を行っておきます。
また通知された内容の確認用のAWS Lambdaを作成しAmazon SNSと連携させておくことで、
どのようなリクエストがGitHubからAmazonSNSに通知されたかを確認できるようにします。

import json
import boto3
import time
bucket_name = '(イベント結果を格納するバケット名)'

def lambda_handler(event, context):
    json_key = str(time.time()) + ".json"
    s3 = boto3.resource('s3')
    obj = s3.Object(bucket_name,json_key)
    r = obj.put(Body = json.dumps(event, indent=2))
    eventName = event['Records'][0]['Sns']['MessageAttributes']['X-Github-Event'];
    print("eventName:" + json.dumps(eventName))
    return ref

プルリクエストをAmazon SNSに通知させてみる

この状態でプルリクエストをだしても、プルリクエストの情報は取得できません。 上記でも記載した通り、GitHubとAmazon SNSの連携のデフォルトの設定はPushのみが対象となっているためです。 Amazon SNSのHookの標準の設定は以下のようになっています。

$ curl https://api.github.com/hooks | jq 'map(select(.name=="amazonsns"))'
[
  {
    "name": "amazonsns",
    "events": [
      "push"
    ],
    "supported_events": [
      "commit_comment",
      "create",
      "delete",
      "deployment",
      "deployment_status",
      "download",
      "follow",
      "fork",
      "fork_apply",
      "gist",
      "gollum",
      "issue_comment",
      "issues",
      "member",
      "public",
      "pull_request",
      "pull_request_review_comment",
      "push",
      "release",
      "status",
      "team_add",
      "watch"
    ],
    "title": "Amazon SNS",
    "schema": [
      [
        "string",
        "aws_key"
      ],
      [
        "string",
        "sns_topic"
      ],
      [
        "string",
        "sns_region"
      ],
      [
        "password",
        "aws_secret"
      ]
    ]
  }
]

eventsがpushのみになっていることがわかります。
また、SupportEventでpull_requestも使えることもわかります。

これらの設定の変更手順は以下のようになります。

  1. GitHubのリポジトリとAmazon SNSの連携の設定を行う
  2. 上記の設定で払い出されたidを確認する
  3. 払い出されたidに対してhook対象のeventの追加を行う

今回は既にGitHubのリポジトリとAmazon SNSの連携は行われているものとして進めます。
払い出されたidの確認に関しては以下のURLで確認できます。

curl -u (github user name) https://api.github.com/repos/(リポジトリのOwner)/(リポジトリ名)/hooks
[
  {
    "type": "Repository",
    "id": 12345678,
    "name": "amazonsns",
    "active": true,
    "events": [
      "push"
    ],
    "config": {
      "aws_key": "(AWS AccessKey)",
      "aws_secret": "********",
      "sns_region": "(設定したリージョン)",
      "sns_topic": "(設定したSNS)"
    },
    "updated_at": "2017-06-27T07:09:02Z",
    "created_at": "2017-06-27T07:09:02Z",
    "url": "https://api.github.com/repos/(リポジトリのOwner)/(リポジトリ名)/hooks/12345678",
    "test_url": "https://api.github.com/repos/(リポジトリのOwner)/(リポジトリ名)/hooks/12345678/test",
    "ping_url": "https://api.github.com/repos/(リポジトリのOwner)/(リポジトリ名)/hooks/12345678/pings",
    "last_response": {
      "code": 200,
      "status": "active",
      "message": "OK"
    }
  }
]

これで取得したIDを用いてEventの種類を追加します。
追加するリクエストは以下になります。
また、このリクエストのレスポンスでeventにpull_requestが追加されたことも確認できます。

curl -u (github user name) https://api.github.com/repos/(リポジトリのOwner)/(リポジトリ名)/hooks/12345678 -X PATCH  -d '{ "add_events": ["pull_request"] }'
[
  {
    "type": "Repository",
    "id": 12345678,
    "name": "amazonsns",
    "active": true,
    "events": [
      "push"
      "pull_request"
    ],
    "config": {
      "aws_key": "(AWS AccessKey)",
      "aws_secret": "********",
      "sns_region": "(設定したリージョン)",
      "sns_topic": "(設定したSNS)"
    },
    "updated_at": "2017-06-28T12:37:35Z",
    "created_at": "2017-06-27T07:09:02Z",
    "url": "https://api.github.com/repos/(リポジトリのOwner)/(リポジトリ名)/hooks/12345678",
    "test_url": "https://api.github.com/repos/(リポジトリのOwner)/(リポジトリ名)/hooks/12345678/test",
    "ping_url": "https://api.github.com/repos/(リポジトリのOwner)/(リポジトリ名)/hooks/12345678/pings",
    "last_response": {
      "code": 200,
      "status": "active",
      "message": "OK"
    }
  }
]

プルリクエストの結果のイベントを確認してみる

設定したリポジトリに対してプルリクエストを送付したところ以下の様なJSONが取得できました。

{
  "Records": [
    {
      "EventSource": "aws:sns",
      "EventVersion": "1.0",
      "EventSubscriptionArn": "arn:aws:sns:(省略)",
      "Sns": {
        "Type": "Notification",
        "MessageId": "(省略)",
        "TopicArn": "arn:aws:sns:(省略)",
        "Subject": null,
        "Message": "(省略)",
        "Timestamp": "2017-06-28T12:48:13.590Z",
        "SignatureVersion": "1",
        "Signature": "(省略)",
        "SigningCertUrl": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-b95095beb82e8f6a046b3aafc7f4149a.pem",
        "UnsubscribeUrl": "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:216054658829:github_notification_sample:d2a8c18f-0fe4-4844-9c3b-fae4b40ae8e0",
        "MessageAttributes": {
          "X-Github-Event": {
            "Type": "String",
            "Value": "pull_request"
          }
        }
      }
    }
  ]
}

ほとんどの項目をマスクしているのですが、MessageAttributesの項目でpull_requestが取得できたことがわかるかと思います。

参考文献

GitHubのissueやpull reqにcommentが付いたらIRC hoooks経由で通知されるように設定した - Glide Note

Repository Webhooks | GitHub Developer Guide