Skip to content

Instantly share code, notes, and snippets.

@nakano348
Created December 9, 2017 16:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nakano348/1f927f0cb189de30683b27e019f8f794 to your computer and use it in GitHub Desktop.
Save nakano348/1f927f0cb189de30683b27e019f8f794 to your computer and use it in GitHub Desktop.
GraphQLを使って指定したGithubリポジトリのプルリクエスト情報を取得・Slackに送信するLambda関数です。
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