Skip to content

Instantly share code, notes, and snippets.

@markis
Created September 14, 2016 18:23
Show Gist options
  • Save markis/4839efeec162432832a2d996b3e5348e to your computer and use it in GitHub Desktop.
Save markis/4839efeec162432832a2d996b3e5348e to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
const clear = '\033c';
(function() {
"use strict";
const https = require('https'),
config = require('./config'),
// array of usernames to filter
people = config.people,
// server for your bit bucket server
server = config.server,
// your username
username = config.username,
// your password
password = config.password,
// array of projects to watch
projects = config.projects,
// do not merge regex
dnmRegex = /\bdnm\b|\bdo not merge\b|\bqa\b/i,
titleLength = process.stdout.columns - 12;
let requestCount = 0;
loadPRS();
function loadPRS() {
Promise.all(
projects.map(proj => getRepos(proj))
)
.then(flatten)
.then(repos => Promise.all(
repos.map(repo => getPullRequests(repo.proj, repo.repo))
))
.then(flatten)
.then(displayPullRequests)
.catch(handleError);
}
function displayPullRequests(pullRequests) {
pullRequests.sort((pr1, pr2) => {
if (pr1.dnm && !pr2.dnm) return 1;
if (!pr1.dnm && pr2.dnm) return -1;
const diff1 = pr1.approvalCount / (pr1.reviewersCount || 1),
diff2 = pr2.approvalCount / (pr2.reviewersCount || 1);
if (diff1 < diff2) return 1;
if (diff1 > diff2) return -1;
return 0;
return 0;
});
process.stdout.write(clear);
pullRequests.forEach(pr => {
const
proj = pr.proj,
repo = pr.repo,
id = pr.id,
ac = pr.approvalCount,
rc = pr.reviewersCount,
title = pr.title.substr(0, titleLength),
author = pr.author.user.name.substr(0,4),
url = `https://${server}/projects/${proj}/repos/${repo}/pull-requests/${id}`;
if (!pr.dnm) {
console.log(`\x1b[91m${ac}/${rc} \x1b[36m[${author}]\x1b[0m ${title}`);
console.log(`\x1b[94m ${url}`);
} else {
console.log(`\x1b[0m\x1b[2m${ac}/${rc} [${author}] ${title}`);
console.log(` ${url}`);
}
});
}
function getPullRequests(proj, repo) {
return get(`/rest/api/1.0/projects/${proj}/repos/${repo}/pull-requests`)
.then((pullRequests) => {
if (pullRequests.values && pullRequests.values.length > 0) {
return pullRequests.values
.filter(pr => pr && pr.author && people.indexOf(pr.author.user.name) !== -1)
.map(pr => {
pr.approvalCount = pr.reviewers.filter(r => r.approved).length
pr.reviewersCount = pr.reviewers.length;
pr.proj = proj;
pr.repo = repo;
pr.dnm = dnmRegex.test(pr.title);
return pr;
});
} else {
return [];
}
});
}
function getRepos(proj) {
return get(`/rest/api/1.0/projects/${proj}/repos/?limit=150`)
.then((repos) => repos.values
.filter(repo => repo && repo.name && repo.name !== 'undefined')
.map(repo => {
return {
proj: proj,
repo: repo.name
}
})
)
}
function get(path) {
return new Promise(function(resolve, reject) {
const options = {
port: 443,
host: server,
path: path,
auth: username + ':' + password
};
requestCount++;
setTimeout(() => {
const request = https.request(options, function(resp) {
const buffer = [];
resp.on('error', reject);
resp.on('data', function (chunk) {
buffer.push(chunk);
});
resp.on('end', function () {
requestCount--;
if (request.res.statusCode === 200) {
const data = JSON.parse(buffer.join(''));
resolve(data);
} else if(request.res.statusCode === 502) {
console.error(buffer.join(''));
resolve([]);
} else if(request.res.statusCode === 404) {
console.error(buffer.join(''));
resolve([]);
} else {
reject(buffer.join(''));
}
});
});
request.end();
}, requestCount * 25);
});
}
function flatten(array) {
return [].concat.apply([], array)
}
function show(data) {
console.log(data);
}
function handleError(err) {
if (err && err.stack) {
console.error(err, err.stack);
} else if (err && err.errors) {
err.errors.forEach((err) => console.error(err.message));
} else {
console.error(err);
}
process.exit(1);
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment