99 lines
2.7 KiB
JavaScript
99 lines
2.7 KiB
JavaScript
const fetch = require('node-fetch');
|
|
|
|
module.exports = class GithubReviews {
|
|
|
|
token = null;
|
|
kreditsAmounts = null;
|
|
pageLimit = 100;
|
|
|
|
constructor (token, kreditsAmounts) {
|
|
this.token = token;
|
|
this.kreditsAmounts = kreditsAmounts;
|
|
}
|
|
|
|
async request (path) {
|
|
return fetch(
|
|
`https://api.github.com${path}`,
|
|
{
|
|
headers: {
|
|
'Accept': 'application/vnd.github.v3+json',
|
|
'User-Agent': 'Kosmos Kredits for reviews',
|
|
'Authorization': `token ${this.token}`
|
|
}
|
|
}
|
|
).then(response => response.json());
|
|
}
|
|
|
|
async getReviewContributions (repos, startDate, endDate) {
|
|
let reviewContributions = {}
|
|
|
|
await Promise.all(repos.map(async (repo) => {
|
|
let page = 1;
|
|
let result;
|
|
|
|
do {
|
|
try {
|
|
result = await this.request(`/repos/${repo}/pulls?state=closed&perPage=${this.pageLimit}&page=${page}`);
|
|
} catch(error) {
|
|
console.log(`failed to fetch PRs for repo ${repo}:`, error.message);
|
|
continue;
|
|
}
|
|
|
|
if (!result || result.length === 0) {
|
|
continue;
|
|
}
|
|
|
|
let pullRequests = result.filter(pr => {
|
|
if (!pr.merged_at) return false; // only interested in merged PRs
|
|
|
|
// check if the PR has been merged in the given timeframe
|
|
const mergeDate = new Date(pr.merged_at);
|
|
if (mergeDate < startDate || mergeDate > endDate) return false;
|
|
|
|
// check if the PR has a kredits label
|
|
return pr.labels.some(label => label.name.match(/kredits-[123]/));
|
|
});
|
|
|
|
await Promise.all(pullRequests.map(async (pr) => {
|
|
let reviews;
|
|
try {
|
|
reviews = await this.request(`/repos/${repo}/pulls/${pr.number}/reviews`);
|
|
} catch(error) {
|
|
console.log(`failed to fetch reviews for repo ${repo}, PR ${pr.number}:`, error.message);
|
|
return;
|
|
}
|
|
|
|
if (!reviews || reviews.length === 0) {
|
|
return;
|
|
}
|
|
|
|
reviews = reviews.filter(review => {
|
|
return ['APPROVED', 'REJECTED'].includes(review.state);
|
|
});
|
|
|
|
reviews.forEach(review => {
|
|
if (typeof reviewContributions[review.user.login] === 'undefined') {
|
|
reviewContributions[review.user.login] = [];
|
|
}
|
|
|
|
let kreditsLabel = pr.labels.find(label => label.name.match(/kredits-[123]/));
|
|
|
|
reviewContributions[review.user.login].push({
|
|
pr,
|
|
prNumber: pr.number,
|
|
review,
|
|
reviewState: review.state,
|
|
kredits: this.kreditsAmounts[kreditsLabel.name]
|
|
});
|
|
});
|
|
}));
|
|
|
|
page++;
|
|
} while (result && result.length > 0);
|
|
}));
|
|
|
|
return reviewContributions;
|
|
}
|
|
|
|
}
|