feat(dev-infra): support --no-branch-prompt to suppress the merge tool branch target confirmation (#40528)

Add support for a `--no-branch-prompt` flag for the `ng-dev pr merge` tool.  This
flag enables suppression of the confirmation prompt for which branches the specified
PR will merge into.

PR Close #40528
This commit is contained in:
Joey Perrott
2021-01-22 14:05:28 -08:00
committed by Jessica Janiuk
parent 1f53301fd3
commit 2980d85b8c
5 changed files with 141 additions and 87 deletions
+2 -2
View File
@@ -11,7 +11,7 @@ import * as yargs from 'yargs';
import {CheckTargetBranchesModule} from './check-target-branches/cli';
import {CheckoutCommandModule} from './checkout/cli';
import {buildDiscoverNewConflictsCommand, handleDiscoverNewConflictsCommand} from './discover-new-conflicts/cli';
import {buildMergeCommand, handleMergeCommand} from './merge/cli';
import {MergeCommandModule} from './merge/cli';
import {buildRebaseCommand, handleRebaseCommand} from './rebase/cli';
/** Build the parser for pull request commands. */
@@ -19,7 +19,6 @@ export function buildPrParser(localYargs: yargs.Argv) {
return localYargs.help()
.strict()
.demandCommand()
.command('merge <pr-number>', 'Merge pull requests', buildMergeCommand, handleMergeCommand)
.command(
'discover-new-conflicts <pr-number>',
'Check if a pending PR causes new conflicts for other pending PRs',
@@ -27,6 +26,7 @@ export function buildPrParser(localYargs: yargs.Argv) {
.command(
'rebase <pr-number>', 'Rebase a pending PR and push the rebased commits back to Github',
buildRebaseCommand, handleRebaseCommand)
.command(MergeCommandModule)
.command(CheckoutCommandModule)
.command(CheckTargetBranchesModule);
}
+29 -10
View File
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Arguments, Argv} from 'yargs';
import {Arguments, Argv, CommandModule} from 'yargs';
import {addGithubTokenOption} from '../../utils/git/github-yargs';
@@ -15,17 +15,36 @@ import {mergePullRequest} from './index';
/** The options available to the merge command via CLI. */
export interface MergeCommandOptions {
githubToken: string;
'pr-number': number;
pr: number;
branchPrompt: boolean;
}
/** Builds the options for the merge command. */
export function buildMergeCommand(yargs: Argv): Argv<MergeCommandOptions> {
return addGithubTokenOption(yargs).help().strict().positional(
'pr-number', {demandOption: true, type: 'number'});
/** Builds the command. */
function builder(yargs: Argv) {
return addGithubTokenOption(yargs)
.help()
.strict()
.positional('pr', {
demandOption: true,
type: 'number',
description: 'The PR to be merged.',
})
.option('branch-prompt' as 'branchPrompt', {
type: 'boolean',
default: true,
description: 'Whether to prompt to confirm the branches a PR will merge into.',
});
}
/** Handles the merge command. i.e. performs the merge of a specified pull request. */
export async function handleMergeCommand(
{'pr-number': pr, githubToken}: Arguments<MergeCommandOptions>) {
await mergePullRequest(pr, githubToken);
/** Handles the command. */
async function handler({pr, githubToken, branchPrompt}: Arguments<MergeCommandOptions>) {
await mergePullRequest(pr, githubToken, {branchPrompt});
}
/** yargs command module describing the command. */
export const MergeCommandModule: CommandModule<{}, MergeCommandOptions> = {
handler,
builder,
command: 'merge <pr>',
describe: 'Merge a PR into its targeted branches.',
};
+6 -12
View File
@@ -14,7 +14,7 @@ import {GITHUB_TOKEN_GENERATE_URL} from '../../utils/git/github-urls';
import {GitClient} from '../../utils/git/index';
import {loadAndValidateConfig, MergeConfigWithRemote} from './config';
import {MergeResult, MergeStatus, PullRequestMergeTask} from './task';
import {MergeResult, MergeStatus, PullRequestMergeTask, PullRequestMergeTaskFlags} from './task';
/**
* Merges a given pull request based on labels configured in the given merge configuration.
@@ -30,13 +30,12 @@ import {MergeResult, MergeStatus, PullRequestMergeTask} from './task';
* @param config Configuration for merging pull requests.
*/
export async function mergePullRequest(
prNumber: number, githubToken: string, projectRoot: string = getRepoBaseDir(),
config?: MergeConfigWithRemote) {
prNumber: number, githubToken: string, flags: PullRequestMergeTaskFlags) {
// Set the environment variable to skip all git commit hooks triggered by husky. We are unable to
// rely on `--no-verify` as some hooks still run, notably the `prepare-commit-msg` hook.
process.env['HUSKY'] = '0';
const api = await createPullRequestMergeTask(githubToken, projectRoot, config);
const api = await createPullRequestMergeTask(githubToken, flags);
// Perform the merge. Force mode can be activated through a command line flag.
// Alternatively, if the merge fails with non-fatal failures, the script
@@ -128,13 +127,8 @@ export async function mergePullRequest(
* and optional explicit configuration. An explicit configuration can be specified
* when the merge script is used outside of a `ng-dev` configured repository.
*/
async function createPullRequestMergeTask(
githubToken: string, projectRoot: string, explicitConfig?: MergeConfigWithRemote) {
if (explicitConfig !== undefined) {
const git = new GitClient(githubToken, {github: explicitConfig.remote}, projectRoot);
return new PullRequestMergeTask(explicitConfig, git);
}
async function createPullRequestMergeTask(githubToken: string, flags: PullRequestMergeTaskFlags) {
const projectRoot = getRepoBaseDir();
const devInfraConfig = getConfig();
const git = new GitClient(githubToken, devInfraConfig, projectRoot);
const {config, errors} = await loadAndValidateConfig(devInfraConfig, git.github);
@@ -150,5 +144,5 @@ async function createPullRequestMergeTask(
config!.remote = devInfraConfig.github;
// We can cast this to a merge config with remote because we always set the
// remote above.
return new PullRequestMergeTask(config! as MergeConfigWithRemote, git);
return new PullRequestMergeTask(config! as MergeConfigWithRemote, git, flags);
}
+18 -2
View File
@@ -34,13 +34,28 @@ export interface MergeResult {
failure?: PullRequestFailure;
}
export interface PullRequestMergeTaskFlags {
branchPrompt: boolean;
}
const defaultPullRequestMergeTaskFlags: PullRequestMergeTaskFlags = {
branchPrompt: true,
};
/**
* Class that accepts a merge script configuration and Github token. It provides
* a programmatic interface for merging multiple pull requests based on their
* labels that have been resolved through the merge script configuration.
*/
export class PullRequestMergeTask {
constructor(public config: MergeConfigWithRemote, public git: GitClient) {}
private flags: PullRequestMergeTaskFlags;
constructor(
public config: MergeConfigWithRemote, public git: GitClient,
flags: Partial<PullRequestMergeTaskFlags>) {
// Update flags property with the provided flags values as patches to the default flag values.
this.flags = {...defaultPullRequestMergeTaskFlags, ...flags};
}
/**
* Merges the given pull request and pushes it upstream.
@@ -79,7 +94,8 @@ export class PullRequestMergeTask {
}
if (!await promptConfirm(getTargettedBranchesConfirmationPromptMessage(pullRequest))) {
if (this.flags.branchPrompt &&
!await promptConfirm(getTargettedBranchesConfirmationPromptMessage(pullRequest))) {
return {status: MergeStatus.USER_ABORTED};
}