renovate/lib/api/gh-got-wrapper.js
Rhys Arkins 9a97a5901e feat: use parse-link-header library (github) (#970)
Now will work with any GitHub host, instead of just api.github.com
2017-10-17 20:44:40 +02:00

103 lines
2.8 KiB
JavaScript

const logger = require('../logger');
const ghGot = require('gh-got');
const parseLinkHeader = require('parse-link-header');
// istanbul ignore next
function sleep(ms) {
// eslint-disable-next-line promise/avoid-new
return new Promise(resolve => setTimeout(resolve, ms));
}
async function get(path, opts, retries = 5) {
try {
if (appMode) {
/* eslint-disable no-param-reassign */
opts = Object.assign({}, opts);
const appAccept = 'application/vnd.github.machine-man-preview+json';
opts.headers = Object.assign(
{},
{
accept: appAccept,
'user-agent': 'https://github.com/singapore/renovate',
},
opts.headers
);
if (opts.headers.accept !== appAccept) {
opts.headers.accept = `${appAccept}, ${opts.headers.accept}`;
}
}
const res = await ghGot(path, opts);
if (opts && opts.paginate) {
// Check if result is paginated
const linkHeader = parseLinkHeader(res.headers.link);
if (linkHeader && linkHeader.next) {
res.body = res.body.concat(
(await get(linkHeader.next.url, opts, retries)).body
);
}
}
return res;
} catch (err) {
if (err.statusCode >= 500 && err.statusCode < 600 && retries > 0) {
logger.info(
{ statusCode: err.statusCode, message: err.message },
`Retrying request`
);
// istanbul ignore if
if (process.env.NODE_ENV !== 'test') {
await sleep(5000 / retries);
}
return get(path, opts, retries - 1);
}
if (
retries > 0 &&
err.statusCode === 403 &&
err.message &&
err.message.indexOf('You have triggered an abuse detection mechanism') ===
0
) {
logger.info(
{ statusCode: err.statusCode, message: err.message },
`Retrying request`
);
// istanbul ignore if
if (process.env.NODE_ENV !== 'test') {
await sleep(180000 / (retries * retries));
}
return get(path, opts, retries - 1);
}
if (
err.statusCode === 403 &&
err.message &&
err.message.indexOf('rate limit exceeded') !== -1
) {
if (retries > 0) {
logger.info(
{ statusCode: err.statusCode, message: err.message },
`Retrying request`
);
// istanbul ignore if
if (process.env.NODE_ENV !== 'test') {
await sleep(60000 / (retries * retries));
}
return get(path, opts, retries - 1);
}
logger.info({ headers: err.headers }, 'Failed retrying request');
}
throw err;
}
}
const helpers = ['get', 'post', 'put', 'patch', 'head', 'delete'];
for (const x of helpers) {
get[x] = (url, opts) =>
get(url, Object.assign({}, opts, { method: x.toUpperCase() }));
}
let appMode = false;
get.setAppMode = function setAppMode(val) {
appMode = val;
};
module.exports = get;