grafana/toolkit: Modify close milestone task to remove label from more than 100 pull requests and add dry run option (#25108)

* Fix close milestone to remove label from all the required pull requests

There used to be a limit to 100 pull requests.

* Add dry run option in close-milestone task
This commit is contained in:
Sofia Papagiannaki 2020-05-26 17:26:16 +03:00 committed by GitHub
parent 170abf2e3d
commit 139be3d7ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 35 deletions

View File

@ -104,6 +104,7 @@ export const run = (includeInternalScripts = false) => {
program program
.command('close-milestone') .command('close-milestone')
.option('-m, --milestone <milestone>', 'Specify milestone') .option('-m, --milestone <milestone>', 'Specify milestone')
.option('--dryRun', 'Only simulate actions')
.description('Helps ends a milestone by removing the cherry-pick label and closing it') .description('Helps ends a milestone by removing the cherry-pick label and closing it')
.action(async cmd => { .action(async cmd => {
if (!cmd.milestone) { if (!cmd.milestone) {
@ -113,6 +114,7 @@ export const run = (includeInternalScripts = false) => {
await execTask(closeMilestoneTask)({ await execTask(closeMilestoneTask)({
milestone: cmd.milestone, milestone: cmd.milestone,
dryRun: !!cmd.dryRun,
}); });
}); });

View File

@ -3,9 +3,10 @@ import GithubClient from '../utils/githubClient';
interface CloseMilestoneOptions { interface CloseMilestoneOptions {
milestone: string; milestone: string;
dryRun: boolean;
} }
const closeMilestoneTaskRunner: TaskRunner<CloseMilestoneOptions> = async ({ milestone }) => { const closeMilestoneTaskRunner: TaskRunner<CloseMilestoneOptions> = async ({ milestone, dryRun }) => {
const githubClient = new GithubClient({ required: true }); const githubClient = new GithubClient({ required: true });
const cherryPickLabel = 'cherry-pick needed'; const cherryPickLabel = 'cherry-pick needed';
@ -16,6 +17,10 @@ const closeMilestoneTaskRunner: TaskRunner<CloseMilestoneOptions> = async ({ mil
return; return;
} }
if (dryRun) {
console.log('dry run is enabled');
}
const milestoneRes = await client.get(`/milestones/${milestone}`, {}); const milestoneRes = await client.get(`/milestones/${milestone}`, {});
const milestoneState = milestoneRes.data.state; const milestoneState = milestoneRes.data.state;
@ -27,46 +32,60 @@ const closeMilestoneTaskRunner: TaskRunner<CloseMilestoneOptions> = async ({ mil
console.log('fetching issues/PRs of the milestone ⏬'); console.log('fetching issues/PRs of the milestone ⏬');
// Get all the issues/PRs with the label cherry-pick let totalIssues = 0;
// Every pull request is actually an issue
const issuesRes = await client.get('/issues', {
params: {
state: 'closed',
labels: cherryPickLabel,
per_page: 100,
milestone: milestone,
},
});
if (issuesRes.data.length < 1) { while (true) {
console.log('no issues to remove label from'); // Get first 100 issues/PRs with the label cherry-pick
} else { // Every pull request is actually an issue
console.log(`found ${issuesRes.data.length} issues to remove the cherry-pick label from 🔎`); const issuesRes = await client.get('/issues', {
} params: {
state: 'closed',
labels: cherryPickLabel,
per_page: 100,
milestone: milestone,
},
});
for (const issue of issuesRes.data) { if (issuesRes.data.length < 1) {
// the reason for using stdout.write is for achieving 'action -> result' on break;
// the same line }
process.stdout.write(`🔧removing label from issue #${issue.number} 🗑...`);
const resDelete = await client.delete(`/issues/${issue.number}/labels/${cherryPickLabel}`, {}); const comparativeStr = totalIssues === 0 ? ' ' : ' more ';
if (resDelete.status === 200) { console.log(`found ${issuesRes.data.length}${comparativeStr}issues to remove the cherry-pick label from 🔎`);
process.stdout.write('done ✅\n'); totalIssues += issuesRes.data.length;
} else {
console.log('failed ❌'); for (const issue of issuesRes.data) {
// the reason for using stdout.write is for achieving 'action -> result' on
// the same line
process.stdout.write(`🔧removing label from issue #${issue.number} 🗑...`);
if (!dryRun) {
const resDelete = await client.delete(`/issues/${issue.number}/labels/${cherryPickLabel}`, {});
if (resDelete.status === 200) {
process.stdout.write('done ✅\n');
} else {
console.log('failed ❌');
}
}
} }
} }
console.log(`cleaned up ${issuesRes.data.length} issues/prs ⚡️`); if (totalIssues === 0) {
console.log('no issues to remove label from');
const resClose = await client.patch(`/milestones/${milestone}`, {
state: 'closed',
});
if (resClose.status === 200) {
console.log('milestone closed 🙌');
} else { } else {
console.log('failed to close the milestone, response:'); console.log(`cleaned up ${totalIssues} issues/prs ⚡️`);
console.log(resClose); }
if (!dryRun) {
const resClose = await client.patch(`/milestones/${milestone}`, {
state: 'closed',
});
if (resClose.status === 200) {
console.log('milestone closed 🙌');
} else {
console.log('failed to close the milestone, response:');
console.log(resClose);
}
} }
}; };