ちょっと前にGitHubのeventをAWS Lambda で処理して、GitHubやSlackのAPIを叩く仕組みを作ったので、メモ。
材料
Github
SNS
KMS
Lambda
Slack
やりたいことはこんな感じ。
あるGitHubリポジトリのissuesに特定のコメントが書き込まれると、そのユーザはプロジェクトのteamに自動で追加されて、Slackへ通知が流れるというモノです。
SNS
まずは媒介となるSNSの作成。
1
2
3
4
$ aws sns create-topic --name github --region ap-northeast-1
{
"TopicArn": "arn:aws:sns:ap-northeast-1:123456789012:github"
}
次にSNSに対してpublishできるIAM userを作成
IAM Policy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"sns:Publish"
],
"Sid": "Stmt0000000000000",
"Resource": [
"arn:aws:sns:ap-northeast-1:123456789012:github"
],
"Effect": "Allow"
}
]
}
GitHub
organization: my_org
repository: test
team: reader
SNS連携
Webhooks & Services からAmazonSNSと連携
AWS KEYには先ほど作成したIAMユーザのを利用。SNS topicのarnにはregionが書かれているにも関わらず、GitHubの方では明示的に指定が必要。
通知するeventの有効化
さて、GitHubではSNSの場合、hooksのjson にある通り、push
時のeventにしか対応していないので、
hooks link 1
2
3
4
"name" : "amazonsns" ,
"events" : [
"push"
] ,
GitHubのWebhook API に従ってissue_comment
を追加してやります。
先ほどのSNS連携のhook idを取得するにはGET /orgs/:org/hooks
1
2
export HOOK_ID = $( curl -H 'Uer-Agent: ijin' -X GET -s -H "Authorization: token xxxxxxxxxx" \
https://api.github.com/repos/my_org/test/hooks | jq '.[].id' )
編集するにはPATCH /orgs/:org/hooks/:id
1
2
curl -H 'Uer-Agent: ijin' -X PATCH -s -H "Authorization: token xxxxxxxxxx" \
https://api.github.com/repos/my_org/test/hooks/$HOOK_ID -d '{"add_events": ["issue_comment"]}' | jq .
Web UIからは分からないので、ついでにreader
teamのIDも取得しておく
1
2
curl -H 'Uer-Agent: ijin' -X GET -s -H "Authorization: token xxxxxxxxxx" \
https://api.github.com/orgs/my_org/teams | jq '.[] | select(.name=="reader")'
(※)User-Agentは必須
これで、誰かがコメントをした時にもSNSが飛びます。
KMS
lambdaでは以下の認証情報を使うので、予めKMSで暗号化しておく。
GitHub token
Slack webhook
rubyで暗号化する場合
1
2
3
4
require 'aws-sdk'
require 'base64'
kms = Aws : :KMS :: Client . new ( region : 'us-east-1' )
Base64 . encode64 kms . encrypt ( key_id : "alias/ijin" , plaintext : 'my plain text code' ) . ciphertext_blob
javascriptの場合
1
2
3
4
5
6
7
var aws = require ( 'aws-sdk' );
var kms = new aws . KMS ({ region : 'us-east-1' });
var text = 'my plain text code' ;
kms . encrypt ({ KeyId : 'alias/ijin' , Plaintext : text }, function ( err , data ) {
if ( err ) console . log ( err , err . stack );
else console . log ( data . CiphertextBlob . toString ( 'base64' ));
});
こうしておくと、SCMに入れても安心。
また、KMSキーの実行権限もlambdaのroleに紐づけておく。
Lambda
Lambda function作成時にはSNSをevent sourceとして指定。
(※) KMSは現在us-eastにしかないので、そこ以外のregionでlambdaを実行する場合は、timeout
は若干長めに指定して置くと良さげ
コードはこんな感じ。
GitHubからSNS hookを受け取って
コメントした内容がjoin
の場合
KMSによってGitHubのtokenを復号化し
そのユーザをteamへ追加する
その後、別lambda functionでslackへ通知する
nodeのlibraryを使うともっとスッキリ書けたけど、1 function 1 fileで纏めたかったのでやや冗長なコードになっちゃいました。。
実行
GitHubでコメント
Lambda発動
1
2
3
4
5
6
7
8
9
10
11
2015 - 08 - 11 T15 : 42 : 53.108 Z a09e3c80 - 403 f - 1 e15 - bbb5 - 55 b693433c0e user : ijin2
2015 - 08 - 11 T15 : 42 : 53.108 Z a09e3c80 - 403 f - 1 e15 - bbb5 - 55 b693433c0e comment : join
2015 - 08 - 11 T15 : 42 : 55.417 Z a09e3c80 - 403 f - 1 e15 - bbb5 - 55 b693433c0e status code : 200
2015 - 08 - 11 T15 : 42 : 55.418 Z a09e3c80 - 403 f - 1 e15 - bbb5 - 55 b693433c0e response :
{
"state" : "pending" ,
"url" : "https://api.github.com/teams/1234567/memberships/ijin2"
}
2015 - 08 - 11 T15 : 42 : 55.418 Z a09e3c80 - 403 f - 1 e15 - bbb5 - 55 b693433c0e Added to the team
END RequestId : a09e3c80 - 403 f - 1 e15 - bbb5 - 55 b693433c0e
REPORT RequestId : a09e3c80 - 403 f - 1 e15 - bbb5 - 55 b693433c0e Duration : 5211.48 ms Billed Duration : 5300 ms Memory Size : 128 MB Max Memory Used : 14 MB
1
2
3
4
5
6
7
8
9
10
11
2015 - 08 - 11 T15 : 42 : 56.058 Z a25c66fc - 403 f - 11 e5 - b291 - 25 d4ee441689 Received event :
{
"username" : "ijin2" ,
"icon_url" : "https://avatars.githubusercontent.com/u/12809425?v=3" ,
"text" : "Added to the team"
}
2015 - 08 - 11 T15 : 42 : 58.310 Z a25c66fc - 403 f - 1 e15 - b291 - 25 d4ee441689 200
2015 - 08 - 11 T15 : 42 : 58.311 Z a25c66fc - 403 f - 1 e15 - b291 - 25 d4ee441689 ok
2015 - 08 - 11 T15 : 42 : 58.311 Z a25c66fc - 403 f - 1 e15 - b291 - 25 d4ee441689 Successfully posted to Slack !
END RequestId : a25c66fc - 403 f - 11 e5 - b291 - 25 d4ee441689
REPORT RequestId : a25c66fc - 403 f - 1 e15 - b291 - 25 d4ee441689 Duration : 2268.06 ms Billed Duration : 2300 ms Memory Size : 128 MB Max Memory Used : 14 MB
teamへの追加(招待)
Slackへ通知
結論
簡単にできますね。実はこんな風に作っちゃった2週間後ぐらいにAWSの人も似たようなブログ を書いていた事を発見しましたが。まあ、こっちはKMSとSlack使ってるので。。
後、KMSのアイコンが欲しい!