Skip to content

Instantly share code, notes, and snippets.

@zamber
Created October 4, 2020 15:49
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 zamber/60e12bed44b71fb690c853ec0f5781bf to your computer and use it in GitHub Desktop.
Save zamber/60e12bed44b71fb690c853ec0f5781bf to your computer and use it in GitHub Desktop.
BitBucket PR creation webhook -> AWS Lambda -> Slack bot
/*
Used for a bigger team where not everyone is on Slack. A random user from the list is chosen and notified about a PR.
If the user is already set as a reviewer it's discarded from the random pool.
The lambda is the most simple configuration for requests with 128MB of RAM provisioned.
https://support.atlassian.com/bitbucket-cloud/docs/event-payloads/
https://api.slack.com/messaging/webhooks
*/
const https = require('https');
const hook = data => new Promise((resolve, reject) => {
const options = {
host: 'hooks.slack.com',
path: '/services/...', // change me
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
};
const req = https.request(options, res => { resolve(JSON.stringify(res.statusCode)); });
req.on('error', e => { reject(e.message); });
req.write(JSON.stringify(data));
req.end();
});
const users = [ // [slack_user_id, bitbucket_user_name]
['UDEADBEEF', 'John Smith'],
];
const pickReviewer = excludeUsers => {
const bb_users = users.map(u => u[1]);
const slack_users = users.map(u => u[0]);
excludeUsers.forEach(user => {
const i = bb_users.indexOf(user);
if (i > -1) {
bb_users.splice(i, 1);
slack_users.splice(i, 1);
}
});
return slack_users[Math.floor(Math.random() * slack_users.length)];
};
const bb_users = users.map(u => u[1]);
const slack_users = users.map(u => u[0]);
const getUser = user => (bb_users.indexOf(user) !== -1 ? `<@${slack_users[bb_users.indexOf(user)]}>` : user);
const reviewersList = reviewers => {
if (reviewers.length === 0) return '';
return `
:mag_right: ${reviewers.map(getUser).join(', ')}
`;
};
const formatSlackMessage = body => {
const pr = body.pullrequest;
const reviewers = pr.reviewers.map(r => r.display_name);
const author = body.pullrequest.author.display_name;
const text = `:git-pr: <${pr.links.html.href}|*${pr.title}*>
:writing_hand: ${pr.author.display_name}${reviewersList(reviewers)}
:game_die: <@${pickReviewer([...reviewers, author])}>`;
return { text };
};
exports.handler = async event => {
let body;
let statusCode = '200';
const headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
};
try {
if (event.httpMethod === 'POST') {
body = await JSON.parse(event.body);
await hook(formatSlackMessage(body))
.then(result => console.log(`Status code: ${result}`))
.catch(err => console.error(`Error doing the request for the event: ${JSON.stringify(event)} => ${err}`));
}
} catch (err) {
statusCode = '400';
body = err.message;
}
return {
statusCode,
body,
headers,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment