refactor(dev-infra): create ng-dev executable locally in the repo (#39089)

Rather than running ng-dev via ts-node, going forward ng-dev is generated and run
locally via node.  Additionally, the generated file is tested on each commit to
ensure that the local generated version stays up to date.

PR Close #39089
This commit is contained in:
Joey Perrott 2020-10-01 16:06:56 -07:00 committed by Alex Rickabaugh
parent d939b5f598
commit d331e09b71
35 changed files with 6869 additions and 79 deletions

View File

@ -16,6 +16,8 @@ export const format: FormatConfig = {
'!.yarn/**', '!.yarn/**',
// Do not format d.ts files as they are generated // Do not format d.ts files as they are generated
'!**/*.d.ts', '!**/*.d.ts',
// Do not format generated ng-dev script
'!dev-infra/ng-dev.js',
] ]
}, },
'buildifier': true 'buildifier': true

View File

@ -1,5 +1,6 @@
load("@build_bazel_rules_nodejs//:index.bzl", "pkg_npm") load("@build_bazel_rules_nodejs//:index.bzl", "generated_file_test", "pkg_npm")
load("@npm//@bazel/typescript:index.bzl", "ts_library") load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("@npm//@bazel/rollup:index.bzl", "rollup_bundle")
ts_library( ts_library(
name = "cli", name = "cli",
@ -23,6 +24,23 @@ ts_library(
], ],
) )
rollup_bundle(
name = "cli_rollup",
entry_point = ":cli.ts",
format = "cjs",
silent = True,
sourcemap = "false",
deps = [
":cli",
],
)
generated_file_test(
name = "local_ng_dev",
src = "ng-dev.js",
generated = "cli_rollup",
)
genrule( genrule(
name = "package-json", name = "package-json",
srcs = [ srcs = [

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {GitClient} from '../../utils/git'; import {GitClient} from '../../utils/git/index';
import {getCaretakerConfig} from '../config'; import {getCaretakerConfig} from '../config';
import {printCiStatus} from './ci'; import {printCiStatus} from './ci';

View File

@ -10,7 +10,7 @@ import fetch from 'node-fetch';
import {fetchActiveReleaseTrains} from '../../release/versioning/index'; import {fetchActiveReleaseTrains} from '../../release/versioning/index';
import {bold, debug, info} from '../../utils/console'; import {bold, debug, info} from '../../utils/console';
import {GitClient} from '../../utils/git'; import {GitClient} from '../../utils/git/index';
/** The results of checking the status of CI. */ /** The results of checking the status of CI. */

View File

@ -13,7 +13,7 @@ import {parse as parseYaml} from 'yaml';
import {getRepoBaseDir} from '../../utils/config'; import {getRepoBaseDir} from '../../utils/config';
import {bold, debug, info} from '../../utils/console'; import {bold, debug, info} from '../../utils/console';
import {GitClient} from '../../utils/git'; import {GitClient} from '../../utils/git/index';
/** Compare the upstream master to the upstream g3 branch, if it exists. */ /** Compare the upstream master to the upstream g3 branch, if it exists. */
export async function printG3Comparison(git: GitClient) { export async function printG3Comparison(git: GitClient) {
@ -120,6 +120,8 @@ export async function printG3Comparison(git: GitClient) {
/** Determine whether the file name passes both include and exclude checks. */ /** Determine whether the file name passes both include and exclude checks. */
function checkMatchAgainstIncludeAndExclude( function checkMatchAgainstIncludeAndExclude(
file: string, includes: string[], excludes: string[]) { file: string, includes: string[], excludes: string[]) {
return multimatch(file, includes).length >= 1 && multimatch(file, excludes).length === 0; return (
multimatch.call(undefined, file, includes).length >= 1 &&
multimatch.call(undefined, file, excludes).length === 0);
} }
} }

View File

@ -9,7 +9,7 @@
import {alias, onUnion, params, types} from 'typed-graphqlify'; import {alias, onUnion, params, types} from 'typed-graphqlify';
import {bold, debug, info} from '../../utils/console'; import {bold, debug, info} from '../../utils/console';
import {GitClient} from '../../utils/git'; import {GitClient} from '../../utils/git/index';
import {CaretakerConfig} from '../config'; import {CaretakerConfig} from '../config';
/** /**

View File

@ -1,4 +1,3 @@
#!/usr/bin/env node
/** /**
* @license * @license
* Copyright Google LLC All Rights Reserved. * Copyright Google LLC All Rights Reserved.
@ -7,15 +6,16 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import * as yargs from 'yargs'; import * as yargs from 'yargs';
import {tsCircularDependenciesBuilder} from './ts-circular-dependencies/index';
import {buildPullapproveParser} from './pullapprove/cli'; import {buildCaretakerParser} from './caretaker/cli';
import {buildCommitMessageParser} from './commit-message/cli'; import {buildCommitMessageParser} from './commit-message/cli';
import {buildFormatParser} from './format/cli'; import {buildFormatParser} from './format/cli';
import {buildReleaseParser} from './release/cli';
import {buildPrParser} from './pr/cli';
import {captureLogOutputForCommand} from './utils/console';
import {buildCaretakerParser} from './caretaker/cli';
import {buildNgbotParser} from './ngbot/cli'; import {buildNgbotParser} from './ngbot/cli';
import {buildPrParser} from './pr/cli';
import {buildPullapproveParser} from './pullapprove/cli';
import {buildReleaseParser} from './release/cli';
import {tsCircularDependenciesBuilder} from './ts-circular-dependencies/index';
import {captureLogOutputForCommand} from './utils/console';
yargs.scriptName('ng-dev') yargs.scriptName('ng-dev')
.middleware(captureLogOutputForCommand) .middleware(captureLogOutputForCommand)

View File

@ -0,0 +1 @@
pr/merge/strategies/commit-message-filter.js

View File

@ -21,7 +21,3 @@ export function buildCommitMessageParser(localYargs: yargs.Argv) {
.command(ValidateFileModule) .command(ValidateFileModule)
.command(ValidateRangeModule); .command(ValidateRangeModule);
} }
if (require.main == module) {
buildCommitMessageParser(yargs).parse();
}

View File

@ -48,7 +48,3 @@ export function buildFormatParser(localYargs: yargs.Argv) {
executionCmd(files!); executionCmd(files!);
}); });
} }
if (require.main === module) {
buildFormatParser(yargs).parse();
}

View File

@ -13,7 +13,7 @@ import {exec} from 'shelljs';
import {info} from '../utils/console'; import {info} from '../utils/console';
import {Formatter, FormatterAction, getActiveFormatters} from './formatters'; import {Formatter, FormatterAction, getActiveFormatters} from './formatters/index';
const AVAILABLE_THREADS = Math.max(cpus().length - 1, 1); const AVAILABLE_THREADS = Math.max(cpus().length - 1, 1);
@ -36,9 +36,9 @@ export function runFormatterInParallel(allFiles: string[], action: FormatterActi
const pendingCommands: {formatter: Formatter, file: string}[] = []; const pendingCommands: {formatter: Formatter, file: string}[] = [];
for (const formatter of formatters) { for (const formatter of formatters) {
pendingCommands.push(...multimatch(allFiles, formatter.getFileMatcher(), { pendingCommands.push(
dot: true ...multimatch.call(undefined, allFiles, formatter.getFileMatcher(), {dot: true})
}).map(file => ({formatter, file}))); .map(file => ({formatter, file})));
} }
// If no commands are generated, resolve the promise as `false` as no files // If no commands are generated, resolve the promise as `false` as no files

View File

@ -1,11 +0,0 @@
#!/usr/bin/env ts-node
/**
* @license
* Copyright Google LLC 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
*/
// Loads the ng-dev cli, automatically executing it.
require('./cli.ts');

6801
dev-infra/ng-dev.js Executable file

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,3 @@ export function buildNgbotParser(localYargs: yargs.Argv) {
return localYargs.help().strict().demandCommand().command( return localYargs.help().strict().demandCommand().command(
'verify', 'Verify the NgBot config', {}, () => verify()); 'verify', 'Verify the NgBot config', {}, () => verify());
} }
if (require.main === module) {
buildNgbotParser(yargs).parse();
}

View File

@ -28,7 +28,3 @@ export function buildPrParser(localYargs: yargs.Argv) {
buildRebaseCommand, handleRebaseCommand) buildRebaseCommand, handleRebaseCommand)
.command(CheckoutCommandModule); .command(CheckoutCommandModule);
} }
if (require.main === module) {
buildPrParser(yargs).parse();
}

View File

@ -9,8 +9,8 @@
import {types as graphQLTypes} from 'typed-graphqlify'; import {types as graphQLTypes} from 'typed-graphqlify';
import {info} from '../../utils/console'; import {info} from '../../utils/console';
import {GitClient} from '../../utils/git';
import {addTokenToGitHttpsUrl} from '../../utils/git/github-urls'; import {addTokenToGitHttpsUrl} from '../../utils/git/github-urls';
import {GitClient} from '../../utils/git/index';
import {getPr} from '../../utils/github'; import {getPr} from '../../utils/github';
/* GraphQL schema for the response body for a pending PR. */ /* GraphQL schema for the response body for a pending PR. */

View File

@ -11,7 +11,7 @@ import {types as graphQLTypes} from 'typed-graphqlify';
import {getConfig, NgDevConfig} from '../../utils/config'; import {getConfig, NgDevConfig} from '../../utils/config';
import {error, info} from '../../utils/console'; import {error, info} from '../../utils/console';
import {GitClient} from '../../utils/git'; import {GitClient} from '../../utils/git/index';
import {getPendingPrs} from '../../utils/github'; import {getPendingPrs} from '../../utils/github';
import {exec} from '../../utils/shelljs'; import {exec} from '../../utils/shelljs';

View File

@ -8,6 +8,9 @@ ts_library(
exclude = ["**/*.spec.ts"], exclude = ["**/*.spec.ts"],
), ),
module_name = "@angular/dev-infra-private/pr/merge", module_name = "@angular/dev-infra-private/pr/merge",
# prodmode target must be set to es5 as the Ora class, which is extended is not a proper
# prototyped object.
prodmode_target = "es5",
visibility = ["//dev-infra:__subpackages__"], visibility = ["//dev-infra:__subpackages__"],
deps = [ deps = [
"//dev-infra/commit-message", "//dev-infra/commit-message",

View File

@ -9,9 +9,9 @@
import {getConfig, getRepoBaseDir} from '../../utils/config'; import {getConfig, getRepoBaseDir} from '../../utils/config';
import {error, green, info, promptConfirm, red, yellow} from '../../utils/console'; import {error, green, info, promptConfirm, red, yellow} from '../../utils/console';
import {GitClient} from '../../utils/git';
import {GithubApiRequestError} from '../../utils/git/github'; import {GithubApiRequestError} from '../../utils/git/github';
import {GITHUB_TOKEN_GENERATE_URL} from '../../utils/git/github-urls'; import {GITHUB_TOKEN_GENERATE_URL} from '../../utils/git/github-urls';
import {GitClient} from '../../utils/git/index';
import {loadAndValidateConfig, MergeConfigWithRemote} from './config'; import {loadAndValidateConfig, MergeConfigWithRemote} from './config';
import {MergeResult, MergeStatus, PullRequestMergeTask} from './task'; import {MergeResult, MergeStatus, PullRequestMergeTask} from './task';

View File

@ -8,7 +8,7 @@
import * as Octokit from '@octokit/rest'; import * as Octokit from '@octokit/rest';
import {GitClient} from '../../utils/git'; import {GitClient} from '../../utils/git/index';
import {PullRequestFailure} from './failures'; import {PullRequestFailure} from './failures';
import {matchesPattern} from './string-pattern'; import {matchesPattern} from './string-pattern';

View File

@ -10,7 +10,7 @@ import {PullsListCommitsResponse, PullsMergeParams} from '@octokit/rest';
import {prompt} from 'inquirer'; import {prompt} from 'inquirer';
import {parseCommitMessage} from '../../../commit-message/parse'; import {parseCommitMessage} from '../../../commit-message/parse';
import {GitClient} from '../../../utils/git'; import {GitClient} from '../../../utils/git/index';
import {GithubApiMergeMethod} from '../config'; import {GithubApiMergeMethod} from '../config';
import {PullRequestFailure} from '../failures'; import {PullRequestFailure} from '../failures';
import {PullRequest} from '../pull-request'; import {PullRequest} from '../pull-request';

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {GitClient} from '../../../utils/git'; import {GitClient} from '../../../utils/git/index';
import {PullRequestFailure} from '../failures'; import {PullRequestFailure} from '../failures';
import {PullRequest} from '../pull-request'; import {PullRequest} from '../pull-request';

View File

@ -7,7 +7,7 @@
*/ */
import {promptConfirm} from '../../utils/console'; import {promptConfirm} from '../../utils/console';
import {GitClient, GitCommandError} from '../../utils/git'; import {GitClient, GitCommandError} from '../../utils/git/index';
import {MergeConfigWithRemote} from './config'; import {MergeConfigWithRemote} from './config';
import {PullRequestFailure} from './failures'; import {PullRequestFailure} from './failures';

View File

@ -10,8 +10,8 @@ import {types as graphQLTypes} from 'typed-graphqlify';
import {getConfig, NgDevConfig} from '../../utils/config'; import {getConfig, NgDevConfig} from '../../utils/config';
import {error, info, promptConfirm} from '../../utils/console'; import {error, info, promptConfirm} from '../../utils/console';
import {GitClient} from '../../utils/git';
import {addTokenToGitHttpsUrl} from '../../utils/git/github-urls'; import {addTokenToGitHttpsUrl} from '../../utils/git/github-urls';
import {GitClient} from '../../utils/git/index';
import {getPr} from '../../utils/github'; import {getPr} from '../../utils/github';
/* GraphQL schema for the response body for each pending PR. */ /* GraphQL schema for the response body for each pending PR. */

View File

@ -13,7 +13,3 @@ export function buildPullapproveParser(localYargs: yargs.Argv) {
return localYargs.help().strict().demandCommand().command( return localYargs.help().strict().demandCommand().command(
'verify', 'Verify the pullapprove config', {}, () => verify()); 'verify', 'Verify the pullapprove config', {}, () => verify());
} }
if (require.main === module) {
buildPullapproveParser(yargs).parse();
}

View File

@ -24,7 +24,3 @@ export function buildReleaseParser(localYargs: yargs.Argv) {
'build-env-stamp', 'Build the environment stamping information', {}, 'build-env-stamp', 'Build the environment stamping information', {},
() => buildEnvStamp()); () => buildEnvStamp());
} }
if (require.main === module) {
buildReleaseParser(yargs).parse();
}

View File

@ -301,7 +301,7 @@ export abstract class ReleaseAction {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
debug(`Waiting for pull request #${id} to be merged.`); debug(`Waiting for pull request #${id} to be merged.`);
const spinner = ora().start(`Waiting for pull request #${id} to be merged.`); const spinner = ora.call(undefined).start(`Waiting for pull request #${id} to be merged.`);
const intervalId = setInterval(async () => { const intervalId = setInterval(async () => {
const prState = await getPullRequestState(this.git, id); const prState = await getPullRequestState(this.git, id);
if (prState === 'merged') { if (prState === 'merged') {
@ -517,7 +517,7 @@ export abstract class ReleaseAction {
/** Publishes the given built package to NPM with the specified NPM dist tag. */ /** Publishes the given built package to NPM with the specified NPM dist tag. */
private async _publishBuiltPackageToNpm(pkg: BuiltPackage, npmDistTag: string) { private async _publishBuiltPackageToNpm(pkg: BuiltPackage, npmDistTag: string) {
debug(`Starting publish of "${pkg.name}".`); debug(`Starting publish of "${pkg.name}".`);
const spinner = ora().start(`Publishing "${pkg.name}"`); const spinner = ora.call(undefined).start(`Publishing "${pkg.name}"`);
try { try {
await runNpmPublish(pkg.outputPath, npmDistTag, this.config.publishRegistry); await runNpmPublish(pkg.outputPath, npmDistTag, this.config.publishRegistry);

View File

@ -11,7 +11,7 @@ import {Arguments, Argv, CommandModule} from 'yargs';
import {getConfig, getRepoBaseDir} from '../../utils/config'; import {getConfig, getRepoBaseDir} from '../../utils/config';
import {error, green, info, red, yellow} from '../../utils/console'; import {error, green, info, red, yellow} from '../../utils/console';
import {addGithubTokenOption} from '../../utils/git/github-yargs'; import {addGithubTokenOption} from '../../utils/git/github-yargs';
import {getReleaseConfig} from '../config'; import {getReleaseConfig} from '../config/index';
import {CompletionState, ReleaseTool} from './index'; import {CompletionState, ReleaseTool} from './index';

View File

@ -54,7 +54,7 @@ export async function invokeSetNpmDistCommand(npmDistTag: string, version: semve
* packages for the currently checked out branch. * packages for the currently checked out branch.
*/ */
export async function invokeReleaseBuildCommand(): Promise<BuiltPackage[]> { export async function invokeReleaseBuildCommand(): Promise<BuiltPackage[]> {
const spinner = ora().start('Building release output.'); const spinner = ora.call(undefined).start('Building release output.');
try { try {
// Since we expect JSON to be printed from the `ng-dev release build` command, // Since we expect JSON to be printed from the `ng-dev release build` command,
// we spawn the process in silent mode. We have set up an Ora progress spinner. // we spawn the process in silent mode. We have set up an Ora progress spinner.

View File

@ -46,7 +46,7 @@ async function handler(args: Arguments<ReleaseSetDistTagOptions>) {
process.exit(1); process.exit(1);
} }
const spinner = ora().start(); const spinner = ora.call(undefined).start();
debug(`Setting "${tagName}" NPM dist tag for release packages to v${version}.`); debug(`Setting "${tagName}" NPM dist tag for release packages to v${version}.`);
for (const pkgName of npmPackages) { for (const pkgName of npmPackages) {

View File

@ -1,4 +1,3 @@
#!/usr/bin/env node
/** /**
* @license * @license
* Copyright Google LLC All Rights Reserved. * Copyright Google LLC All Rights Reserved.
@ -13,12 +12,12 @@ import {isAbsolute, relative, resolve} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import * as yargs from 'yargs'; import * as yargs from 'yargs';
import {green, info, error, red, yellow} from '../utils/console'; import {error, green, info, red, yellow} from '../utils/console';
import {Analyzer, ReferenceChain} from './analyzer'; import {Analyzer, ReferenceChain} from './analyzer';
import {compareGoldens, convertReferenceChainToGolden, Golden} from './golden'; import {CircularDependenciesTestConfig, loadTestConfig} from './config';
import {convertPathToForwardSlash} from './file_system'; import {convertPathToForwardSlash} from './file_system';
import {loadTestConfig, CircularDependenciesTestConfig} from './config'; import {compareGoldens, convertReferenceChainToGolden, Golden} from './golden';
export function tsCircularDependenciesBuilder(localYargs: yargs.Argv) { export function tsCircularDependenciesBuilder(localYargs: yargs.Argv) {
@ -134,7 +133,3 @@ function getRelativePath(baseDir: string, path: string) {
function convertReferenceChainToString(chain: ReferenceChain<string>) { function convertReferenceChainToString(chain: ReferenceChain<string>) {
return chain.join(' → '); return chain.join(' → ');
} }
if (require.main === module) {
tsCircularDependenciesBuilder(yargs).parse();
}

View File

@ -7,6 +7,9 @@ ts_library(
"git/*.ts", "git/*.ts",
]), ]),
module_name = "@angular/dev-infra-private/utils", module_name = "@angular/dev-infra-private/utils",
# prodmode target must be set to es5 as the Octokit class, which is extended is not a proper
# prototyped object.
prodmode_target = "es5",
visibility = ["//dev-infra:__subpackages__"], visibility = ["//dev-infra:__subpackages__"],
deps = [ deps = [
"@npm//@octokit/graphql", "@npm//@octokit/graphql",

View File

@ -8,7 +8,7 @@
import {params, types} from 'typed-graphqlify'; import {params, types} from 'typed-graphqlify';
import {GitClient} from './git'; import {GitClient} from './git/index';
/** Get a PR from github */ /** Get a PR from github */
export async function getPr<PrSchema>(prSchema: PrSchema, prNumber: number, git: GitClient) { export async function getPr<PrSchema>(prSchema: PrSchema, prNumber: number, git: GitClient) {

View File

@ -34,10 +34,9 @@
"public-api:update": "node goldens/public-api/manage.js accept", "public-api:update": "node goldens/public-api/manage.js accept",
"symbol-extractor:check": "node tools/symbol-extractor/run_all_symbols_extractor_tests.js test", "symbol-extractor:check": "node tools/symbol-extractor/run_all_symbols_extractor_tests.js test",
"symbol-extractor:update": "node tools/symbol-extractor/run_all_symbols_extractor_tests.js accept", "symbol-extractor:update": "node tools/symbol-extractor/run_all_symbols_extractor_tests.js accept",
"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 ng-dev ts-circular-deps check --config ./packages/circular-deps-test.conf.js",
"ts-circular-deps:check": "yarn -s ts-circular-deps check", "ts-circular-deps:approve": "yarn -s ng-dev ts-circular-deps approve --config ./packages/circular-deps-test.conf.js",
"ts-circular-deps:approve": "yarn -s ts-circular-deps approve", "ng-dev": "node dev-infra/ng-dev"
"ng-dev": "ts-node --transpile-only -- dev-infra/cli.ts"
}, },
"// 1": "dependencies are used locally and by bazel", "// 1": "dependencies are used locally and by bazel",
"dependencies": { "dependencies": {

View File

@ -98,7 +98,8 @@
"./modules/benchmarks_external/**/*", "./modules/benchmarks_external/**/*",
// Ignore zone.js directory // Ignore zone.js directory
// TODO(JiaLiPassion): add zone.js back later // TODO(JiaLiPassion): add zone.js back later
"./packages/zone.js/**/*" "./packages/zone.js/**/*",
"./dev-infra/ng-dev.js"
] ]
} }
} }