fleet/website/api/helpers/github-automations/get-is-pr-preapproved.js

100 lines
4.1 KiB
JavaScript
Vendored

module.exports = {
friendlyName: 'Get "is PR preapproved?"',
description: '',
inputs: {
repo: { type: 'string', example: 'fleet', required: true, isIn: ['fleet', 'confidential']},
prNumber: { type: 'number', example: 382, required: true },
githubUserToCheck: { type: 'string', example: 'mikermcneil', description: 'If excluded, then this returns `true` if all of the PRs changed paths are preapproved for SOMEONE.' },
isGithubUserMaintainerOrDoesntMatter: { type: 'boolean', required: true, description: 'Whether (a) the user is a maintainer, or (b) it even matters for this check whether the user is a maintainer.' },// FUTURE: « this could be replaced with an extra GitHub API call herein, but doesn't seem worth it
},
exits: {
success: {
outputFriendlyName: 'Is PR preapproved?',
outputDescription: 'Whether the provided GitHub user is the DRI for all changed paths.',
outputType: 'boolean',
},
},
fn: async function ({repo, prNumber, githubUserToCheck, isGithubUserMaintainerOrDoesntMatter}) {
require('assert')(sails.config.custom.githubRepoDRIByPath);
require('assert')(sails.config.custom.confidentialGithubRepoDRIByPath);
require('assert')(sails.config.custom.fleetMdmGitopsGithubRepoDRIByPath);
require('assert')(sails.config.custom.githubAccessToken);
let DRI_BY_PATH = sails.config.custom.githubRepoDRIByPath;
if (repo === 'confidential') {
DRI_BY_PATH = sails.config.custom.confidentialGithubRepoDRIByPath;
}
if (repo === 'fleet-mdm-gitops') {
DRI_BY_PATH = sails.config.custom.fleetMdmGitopsGithubRepoDRIByPath;
}
let owner = 'fleetdm';
let baseHeaders = {
'User-Agent': 'Fleet auto-approve',
'Authorization': `token ${sails.config.custom.githubAccessToken}`
};
// Check the PR's author versus the intersection of DRIs for all changed files.
return await sails.helpers.flow.build(async()=>{
let isDRIForAllChangedPathsStill = false;
// [?] https://docs.github.com/en/rest/reference/pulls#list-pull-requests-files
let changedPaths = _.pluck(await sails.helpers.http.get(`https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/files`, {
per_page: 100,//eslint-disable-line camelcase
}, baseHeaders).retry(), 'filename');// (don't worry, it's the whole path, not the filename)
isDRIForAllChangedPathsStill = _.all(changedPaths, (changedPath)=>{
changedPath = changedPath.replace(/\/+$/,'');// « trim trailing slashes, just in case (b/c otherwise could loop forever)
// sails.log.verbose(`…checking DRI of changed path "${changedPath}"`);
let selfMergers = DRI_BY_PATH[changedPath] ? [].concat(DRI_BY_PATH[changedPath]) : [];// « ensure array
if (!githubUserToCheck && selfMergers.length >= 1) {// « not checking a user, so just make sure all these paths are preapproved for SOMEONE
return true;
}
if (githubUserToCheck && (selfMergers.includes(githubUserToCheck.toLowerCase()) || (isGithubUserMaintainerOrDoesntMatter && selfMergers.includes('*')))) {
return true;
}//•
let numRemainingPathsToCheck = changedPath.split('/').length;
while (numRemainingPathsToCheck > 0) {
let ancestralPath = changedPath.split('/').slice(0, -1 * numRemainingPathsToCheck).join('/');
// sails.log.verbose(`…checking DRI of ancestral path "${ancestralPath}" for changed path`);
let selfMergers = DRI_BY_PATH[ancestralPath] ? [].concat(DRI_BY_PATH[ancestralPath]) : [];// « ensure array
if (!githubUserToCheck && selfMergers.length >= 1) {// « not checking a user, so just make sure all these paths are preapproved for SOMEONE
return true;
}
if (githubUserToCheck && (selfMergers.includes(githubUserToCheck.toLowerCase()) || (isGithubUserMaintainerOrDoesntMatter && selfMergers.includes('*')))) {
return true;
}//•
numRemainingPathsToCheck--;
}//∞
});//∞
if (isDRIForAllChangedPathsStill && changedPaths.length < 100) {
return true;
} else {
return false;
}
});
}
};