* feat: show open boilerplate prs on dashboard fix: rest of boilerplate server changes fix: more fix: other * fix: update lib functions * fix: retrofitted one-off scripts * feat: added rateLimit for requests * fix: reduce time * fix: put limiter inside each route * fix: make client show when rated limited * fix: removed unused probot from app * fix: renamed folders * fix: consolidate config.js and constants.js * chore: update octokit to latest version * fix: remove invalid file * fix: refactored update-db.js * feat: add fcc logo * fix: logo url * fix: remove Home link * fix: change link colors * fix: added rate limiter to landing page * fix: ran npm install in client to create package-lock.json * fix: correct typo in doc Co-authored-by: Nicholas Carrigan (he/him) <nhcarrigan@gmail.com> * fix: Replace favicon, Gitter => Discord Signed-off-by: nhcarrigan <nhcarrigan@gmail.com> * fix: add extra linting guidance to package.json * Ignore contributor app Signed-off-by: nhcarrigan <nhcarrigan@gmail.com> * fix: revert linting rules for client * fix: add skip_preflight_check=true for tests Co-authored-by: Kristofer Koishigawa <scissorsneedfoodtoo@gmail.com> Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com> Co-authored-by: Kris Koishigawa <scissorsneedfoodtoo@gmail.com> Co-authored-by: Nicholas Carrigan (he/him) <nhcarrigan@gmail.com>
174 lines
4.5 KiB
JavaScript
174 lines
4.5 KiB
JavaScript
const { Octokit } = require('@octokit/rest');
|
|
const _cliProgress = require('cli-progress');
|
|
|
|
const {
|
|
github: { owner, secret }
|
|
} = require('../config');
|
|
|
|
const octokit = new Octokit({ auth: secret });
|
|
|
|
const { getRange, getCount } = require('./pr-stats');
|
|
|
|
/* eslint-disable camelcase */
|
|
const prsPaginate = async (
|
|
repo,
|
|
base,
|
|
method,
|
|
firstPR,
|
|
lastPR,
|
|
prPropsToGet
|
|
) => {
|
|
let methodProps = {
|
|
owner,
|
|
repo,
|
|
state: 'open',
|
|
sort: 'created',
|
|
direction: 'asc',
|
|
page: 1,
|
|
per_page: 100
|
|
};
|
|
|
|
if (base) {
|
|
methodProps = { ...methodProps, base };
|
|
}
|
|
|
|
const prFilter = (prs, first, last, prPropsToGet) => {
|
|
const filtered = [];
|
|
for (let pr of prs) {
|
|
if (pr.number >= first && pr.number <= last) {
|
|
const propsObj = prPropsToGet.reduce((obj, prop) => {
|
|
obj[prop] = pr[prop];
|
|
return obj;
|
|
}, {});
|
|
filtered.push(propsObj);
|
|
}
|
|
if (pr.number >= last) {
|
|
done = true;
|
|
return filtered;
|
|
}
|
|
}
|
|
return filtered;
|
|
};
|
|
|
|
// will be true when lastPR is seen in paginated results
|
|
let done = false;
|
|
let response = await method(methodProps);
|
|
console.log('x-ratelimit-remaining:', response.meta['x-ratelimit-remaining']);
|
|
let { data } = response;
|
|
data = prFilter(data, firstPR, lastPR, prPropsToGet);
|
|
while (octokit.hasNextPage(response) && !done) {
|
|
response = await octokit.getNextPage(response);
|
|
console.log(
|
|
'x-ratelimit-remaining:',
|
|
response.meta['x-ratelimit-remaining']
|
|
);
|
|
let dataFiltered = prFilter(response.data, firstPR, lastPR, prPropsToGet);
|
|
data = data.concat(dataFiltered);
|
|
// progressBar.increment(dataFiltered.length);
|
|
}
|
|
return data;
|
|
};
|
|
|
|
const getUserInput = async (repo, base, rangeType = '') => {
|
|
let data, firstPR, lastPR;
|
|
if (rangeType === 'all') {
|
|
data = await getRange(repo, base).then(data => data);
|
|
firstPR = data[0];
|
|
lastPR = data[1];
|
|
} else {
|
|
let [type, start, end] = process.argv.slice(2);
|
|
data = await getRange(repo, base).then(data => data);
|
|
firstPR = data[0];
|
|
lastPR = data[1];
|
|
if (type !== 'all' && type !== 'range') {
|
|
throw 'Please specify either all or range for 1st arg.';
|
|
}
|
|
if (type === 'range') {
|
|
start = parseInt(start, 10);
|
|
end = parseInt(end, 10);
|
|
if (!start || !end) {
|
|
throw 'Specify both a starting PR # (2nd arg) and ending PR # (3rd arg).';
|
|
}
|
|
if (start > end) {
|
|
throw 'Starting PR # must be less than or equal to end PR #.';
|
|
}
|
|
if (start < firstPR) {
|
|
throw `Starting PR # can not be less than first open PR # (${firstPR})`;
|
|
}
|
|
firstPR = start;
|
|
if (end > lastPR) {
|
|
throw `Ending PR # can not be greater than last open PR # (${lastPR})`;
|
|
}
|
|
lastPR = end;
|
|
}
|
|
}
|
|
// A null value for firstPR or lastPR indicates the repo had no open PRs
|
|
if (firstPR === null || lastPR === null) {
|
|
return { totalPRs: 0, firstPR, lastPR };
|
|
}
|
|
const totalPRs = await getCount(repo, base).then(data => data);
|
|
return { totalPRs, firstPR, lastPR };
|
|
};
|
|
|
|
const getPRs = async (repo, base, totalPRs, firstPR, lastPR, prPropsToGet) => {
|
|
let progressText = `Retrieve PRs (${firstPR}-${lastPR}) [{bar}] `;
|
|
progressText += '{percentage}% | Elapsed Time: {duration_formatted} ';
|
|
progressText += '| ETA: {eta_formatted}';
|
|
const getPRsBar = new _cliProgress.Bar(
|
|
{
|
|
format: progressText,
|
|
etaBuffer: 50
|
|
},
|
|
_cliProgress.Presets.shades_classic
|
|
);
|
|
// getPRsBar.start(totalPRs, 0);
|
|
let openPRs = await prsPaginate(
|
|
repo,
|
|
base,
|
|
octokit.pulls.list,
|
|
firstPR,
|
|
lastPR,
|
|
prPropsToGet,
|
|
getPRsBar
|
|
);
|
|
// getPRsBar.update(totalPRs);
|
|
// getPRsBar.stop();
|
|
console.log(`# of PRs retrieved: ${openPRs.length}`);
|
|
return { firstPR, lastPR, openPRs };
|
|
};
|
|
|
|
const filesPaginate = async (repo, number) => {
|
|
let methodProps = {
|
|
owner,
|
|
state: 'open',
|
|
sort: 'created',
|
|
direction: 'asc',
|
|
page: 1,
|
|
per_page: 100
|
|
};
|
|
|
|
if (repo) {
|
|
methodProps = { ...methodProps, repo };
|
|
}
|
|
|
|
let response = await octokit.pulls.listFiles({
|
|
number,
|
|
...methodProps
|
|
});
|
|
|
|
let { data } = response;
|
|
while (octokit.hasNextPage(response)) {
|
|
response = await octokit.getNextPage(response);
|
|
let { data: moreData } = response;
|
|
data = data.concat(moreData);
|
|
}
|
|
return data;
|
|
};
|
|
|
|
const getFiles = async (repo, number) => await filesPaginate(repo, number);
|
|
|
|
const getFilenames = async (repo, number) =>
|
|
(await getFiles(repo, number)).map(({ filename }) => filename);
|
|
|
|
module.exports = { getPRs, getUserInput, getFiles, getFilenames };
|