From 43006bcc456c7561c063b700c4ee2fedf44c60e0 Mon Sep 17 00:00:00 2001 From: Joey Perrott Date: Thu, 26 Mar 2020 10:45:09 -0700 Subject: [PATCH] feat(dev-infra): standard CLI commands using yargs (#36326) Creates a standard model for CLI commands provided by ng-dev. Allows for us to have any of the tools/scripts extend to be included in the ng-dev command, or be standalone using the same yargs parser. PR Close #36326 --- dev-infra/BUILD.bazel | 3 ++ dev-infra/cli.ts | 35 ++++++---------- dev-infra/commit-message/BUILD.bazel | 4 ++ dev-infra/commit-message/cli.ts | 20 ++++++++++ dev-infra/commit-message/validate-file.ts | 21 ++++++++++ dev-infra/pullapprove/BUILD.bazel | 3 ++ dev-infra/pullapprove/cli.ts | 19 +++++++++ dev-infra/ts-circular-dependencies/index.ts | 44 +++++++++++++-------- package.json | 5 ++- 9 files changed, 114 insertions(+), 40 deletions(-) create mode 100644 dev-infra/commit-message/cli.ts create mode 100644 dev-infra/commit-message/validate-file.ts create mode 100644 dev-infra/pullapprove/cli.ts diff --git a/dev-infra/BUILD.bazel b/dev-infra/BUILD.bazel index 60d60aa480..57897870bf 100644 --- a/dev-infra/BUILD.bazel +++ b/dev-infra/BUILD.bazel @@ -10,8 +10,11 @@ ts_library( deps = [ "//dev-infra/commit-message", "//dev-infra/pullapprove", + "//dev-infra/ts-circular-dependencies", "//dev-infra/utils:config", "@npm//@types/node", + "@npm//@types/yargs", + "@npm//yargs", ], ) diff --git a/dev-infra/cli.ts b/dev-infra/cli.ts index 3aa6d2e733..0c30ac4ae6 100644 --- a/dev-infra/cli.ts +++ b/dev-infra/cli.ts @@ -6,26 +6,17 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -import {readFileSync} from 'fs'; -import {join} from 'path'; -import {verify} from './pullapprove/verify'; -import {validateCommitMessage} from './commit-message/validate'; -import {getRepoBaseDir} from './utils/config'; +import * as yargs from 'yargs'; +import {tsCircularDependenciesBuilder} from './ts-circular-dependencies/index'; +import {buildPullapproveParser} from './pullapprove/cli'; +import {buildCommitMessageParser} from './commit-message/cli'; -const args = process.argv.slice(2); - - -// TODO(josephperrott): Set up proper cli flag/command handling -switch (args[0]) { - case 'pullapprove:verify': - verify(); - break; - case 'commit-message:pre-commit-validate': - const commitMessage = readFileSync(join(getRepoBaseDir(), '.git/COMMIT_EDITMSG'), 'utf8'); - if (validateCommitMessage(commitMessage)) { - console.info('√ Valid commit message'); - } - break; - default: - console.info('No commands were matched'); -} +yargs.scriptName('ng-dev') + .demandCommand() + .recommendCommands() + .command('ts-circular-deps ', '', tsCircularDependenciesBuilder) + .command('pullapprove ', '', buildPullapproveParser) + .command('commit-message ', '', buildCommitMessageParser) + .wrap(120) + .strict() + .parse(); diff --git a/dev-infra/commit-message/BUILD.bazel b/dev-infra/commit-message/BUILD.bazel index e6029084c3..fe11b49270 100644 --- a/dev-infra/commit-message/BUILD.bazel +++ b/dev-infra/commit-message/BUILD.bazel @@ -4,15 +4,19 @@ load("@npm_bazel_typescript//:index.bzl", "ts_library") ts_library( name = "commit-message", srcs = [ + "cli.ts", "config.ts", "validate.ts", + "validate-file.ts", ], module_name = "@angular/dev-infra-private/commit-message", visibility = ["//dev-infra:__subpackages__"], deps = [ "//dev-infra/utils:config", "@npm//@types/node", + "@npm//@types/yargs", "@npm//tslib", + "@npm//yargs", ], ) diff --git a/dev-infra/commit-message/cli.ts b/dev-infra/commit-message/cli.ts new file mode 100644 index 0000000000..c4443396be --- /dev/null +++ b/dev-infra/commit-message/cli.ts @@ -0,0 +1,20 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import * as yargs from 'yargs'; +import {validateFile} from './validate-file'; + +/** Build the parser for the commit-message commands. */ +export function buildCommitMessageParser(localYargs: yargs.Argv) { + return localYargs.help().strict().command( + 'pre-commit-validate', 'Validate the most recent commit message', {}, + () => { validateFile('.git/COMMIT_EDITMSG'); }); +} + +if (require.main == module) { + buildCommitMessageParser(yargs).parse(); +} diff --git a/dev-infra/commit-message/validate-file.ts b/dev-infra/commit-message/validate-file.ts new file mode 100644 index 0000000000..1bac796df1 --- /dev/null +++ b/dev-infra/commit-message/validate-file.ts @@ -0,0 +1,21 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {readFileSync} from 'fs'; +import {join} from 'path'; + +import {getRepoBaseDir} from '../utils/config'; + +import {validateCommitMessage} from './validate'; + +/** Validate commit message at the provided file path. */ +export function validateFile(filePath: string) { + const commitMessage = readFileSync(join(getRepoBaseDir(), filePath), 'utf8'); + if (validateCommitMessage(commitMessage)) { + console.info('√ Valid commit message'); + } +} diff --git a/dev-infra/pullapprove/BUILD.bazel b/dev-infra/pullapprove/BUILD.bazel index 9d1ffb6d7d..6b341553ae 100644 --- a/dev-infra/pullapprove/BUILD.bazel +++ b/dev-infra/pullapprove/BUILD.bazel @@ -3,6 +3,7 @@ load("@npm_bazel_typescript//:index.bzl", "ts_library") ts_library( name = "pullapprove", srcs = [ + "cli.ts", "group.ts", "logging.ts", "parse-yaml.ts", @@ -16,9 +17,11 @@ ts_library( "@npm//@types/node", "@npm//@types/shelljs", "@npm//@types/yaml", + "@npm//@types/yargs", "@npm//minimatch", "@npm//shelljs", "@npm//tslib", "@npm//yaml", + "@npm//yargs", ], ) diff --git a/dev-infra/pullapprove/cli.ts b/dev-infra/pullapprove/cli.ts new file mode 100644 index 0000000000..d1036e644e --- /dev/null +++ b/dev-infra/pullapprove/cli.ts @@ -0,0 +1,19 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import * as yargs from 'yargs'; +import {verify} from './verify'; + +/** Build the parser for the pullapprove commands. */ +export function buildPullapproveParser(localYargs: yargs.Argv) { + return localYargs.help().strict().demandCommand().command( + 'verify', 'Verify the pullapprove config', {}, () => verify()); +} + +if (require.main === module) { + buildPullapproveParser(yargs).parse(); +} diff --git a/dev-infra/ts-circular-dependencies/index.ts b/dev-infra/ts-circular-dependencies/index.ts index f4a5cb3591..50f8a903b7 100644 --- a/dev-infra/ts-circular-dependencies/index.ts +++ b/dev-infra/ts-circular-dependencies/index.ts @@ -19,22 +19,30 @@ import {compareGoldens, convertReferenceChainToGolden, Golden} from './golden'; import {convertPathToForwardSlash} from './file_system'; import {loadTestConfig, CircularDependenciesTestConfig} from './config'; -if (require.main === module) { - const {_: command, config: configArg, warnings} = - yargs.help() - .strict() - .command('check', 'Checks if the circular dependencies have changed.') - .command('approve', 'Approves the current circular dependencies.') - .demandCommand() - .option( - 'config', - {type: 'string', demandOption: true, description: 'Path to the configuration file.'}) - .option('warnings', {type: 'boolean', description: 'Prints all warnings.'}) - .argv; - const configPath = isAbsolute(configArg) ? configArg : resolve(configArg); - const config = loadTestConfig(configPath); - const isApprove = command.includes('approve'); - process.exit(main(isApprove, config, warnings)); + +export function tsCircularDependenciesBuilder(localYargs: yargs.Argv) { + return localYargs.help() + .strict() + .demandCommand() + .option( + 'config', + {type: 'string', demandOption: true, description: 'Path to the configuration file.'}) + .option('warnings', {type: 'boolean', description: 'Prints all warnings.'}) + .command( + 'check', 'Checks if the circular dependencies have changed.', {}, + (argv: yargs.Arguments) => { + const {config: configArg, warnings} = argv; + const configPath = isAbsolute(configArg) ? configArg : resolve(configArg); + const config = loadTestConfig(configPath); + process.exit(main(false, config, warnings)); + }) + .command( + 'approve', 'Approves the current circular dependencies.', {}, (argv: yargs.Arguments) => { + const {config: configArg, warnings} = argv; + const configPath = isAbsolute(configArg) ? configArg : resolve(configArg); + const config = loadTestConfig(configPath); + process.exit(main(true, config, warnings)); + }); } /** @@ -126,3 +134,7 @@ function getRelativePath(baseDir: string, path: string) { function convertReferenceChainToString(chain: ReferenceChain) { return chain.join(' → '); } + +if (require.main === module) { + tsCircularDependenciesBuilder(yargs).parse(); +} diff --git a/package.json b/package.json index 7aca79ee8b..c6f06d854d 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,10 @@ "tslint": "tsc -p tools/tsconfig.json && tslint -c tslint.json \"+(packages|modules|scripts|tools)/**/*.+(js|ts)\"", "public-api:check": "node goldens/public-api/manage.js test", "public-api:update": "node goldens/public-api/manage.js accept", - "ts-circular-deps": "ts-node dev-infra/ts-circular-dependencies/index.ts --config ./packages/circular-deps-test.conf.js", + "ts-circular-deps": "ts-node --transpile-only -- dev-infra/ts-circular-dependencies/index.ts --config ./packages/circular-deps-test.conf.js", "ts-circular-deps:check": "yarn -s ts-circular-deps check", - "ts-circular-deps:approve": "yarn -s ts-circular-deps approve" + "ts-circular-deps:approve": "yarn -s ts-circular-deps approve", + "ng-dev": "ts-node --transpile-only -- dev-infra/cli.ts" }, "// 1": "dependencies are used locally and by bazel", "dependencies": {