Created
December 9, 2017 16:12
-
-
Save nakano348/1f927f0cb189de30683b27e019f8f794 to your computer and use it in GitHub Desktop.
GraphQLを使って指定したGithubリポジトリのプルリクエスト情報を取得・Slackに送信するLambda関数です。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const AWS = require('aws-sdk'); | |
const url = require('url'); | |
const https = require('https'); | |
const GraphQLClient = require('graphql-request').GraphQLClient; | |
// Github APIで使用するトークン | |
const token = process.env.token; | |
// リポジトリの所有者名 | |
const owner = process.env.owner; | |
// Githubのリポジトリ名 | |
const repo = process.env.repo; | |
// 送信先のSlackのチャンネル名 | |
const slackChannel = process.env.slackChannel; | |
// Slackのincoming webhookのURL | |
const encrypted = process.env['kmsEncryptedHookUrl']; | |
let decrypted; | |
// Github API v4のエンドポイント | |
const endpoint = 'https://api.github.com/graphql'; | |
const client = new GraphQLClient(endpoint, { | |
headers: { | |
Authorization: 'bearer ' + token, | |
}, | |
}); | |
// Github API(GraphQL)のクエリ | |
const query = `{ | |
repository(owner: "${owner}", name: "${repo}") { | |
pullRequests(last: 10, states:[OPEN]) { | |
edges { | |
node { | |
number | |
} | |
} | |
} | |
} | |
}`; | |
// OPEN状態のプルリクエストの情報を取得する | |
function getOpenedPullRequests(callback) { | |
let message; | |
client.request(query) | |
.then( | |
data => { | |
// マージされていないプルリクエストの件数を取得 | |
let number = data.repository.pullRequests.edges.length; | |
// 送信するメッセージを定義 | |
message = 'マージされていないプルリクエストが' + number + '件あります。'; | |
postMessage(message, (response) => { | |
if (response.statusCode < 400) { | |
console.info('Message posted successfully'); | |
callback(null); | |
} else if (response.statusCode < 500) { | |
console.error(`Error posting message to Slack API: ${response.statusCode} - ${response.statusMessage}`); | |
callback(null); // Don't retry because the error is due to a problem with the request | |
} else { | |
// Let Lambda retry | |
callback(`Server error when processing message: ${response.statusCode} - ${response.statusMessage}`); | |
} | |
}); | |
} | |
).catch(err => { | |
console.log(err.response.errors); // GraphQL response errors | |
console.log(err.response.data); // Response data if available | |
}); | |
} | |
// Slackにメッセージを送信する | |
function postMessage(message, callback) { | |
const slackMessage = { | |
channel: slackChannel, | |
text: message.toString() | |
}; | |
console.log(slackMessage); | |
const body = JSON.stringify(slackMessage); | |
const options = url.parse(decrypted); | |
options.method = 'POST'; | |
options.headers = { | |
'Content-Type': 'application/json', | |
'Content-Length': Buffer.byteLength(body), | |
}; | |
const postReq = https.request(options, (res) => { | |
const chunks = []; | |
res.setEncoding('utf8'); | |
res.on('data', (chunk) => chunks.push(chunk)); | |
res.on('end', () => { | |
if (callback) { | |
callback({ | |
body: chunks.join(''), | |
statusCode: res.statusCode, | |
statusMessage: res.statusMessage, | |
}); | |
} | |
}); | |
return res; | |
}); | |
postReq.write(body); | |
postReq.end(); | |
} | |
function processEvent(event, context, callback) { | |
getOpenedPullRequests(callback); | |
} | |
exports.handler = (event, context, callback) => { | |
if (decrypted) { | |
processEvent(event, context, callback); | |
} else { | |
// Decrypt code should run once and variables stored outside of the function | |
// handler so that these are decrypted once per container | |
const kms = new AWS.KMS(); | |
kms.decrypt({ CiphertextBlob: new Buffer(encrypted, 'base64') }, (err, data) => { | |
if (err) { | |
console.log('Decrypt error:', err); | |
return callback(err); | |
} | |
decrypted = data.Plaintext.toString('ascii'); | |
processEvent(event, context, callback); | |
}); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment