Slide 1

Slide 1 text

AWS Lambdaで作る GitHub bot SRE-SET Automation-night #2 佐々木 健一 SRE@株式会社メルカリ

Slide 2

Slide 2 text

自己紹介 Kenichi SASAKI (@siroken3) Software Engineer (SRE) Mercari, Inc (2014/7〜)

Slide 3

Slide 3 text

GitHub bot • 造語 • bot=人間ぽいもの • botと仲良く働いてやりましょう!

Slide 4

Slide 4 text

GitHub botでできること • PullRequestへのコメントで何かさせる • Issueに自動的にラベリング • PullRequestの内容チェック • Request_changes • GitHub apiは多機能

Slide 5

Slide 5 text

AWS Lambda • AWSのサーバレスアーキテクチャ • インフラの面倒をみなくてもよい

Slide 6

Slide 6 text

今回作ってみるGitHub bot • PullRequest へのコメントに反応 • 「Repeat 文言」 とコメントするとbotが 発言

Slide 7

Slide 7 text

デモ

Slide 8

Slide 8 text

全体像 SNS Event Invoke GitHub api

Slide 9

Slide 9 text

開発環境 • 言語 • Node.js (v6.10.3) • ライブラリ • AWS-SDK • @octocat/rest

Slide 10

Slide 10 text

開発環境 • デプロイツール • Apex (http://apex.run) • GitHub統合方法 • Personal access tokens • (bot専用のGitHubアカウントがよさそう)

Slide 11

Slide 11 text

今回のコードは https://github.com/siroken3/SreSetAutomationNightVol2

Slide 12

Slide 12 text

Lambda SNS Event Invoke GitHub api

Slide 13

Slide 13 text

Apex project init $ apex init _ ____ _______ __ / \ | _ \| ____\ \/ / / _ \ | |_) | _| \ / / ___ \| __/| |___ / \ /_/ \_\_| |_____/_/\_\ Enter the name of your project. It should be machine-friendly, as this is used to prefix your functions in Lambda. Project name: SRE-SET-Automation-Night-Vol2 Enter an optional description of your project. Project description: A sample apex project for SRE-SET automation night vol.2 [+] creating IAM SRE-SET-Automation-Night-Vol2_lambda_function role [+] creating IAM SRE-SET-Automation-Night-Vol2_lambda_logs policy [+] attaching policy to lambda_function role. [+] creating ./project.json [+] creating ./functions Setup complete, deploy those functions! $ apex deploy

Slide 14

Slide 14 text

GitHub api SNS Event Invoke GitHub api

Slide 15

Slide 15 text

How to get personal token Settings > Developer settings > Personal access tokens > Generate new token Scopeの選択は repo

Slide 16

Slide 16 text

Create KMS Key for Encrypt Apexが生成した Role 自分の IAMユーザ AWS KMS で暗号化

Slide 17

Slide 17 text

Encrypt personal token $ aws kms encrypt --key-id \ arn:aws:kms:us-east-1:xxxxxxxxxxxx:alias/AutomationNight \ --plaintext $TOKEN \ --query CiphertextBlob \ --output text (base64化されたTOKENが出力される) $ vim project.json "role": "arn:aws:iam::... "environment": { "GITHUB_TOKEN": (base64化されたTOKEN) }, "kms_arn": 作成したKMS Keyのarn

Slide 18

Slide 18 text

Decrypt the token const AWS = require("aws-sdk"); const decrypt = (encrypted) => { const kms = new AWS.KMS(); return kms.decrypt({ CiphertextBlob: new Buffer(encrypted, 'base64') }).promise() .then((data) => { return data.Plaintext.toString('ascii'); }); };

Slide 19

Slide 19 text

Decryptされたtokenで認証 exports.handle = (event, context, callback) => { let message = JSON.parse(event.Records[0].Sns.Message); let encryptedGithubToken = process.env['GITHUB_TOKEN']; decrypt(encryptedGithubToken) .then((token) => { // Decrypt enveironment variable GITHUB_TOKEN octokit.authenticate({ type: "oauth", token: token }); // 以降実行したいコード }

Slide 20

Slide 20 text

Lambda invoke SNS Event Invoke GitHub api

Slide 21

Slide 21 text

Setup AWS SNS Topics

Slide 22

Slide 22 text

AWS SNS - Lambda連携

Slide 23

Slide 23 text

AWS SNS - Lambda連携 exports.handle = (event, context, callback) => { let msg = JSON.parse(event.Records[0].Sns.Message); { Event: { Records[{ Sns: { Message: “エスケープされたJSON形式でのGitHubイベント” } }] } }

Slide 24

Slide 24 text

PullRequestにコメント const octokit = require("@octokit/rest")(); // This condition prevents infinity loop if (mag.comment.body.match(/^repeat/i)) { // Call GitHub api which creates issue comment. return octokit.issues.createComment({ owner: msg.repository.owner.login, repo: msg.repository.name, number: msg.issue.number, body: `@${msg.sender.login}, You said "${msg.comment.body}"` }); } else { return Promise.resolve("The comment was ignored."); }

Slide 25

Slide 25 text

Setup GitHub SNS Event SNS Event Invoke GitHub api

Slide 26

Slide 26 text

GitHub発行イベント (Repository) Settings > Integrations & services

Slide 27

Slide 27 text

GitHub発行イベント • デフォルトでSNSで受け取れるGitHub のイベント= “push”のみ • 変更できる

Slide 28

Slide 28 text

GitHub発行イベント変更 $ export TOKEN=xxxx $ export REPO_NAME=SreSetAutomationNightVol2 $ export GITHUB_ID=siroken3 $ export HOOK_ID=$(curl -X GET -s -H "Authorization: token $TOKEN" https://api.github.com/repos/$GITHUB_ID/$REPO_NAME/hooks | jq '.[] | select( .name == "amazonsns") | .id') $ curl -X PATCH -s -H "Authorization: token xxxxxx" https://api.github.com/repos/$GITHUB_ID/$REPO_NAME/hooks/$HO OK_ID -d '{"add_events": ["issue_comment"], "remove_events": ["push"]}'

Slide 29

Slide 29 text

これで全てがつながった! SNS Event Invoke GitHub api

Slide 30

Slide 30 text

今回のコードは https://github.com/siroken3/SreSetAutomationNightVol2

Slide 31

Slide 31 text

所感・落ち穂拾い • システム間連携肝要 • プリミティブな処理も必要 • GitHub apiのドキュメント重要 • イベントの解析にconsole.log重宝 • AWS Cloud9のlambdaデバッガよさそう?

Slide 32

Slide 32 text

参考 • GitHubのプルリクエストをAmazon SNSに通知する (クラスメソッド株式会 社) • https://dev.classmethod.jp/cloud/aws/github-p ullrequest-to-amazonsns/

Slide 33

Slide 33 text

参考 • AWS Lambdaで環境変数とKMSを 使ってkintoneのAPIアクセス情報を設 定する (株式会社ジョイゾー) • https://www.joyzo.co.jp/blog/3616

Slide 34

Slide 34 text

参考 • @octokit/rest • https://octokit.github.io/rest.js • GitHub REST API v3 (GitHub Inc.) • https://developer.github.com/v3/

Slide 35

Slide 35 text

ご静聴ありがとうございました