Skip to content

Instantly share code, notes, and snippets.

@joseluisq
Created February 25, 2019 12:00
Show Gist options
  • Save joseluisq/66505b544bf8fca4486be86eb908779b to your computer and use it in GitHub Desktop.
Save joseluisq/66505b544bf8fca4486be86eb908779b to your computer and use it in GitHub Desktop.
Rocket Chat and Bitbucket Server webhooks integration
// Mock Request Data (Pull Request Comment)
module.exports = {
url: {
hash: null,
search: null,
query: {},
pathname: '/hooks/2f7YhFx2f7YhFx2f7YhFx/hUPO&&)6@HqG_wY^B(2$MK_ivkEU1ix7MK_ivkEU1ix7',
path: '/hooks/2f7YhFx2f7YhFx2f7YhFx/hUPO&&)6@HqG_wY^B(2$MK_ivkEU1ix7MK_ivkEU1ix7'
},
url_raw: '/hooks/2f7YhFx2f7YhFx2f7YhFx/hUPO&&)6@HqG_wY^B(2$MK_ivkEU1ix7MK_ivkEU1ix7',
url_params: {
integrationId: '2f7YhFx2f7YhFx2f7YhFx',
token: 'hUPO&&)6@HqG_wY^B(2$MK_ivkEU1ix7MK_ivkEU1ix7'
},
content: {
actor: {
username: 'jd',
displayName: 'John Doe'
},
pullrequest: {
id: '1',
title: 'ABCD-123: Create the results page',
link: 'https://bitbucket.mydomain.com/projects/ABCD/repos/some-project/pull-requests/1',
authorLogin: 'John Doe',
fromRef: [Object],
toRef: [Object]
},
repository: {
scmId: 'git',
project: { key: "ABCD", name: "My Awesome Project" },
slug: 'some-project',
links: { self: [ { href: "https://bitbucket.mydomain.com/projects/ABCD/repos/some-project/browse" } ] },
owner: { username: "ABCD", displayName: "ABCD" },
fullName: 'ABCD/some-project',
public: false,
ownerName: 'ABCD'
},
comment: 'This is a new PR comment!'
},
content_raw: null,
headers: {
host: 'chat.mydomain.com',
'user-agent': 'Apache-HttpClient/4.5.5 (Java/1.8.0_151)',
'content-length': '1696',
'accept-encoding': 'gzip,deflate',
'content-type': 'application/json; charset=UTF-8',
'x-bitbucket-type': 'server',
'x-event-key': 'pullrequest:comment',
'x-forwarded-for': '10.255.0.2',
'x-forwarded-host': 'chat.mydomain.com',
'x-forwarded-port': '443',
'x-forwarded-proto': 'https',
'x-forwarded-server': '1a2ad03db35e',
'x-real-ip': '10.255.0.2'
},
body: {
actor: {
username: 'jd',
displayName: 'John Doe'
},
pullrequest: {
id: '1',
title: 'ABCD-126: Create the results page',
link: 'https://bitbucket.mydomain.com/projects/ABCD/repos/some-project/pull-requests/1',
authorLogin: 'John Doe',
fromRef: [Object],
toRef: [Object]
},
repository: {
scmId: 'git',
project: [Object],
slug: 'some-project',
links: [Object],
owner: [Object],
fullName: 'ABCD/some-project',
public: false,
ownerName: 'ABCD'
},
comment: 'This is a new PR comment!'
},
user: {
_id: 'rocket.bot',
name: 'Rocket.Bot',
username: 'rocket.bot'
}
}
const config = {
bitBucketUrl: '',
color: '#225159',
update: true
};
const bitBucketUpdate = (request, i) => {
const text = 'New ' + request.content.refChanges[i].type.toLowerCase() + ' on project ' + request.content.repository.project.name;
const username = request.content.changesets.values[i].toCommit.author.name;
const usermail = request.content.changesets.values[i].toCommit.author.emailAddress;
const attachment = {
author_name: username + ' (' + usermail + ')',
title: 'Repository "' + request.content.repository.name + '" in project "' + request.content.repository.project.name + '" updated',
title_link: config['bitBucketUrl'].replace(/\/$/, '') + '/projects/' + request.content.repository.project.key + '/repos/' + request.content.repository.slug + '/browse/',
text: username + ' updated ' + request.content.changesets.values[i].changes.size + ((request.content.changesets.values[i].changes.size > 1) ? ' files' : ' file') + ' on branch ' + request.content.refChanges[i].refId + '` with message:\n"' + request.content.changesets.values[i].toCommit.message + '"',
color: ((config['color'] != '') ? '#' + config['color'].replace('#', '') : '#225159')
};
return {
content: {
text: text,
attachments: [attachment]
}
};
};
function get_basic_info(request) {
const content = request.content;
const author = {
username: content.actor.username,
displayName: content.actor.displayName
};
const repository = {
name: content.repository.fullName,
link: content.repository.links.self[0].href,
project: content.repository.project,
owner: content.repository.owner,
slug: content.repository.slug,
fullName: content.repository.fullName,
ownerName: content.repository.ownerName
};
const pullrequest = content.pullrequest || {};
const comment = content.comment || '';
return {
author,
repository,
pullrequest,
comment
};
}
function create_attachement(author, text, timestamp){
const attachment = {
author_name: author.displayname,
author_link: author.link,
author_icon: author.avatar,
text: text,
ts: timestamp
};
return attachment;
}
const processors = {
refChanges(request) {
let result = {};
if(config[change.type.toLowerCase()]) {
switch(change.type) {
case 'UPDATE':
result = bitBucketUpdate(request, i);
}
}
return result
},
pullrequest_created(request) {
const author = {
username: request.content.pullrequest.author.username,
displayname: request.content.pullrequest.author.display_name
};
const pullrequest = {
sourcerepo: request.content.pullrequest.source.repository.name,
sourcebranch: request.content.pullrequest.source.branch.name,
destinationrepo: request.content.pullrequest.destination.repository.name,
destinationbranch: request.content.pullrequest.destination.branch.name,
id: request.content.pullrequest.id,
title: request.content.pullrequest.title,
description: request.content.pullrequest.description
};
const links = {
self: request.content.pullrequest.links.self.href,
decline: request.content.pullrequest.links.decline.href,
approve: request.content.pullrequest.links.approve.href,
merge: request.content.pullrequest.links.merge.href,
commits: request.content.pullrequest.links.commits.href,
comments: request.content.pullrequest.links.comments.href
};
let text = '';
text += author.displayname + ' _(@' + author.username + ')_ *opened* a new pull request:\n';
text += '`' + pullrequest.sourcerepo + '/' + pullrequest.sourcebranch + '` => `' + pullrequest.destinationrepo + '/' + pullrequest.destinationbranch + '`\n\n';
text += 'Description:\n';
text += pullrequest.description + '\n';
let actions = 'Actions:';
if(showLinks.decline) {
actions += ' | [decline](' + links.decline + ')';
}
if(showLinks.approve) {
actions += ' | [approve](' + links.approve + ')';
}
if(showLinks.merge) {
actions += ' | [merge](' + links.merge + ')';
}
if(showLinks.commits) {
actions += ' | [view commits](' + links.commits + ')';
}
if(showLinks.comments) {
actions += ' | [view comments](' + links.comments + ')';
}
if(actions != 'Actions:') {
text += actions;
}
const attachment = {
author_name: '#' + pullrequest.id + ' - ' + pullrequest.title,
author_link: links.self
};
return {
content: {
text: text,
attachments: [attachment],
parseUrls: false,
color: ((config.color !== '') ? '#' + config.color.replace('#', '') : '#225159')
}
};
},
pullrequest_comment(request) {
const info = get_basic_info(request);
const author = info.author
const text = info.comment;
const pr = info.pullrequest;
const repo = info.repository;
const attachment = {
author_name: author.displayName + ' (' + author.username + ')',
title: 'New PR comment on "' + pr.title + '" (' + repo.fullName + ')',
title_link: pr.link,
text,
color: ((config['color'] != '') ? '#' + config['color'].replace('#', '') : '#225159')
};
return {
content: {
text,
attachments: [attachment]
}
};
}
}
class Script {
process_incoming_request({ request }) {
let result = {};
// debug only: output incoming request
console.log("REQUEST: ", request);
if (request.headers['x-event-key']) {
const key = request.headers['x-event-key'].replace(':', '_');
const fn = processors[key];
if (fn) {
result = processors[key](request);
}
}
if (result.content !== undefined) {
return result;
}
}
}
// Note:
// This is not a test suite (unit test o similar) but just a conventional usage test
// as a previous step to perform an integration webhook into RocketChat.
// 1. Add module.exports to rocket_chat_bitbucket_server.webhook.js (testing purpose only)
const { Script } = require('./rocket_chat_bitbucket_server.webhook');
// 2. Test a mocking request
const notice = new Script()
// Testing a Pull Request Comment (mocking)
const request = require('./request_comment.mock.js')
const res = notice.process_incoming_request({request})
// 3. Check out if the data is returning ok
console.log(res.content.attachments)
// 4. When data is ok, then copy rocket_chat_bitbucket_server.webhook.js content into RocketChat "Incoming WebHook Integration"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment