|
#!/usr/bin/env node |
|
|
|
const util = require('util'); |
|
const exec = util.promisify(require('child_process').exec); |
|
|
|
/** |
|
* Retrieve any assigned PRs for the user/project combo. |
|
* |
|
* @param {string} ghRepo Repository using the [HOST/]OWNER/REPO format |
|
* @param {string} ghUser |
|
*/ |
|
async function fetchAssigned(ghUser, ghRepo) { |
|
const fields = [ |
|
"id", |
|
"number", |
|
"author", |
|
"title", |
|
"reviewRequests", |
|
"assignees", |
|
"state", |
|
"url", |
|
]; |
|
const cmd = `gh pr list -s open -R ${ghRepo} --json ${fields.join(',')}`; |
|
console.log(`runnning command: "${cmd}"`); |
|
const {stdout, stderr} = await exec(cmd); |
|
if (stderr) { |
|
throw new Error(`Could not fetch PRs for user/repo: ${stderr}`); |
|
} |
|
|
|
const res = JSON.parse(stdout.trim()); |
|
// console.dir(res, {depth: 3}) |
|
|
|
const isGhUserReducer = (acc, val) => `${val.login || val.name}`.toUpperCase() === `${ghUser.toUpperCase()}` || acc; |
|
return res.filter(x => { |
|
const isReviewRequested = x.reviewRequests.reduce(isGhUserReducer, false); |
|
const isAssignee = x.assignees.reduce(isGhUserReducer, false); |
|
return isReviewRequested || isAssignee; |
|
}); |
|
} |
|
|
|
/** |
|
* |
|
* @param {string} ghUser |
|
* @param {string} ghRepo Repository using the [HOST/]OWNER/REPO format |
|
* @param {string} pr [<number> | <url> | <branch>] |
|
*/ |
|
async function removeUserFromPr(ghUser, ghRepo, prNumber) { |
|
const cmd = `gh pr edit ${prNumber} -R "${ghRepo}" --remove-assignee ${ghUser} --remove-reviewer ${ghUser}` |
|
|
|
console.log(`runnning command: "${cmd}"`); |
|
|
|
const {stdout, stderr} = await exec(cmd); |
|
if (stderr) { |
|
throw new Error(`Could not remove user from pr: ${stderr}`); |
|
} |
|
} |
|
|
|
|
|
/** |
|
* EXAMPLE USEAGE: `./gh-pr-cleanup.js facebook/react zucksucks` |
|
*/ |
|
(async ({ghRepo, ghUser}) => { |
|
let assignedPrs = []; |
|
try { |
|
console.log(`Retrieving all open PR's assigned to ${ghUser} in project ${ghRepo}`); |
|
assignedPrs = await fetchAssigned(ghUser, ghRepo); |
|
// console.log(JSON.stringify(assignedPrs, null, '')); |
|
} catch(e) { |
|
console.error(e); |
|
} |
|
|
|
console.log(`Removing ${ghUser} from ${assignedPrs.length} in repo ${ghRepo}`); |
|
|
|
await Promise.all( |
|
assignedPrs.map(async (pr) => { |
|
try { |
|
await removeUserFromPr(ghUser, ghRepo, pr.number); |
|
} catch (e) { |
|
console.warn(`Could not remove user "${ghUser}" from ${pr.url}! Reason: ${e}`); |
|
} |
|
}) |
|
); |
|
})({ |
|
ghRepo: process.argv.length > 2 ? process.argv[2] : '<org>/<project>', |
|
ghUser: process.argv.length > 3 ? process.argv[3] : '<gh-username>', |
|
}); |
|
|