refactor(dev-infra): remove usages and dependency on shelljs (#42911)
Remove usages of shelljs and instead use spawn/spawnSync. PR Close #42911
This commit is contained in:
parent
d3b0d1e3fb
commit
992dc93ea3
|
@ -10,10 +10,8 @@ ts_library(
|
||||||
"//packages/benchpress",
|
"//packages/benchpress",
|
||||||
"@npm//@types/node",
|
"@npm//@types/node",
|
||||||
"@npm//@types/selenium-webdriver",
|
"@npm//@types/selenium-webdriver",
|
||||||
"@npm//@types/shelljs",
|
|
||||||
"@npm//node-uuid",
|
"@npm//node-uuid",
|
||||||
"@npm//protractor",
|
"@npm//protractor",
|
||||||
"@npm//selenium-webdriver",
|
"@npm//selenium-webdriver",
|
||||||
"@npm//shelljs",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {mkdir} from 'shelljs';
|
import {mkdirSync} from 'fs';
|
||||||
|
|
||||||
export {verifyNoBrowserErrors} from './e2e_util';
|
export {verifyNoBrowserErrors} from './e2e_util';
|
||||||
|
|
||||||
|
@ -61,7 +61,9 @@ function createBenchpressRunner(): Runner {
|
||||||
runId = process.env.GIT_SHA + ' ' + runId;
|
runId = process.env.GIT_SHA + ' ' + runId;
|
||||||
}
|
}
|
||||||
const resultsFolder = './dist/benchmark_results';
|
const resultsFolder = './dist/benchmark_results';
|
||||||
mkdir('-p', resultsFolder);
|
mkdirSync(resultsFolder, {
|
||||||
|
recursive: true,
|
||||||
|
});
|
||||||
const providers: StaticProvider[] = [
|
const providers: StaticProvider[] = [
|
||||||
SeleniumWebDriverAdapter.PROTRACTOR_PROVIDERS,
|
SeleniumWebDriverAdapter.PROTRACTOR_PROVIDERS,
|
||||||
{provide: Options.FORCE_GC, useValue: globalOptions.forceGc},
|
{provide: Options.FORCE_GC, useValue: globalOptions.forceGc},
|
||||||
|
|
|
@ -145,6 +145,9 @@ var GitCommandError = /** @class */ (function (_super) {
|
||||||
// we sanitize the command that will be part of the error message.
|
// we sanitize the command that will be part of the error message.
|
||||||
_super.call(this, "Command failed: git " + client.sanitizeConsoleOutput(args.join(' '))) || this;
|
_super.call(this, "Command failed: git " + client.sanitizeConsoleOutput(args.join(' '))) || this;
|
||||||
_this.args = args;
|
_this.args = args;
|
||||||
|
// Set the prototype explicitly because in ES5, the prototype is accidentally lost due to
|
||||||
|
// a limitation in down-leveling.
|
||||||
|
// https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work.
|
||||||
Object.setPrototypeOf(_this, GitCommandError.prototype);
|
Object.setPrototypeOf(_this, GitCommandError.prototype);
|
||||||
return _this;
|
return _this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,10 @@ ts_library(
|
||||||
"@npm//@types/git-raw-commits",
|
"@npm//@types/git-raw-commits",
|
||||||
"@npm//@types/inquirer",
|
"@npm//@types/inquirer",
|
||||||
"@npm//@types/node",
|
"@npm//@types/node",
|
||||||
"@npm//@types/shelljs",
|
|
||||||
"@npm//@types/yargs",
|
"@npm//@types/yargs",
|
||||||
"@npm//conventional-commits-parser",
|
"@npm//conventional-commits-parser",
|
||||||
"@npm//git-raw-commits",
|
"@npm//git-raw-commits",
|
||||||
"@npm//inquirer",
|
"@npm//inquirer",
|
||||||
"@npm//shelljs",
|
|
||||||
"@npm//yargs",
|
"@npm//yargs",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,11 +10,9 @@ ts_library(
|
||||||
"//dev-infra/utils",
|
"//dev-infra/utils",
|
||||||
"@npm//@types/cli-progress",
|
"@npm//@types/cli-progress",
|
||||||
"@npm//@types/node",
|
"@npm//@types/node",
|
||||||
"@npm//@types/shelljs",
|
|
||||||
"@npm//@types/yargs",
|
"@npm//@types/yargs",
|
||||||
"@npm//cli-progress",
|
"@npm//cli-progress",
|
||||||
"@npm//multimatch",
|
"@npm//multimatch",
|
||||||
"@npm//shelljs",
|
|
||||||
"@npm//yargs",
|
"@npm//yargs",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,7 +10,8 @@ import {GitClient} from '../../utils/git/git-client';
|
||||||
import {FormatConfig} from '../config';
|
import {FormatConfig} from '../config';
|
||||||
|
|
||||||
// A callback to determine if the formatter run found a failure in formatting.
|
// A callback to determine if the formatter run found a failure in formatting.
|
||||||
export type CallbackFunc = (file: string, code: number, stdout: string, stderr: string) => boolean;
|
export type CallbackFunc =
|
||||||
|
(file: string, code: number|NodeJS.Signals, stdout: string, stderr: string) => boolean;
|
||||||
|
|
||||||
// The actions a formatter can take.
|
// The actions a formatter can take.
|
||||||
export type FormatterAction = 'check'|'format';
|
export type FormatterAction = 'check'|'format';
|
||||||
|
|
|
@ -26,14 +26,14 @@ export class Buildifier extends Formatter {
|
||||||
check: {
|
check: {
|
||||||
commandFlags: `${BAZEL_WARNING_FLAG} --lint=warn --mode=check --format=json`,
|
commandFlags: `${BAZEL_WARNING_FLAG} --lint=warn --mode=check --format=json`,
|
||||||
callback:
|
callback:
|
||||||
(_: string, code: number, stdout: string) => {
|
(_: string, code: number|NodeJS.Signals, stdout: string) => {
|
||||||
return code !== 0 || !(JSON.parse(stdout) as {success: string}).success;
|
return code !== 0 || !(JSON.parse(stdout) as {success: string}).success;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
format: {
|
format: {
|
||||||
commandFlags: `${BAZEL_WARNING_FLAG} --lint=fix --mode=fix`,
|
commandFlags: `${BAZEL_WARNING_FLAG} --lint=fix --mode=fix`,
|
||||||
callback:
|
callback:
|
||||||
(file: string, code: number, _: string, stderr: string) => {
|
(file: string, code: number|NodeJS.Signals, _: string, stderr: string) => {
|
||||||
if (code !== 0) {
|
if (code !== 0) {
|
||||||
error(`Error running buildifier on: ${file}`);
|
error(`Error running buildifier on: ${file}`);
|
||||||
error(stderr);
|
error(stderr);
|
||||||
|
|
|
@ -26,14 +26,14 @@ export class ClangFormat extends Formatter {
|
||||||
check: {
|
check: {
|
||||||
commandFlags: `--Werror -n -style=file`,
|
commandFlags: `--Werror -n -style=file`,
|
||||||
callback:
|
callback:
|
||||||
(_: string, code: number) => {
|
(_: string, code: number|NodeJS.Signals) => {
|
||||||
return code !== 0;
|
return code !== 0;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
format: {
|
format: {
|
||||||
commandFlags: `-i -style=file`,
|
commandFlags: `-i -style=file`,
|
||||||
callback:
|
callback:
|
||||||
(file: string, code: number, _: string, stderr: string) => {
|
(file: string, code: number|NodeJS.Signals, _: string, stderr: string) => {
|
||||||
if (code !== 0) {
|
if (code !== 0) {
|
||||||
error(`Error running clang-format on: ${file}`);
|
error(`Error running clang-format on: ${file}`);
|
||||||
error(stderr);
|
error(stderr);
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {join} from 'path';
|
import {join} from 'path';
|
||||||
import {exec} from 'shelljs';
|
|
||||||
|
|
||||||
|
import {spawnSync} from '../../utils/child-process';
|
||||||
import {error} from '../../utils/console';
|
import {error} from '../../utils/console';
|
||||||
|
|
||||||
import {Formatter} from './base-formatter';
|
import {Formatter} from './base-formatter';
|
||||||
|
@ -27,21 +27,22 @@ export class Prettier extends Formatter {
|
||||||
* The configuration path of the prettier config, obtained during construction to prevent needing
|
* The configuration path of the prettier config, obtained during construction to prevent needing
|
||||||
* to discover it repeatedly for each execution.
|
* to discover it repeatedly for each execution.
|
||||||
*/
|
*/
|
||||||
private configPath =
|
private configPath = this.config['prettier'] ?
|
||||||
this.config['prettier'] ? exec(`${this.binaryFilePath} --find-config-path .`).trim() : '';
|
spawnSync(this.binaryFilePath, ['--find-config-path', '.']).stdout.trim() :
|
||||||
|
'';
|
||||||
|
|
||||||
override actions = {
|
override actions = {
|
||||||
check: {
|
check: {
|
||||||
commandFlags: `--config ${this.configPath} --check`,
|
commandFlags: `--config ${this.configPath} --check`,
|
||||||
callback:
|
callback:
|
||||||
(_: string, code: number, stdout: string) => {
|
(_: string, code: number|NodeJS.Signals, stdout: string) => {
|
||||||
return code !== 0;
|
return code !== 0;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
format: {
|
format: {
|
||||||
commandFlags: `--config ${this.configPath} --write`,
|
commandFlags: `--config ${this.configPath} --write`,
|
||||||
callback:
|
callback:
|
||||||
(file: string, code: number, _: string, stderr: string) => {
|
(file: string, code: number|NodeJS.Signals, _: string, stderr: string) => {
|
||||||
if (code !== 0) {
|
if (code !== 0) {
|
||||||
error(`Error running prettier on: ${file}`);
|
error(`Error running prettier on: ${file}`);
|
||||||
error(stderr);
|
error(stderr);
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
import {Bar} from 'cli-progress';
|
import {Bar} from 'cli-progress';
|
||||||
import * as multimatch from 'multimatch';
|
import * as multimatch from 'multimatch';
|
||||||
import {cpus} from 'os';
|
import {cpus} from 'os';
|
||||||
import {exec} from 'shelljs';
|
|
||||||
|
|
||||||
|
import {spawn, SpawnResult} from '../utils/child-process';
|
||||||
import {info} from '../utils/console';
|
import {info} from '../utils/console';
|
||||||
|
|
||||||
import {Formatter, FormatterAction, getActiveFormatters} from './formatters/index';
|
import {Formatter, FormatterAction, getActiveFormatters} from './formatters/index';
|
||||||
|
@ -86,12 +86,11 @@ export function runFormatterInParallel(allFiles: string[], action: FormatterActi
|
||||||
// Get the file and formatter for the next command.
|
// Get the file and formatter for the next command.
|
||||||
const {file, formatter} = nextCommand;
|
const {file, formatter} = nextCommand;
|
||||||
|
|
||||||
exec(
|
const [spawnCmd, ...spawnArgs] = [...formatter.commandFor(action).split(' '), file];
|
||||||
`${formatter.commandFor(action)} ${file}`,
|
spawn(spawnCmd, spawnArgs, {suppressErrorOnFailingExitCode: true, mode: 'silent'})
|
||||||
{async: true, silent: true},
|
.then(({stdout, stderr, status}: SpawnResult) => {
|
||||||
(code, stdout, stderr) => {
|
|
||||||
// Run the provided callback function.
|
// Run the provided callback function.
|
||||||
const failed = formatter.callbackFor(action)(file, code, stdout, stderr);
|
const failed = formatter.callbackFor(action)(file, status, stdout, stderr);
|
||||||
if (failed) {
|
if (failed) {
|
||||||
failures.push({filePath: file, message: stderr});
|
failures.push({filePath: file, message: stderr});
|
||||||
}
|
}
|
||||||
|
@ -110,8 +109,7 @@ export function runFormatterInParallel(allFiles: string[], action: FormatterActi
|
||||||
progressBar.stop();
|
progressBar.stop();
|
||||||
resolve(failures);
|
resolve(failures);
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
// Mark the thread as in use as the command execution has been started.
|
// Mark the thread as in use as the command execution has been started.
|
||||||
threads[thread] = true;
|
threads[thread] = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {green} from 'chalk';
|
import {green} from 'chalk';
|
||||||
import {lstatSync, stat, Stats} from 'fs';
|
import {lstatSync} from 'fs';
|
||||||
import {isAbsolute, join, resolve} from 'path';
|
import {resolve} from 'path';
|
||||||
import {Arguments, Argv, CommandModule} from 'yargs';
|
import {Arguments, Argv, CommandModule} from 'yargs';
|
||||||
|
|
||||||
import {buildReleaseOutput} from '../../release/build/index';
|
import {buildReleaseOutput} from '../../release/build/index';
|
||||||
|
import {spawn} from '../../utils/child-process';
|
||||||
import {error, info, red} from '../../utils/console';
|
import {error, info, red} from '../../utils/console';
|
||||||
import {exec} from '../../utils/shelljs';
|
|
||||||
|
|
||||||
|
|
||||||
/** Command line options. */
|
/** Command line options. */
|
||||||
|
@ -52,8 +52,8 @@ async function handler({projectRoot}: Arguments<BuildAndLinkOptions>) {
|
||||||
info(green(` ✓ Built release output.`));
|
info(green(` ✓ Built release output.`));
|
||||||
|
|
||||||
for (const {outputPath, name} of releaseOutputs) {
|
for (const {outputPath, name} of releaseOutputs) {
|
||||||
exec(`yarn link --cwd ${outputPath}`);
|
await spawn('yarn', ['link', '--cwd', outputPath]);
|
||||||
exec(`yarn link --cwd ${projectRoot} ${name}`);
|
await spawn('yarn', ['link', '--cwd', projectRoot, name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
info(green(` ✓ Linked release packages in provided project.`));
|
info(green(` ✓ Linked release packages in provided project.`));
|
||||||
|
|
|
@ -22,7 +22,6 @@ var conventionalCommitsParser = require('conventional-commits-parser');
|
||||||
var gitCommits_ = require('git-raw-commits');
|
var gitCommits_ = require('git-raw-commits');
|
||||||
var cliProgress = require('cli-progress');
|
var cliProgress = require('cli-progress');
|
||||||
var os = require('os');
|
var os = require('os');
|
||||||
var shelljs = require('shelljs');
|
|
||||||
var minimatch = require('minimatch');
|
var minimatch = require('minimatch');
|
||||||
var ejs = require('ejs');
|
var ejs = require('ejs');
|
||||||
var ora = require('ora');
|
var ora = require('ora');
|
||||||
|
@ -317,6 +316,9 @@ var GitCommandError = /** @class */ (function (_super) {
|
||||||
// we sanitize the command that will be part of the error message.
|
// we sanitize the command that will be part of the error message.
|
||||||
_super.call(this, "Command failed: git " + client.sanitizeConsoleOutput(args.join(' '))) || this;
|
_super.call(this, "Command failed: git " + client.sanitizeConsoleOutput(args.join(' '))) || this;
|
||||||
_this.args = args;
|
_this.args = args;
|
||||||
|
// Set the prototype explicitly because in ES5, the prototype is accidentally lost due to
|
||||||
|
// a limitation in down-leveling.
|
||||||
|
// https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work.
|
||||||
Object.setPrototypeOf(_this, GitCommandError.prototype);
|
Object.setPrototypeOf(_this, GitCommandError.prototype);
|
||||||
return _this;
|
return _this;
|
||||||
}
|
}
|
||||||
|
@ -2440,6 +2442,113 @@ function buildCommitMessageParser(localYargs) {
|
||||||
.command(ValidateRangeModule);
|
.command(ValidateRangeModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Spawns a given command with the specified arguments inside an interactive shell. All process
|
||||||
|
* stdin, stdout and stderr output is printed to the current console.
|
||||||
|
*
|
||||||
|
* @returns a Promise resolving on success, and rejecting on command failure with the status code.
|
||||||
|
*/
|
||||||
|
function spawnInteractive(command, args, options) {
|
||||||
|
if (options === void 0) { options = {}; }
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
var commandText = command + " " + args.join(' ');
|
||||||
|
debug("Executing command: " + commandText);
|
||||||
|
var childProcess = child_process.spawn(command, args, tslib.__assign(tslib.__assign({}, options), { shell: true, stdio: 'inherit' }));
|
||||||
|
childProcess.on('exit', function (status) { return status === 0 ? resolve() : reject(status); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Spawns a given command with the specified arguments inside a shell. All process stdout
|
||||||
|
* output is captured and returned as resolution on completion. Depending on the chosen
|
||||||
|
* output mode, stdout/stderr output is also printed to the console, or only on error.
|
||||||
|
*
|
||||||
|
* @returns a Promise resolving with captured stdout and stderr on success. The promise
|
||||||
|
* rejects on command failure.
|
||||||
|
*/
|
||||||
|
function spawn(command, args, options) {
|
||||||
|
if (options === void 0) { options = {}; }
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
var commandText = command + " " + args.join(' ');
|
||||||
|
var outputMode = options.mode;
|
||||||
|
debug("Executing command: " + commandText);
|
||||||
|
var childProcess = child_process.spawn(command, args, tslib.__assign(tslib.__assign({}, options), { shell: true, stdio: 'pipe' }));
|
||||||
|
var logOutput = '';
|
||||||
|
var stdout = '';
|
||||||
|
var stderr = '';
|
||||||
|
// Capture the stdout separately so that it can be passed as resolve value.
|
||||||
|
// This is useful if commands return parsable stdout.
|
||||||
|
childProcess.stderr.on('data', function (message) {
|
||||||
|
stderr += message;
|
||||||
|
logOutput += message;
|
||||||
|
// If console output is enabled, print the message directly to the stderr. Note that
|
||||||
|
// we intentionally print all output to stderr as stdout should not be polluted.
|
||||||
|
if (outputMode === undefined || outputMode === 'enabled') {
|
||||||
|
process.stderr.write(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
childProcess.stdout.on('data', function (message) {
|
||||||
|
stdout += message;
|
||||||
|
logOutput += message;
|
||||||
|
// If console output is enabled, print the message directly to the stderr. Note that
|
||||||
|
// we intentionally print all output to stderr as stdout should not be polluted.
|
||||||
|
if (outputMode === undefined || outputMode === 'enabled') {
|
||||||
|
process.stderr.write(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
childProcess.on('exit', function (exitCode, signal) {
|
||||||
|
var exitDescription = exitCode !== null ? "exit code \"" + exitCode + "\"" : "signal \"" + signal + "\"";
|
||||||
|
var printFn = outputMode === 'on-error' ? error : debug;
|
||||||
|
var status = statusFromExitCodeAndSignal(exitCode, signal);
|
||||||
|
printFn("Command \"" + commandText + "\" completed with " + exitDescription + ".");
|
||||||
|
printFn("Process output: \n" + logOutput);
|
||||||
|
// On success, resolve the promise. Otherwise reject with the captured stderr
|
||||||
|
// and stdout log output if the output mode was set to `silent`.
|
||||||
|
if (status === 0 || options.suppressErrorOnFailingExitCode) {
|
||||||
|
resolve({ stdout: stdout, stderr: stderr, status: status });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
reject(outputMode === 'silent' ? logOutput : undefined);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Spawns a given command with the specified arguments inside a shell synchronously.
|
||||||
|
*
|
||||||
|
* @returns The command's stdout and stderr.
|
||||||
|
*/
|
||||||
|
function spawnSync(command, args, options) {
|
||||||
|
if (options === void 0) { options = {}; }
|
||||||
|
var commandText = command + " " + args.join(' ');
|
||||||
|
debug("Executing command: " + commandText);
|
||||||
|
var _a = child_process.spawnSync(command, args, tslib.__assign(tslib.__assign({}, options), { encoding: 'utf8', shell: true, stdio: 'pipe' })), exitCode = _a.status, signal = _a.signal, stdout = _a.stdout, stderr = _a.stderr;
|
||||||
|
/** The status of the spawn result. */
|
||||||
|
var status = statusFromExitCodeAndSignal(exitCode, signal);
|
||||||
|
if (status === 0 || options.suppressErrorOnFailingExitCode) {
|
||||||
|
return { status: status, stdout: stdout, stderr: stderr };
|
||||||
|
}
|
||||||
|
throw new Error(stderr);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convert the provided exitCode and signal to a single status code.
|
||||||
|
*
|
||||||
|
* During `exit` node provides either a `code` or `signal`, one of which is guaranteed to be
|
||||||
|
* non-null.
|
||||||
|
*
|
||||||
|
* For more details see: https://nodejs.org/api/child_process.html#child_process_event_exit
|
||||||
|
*/
|
||||||
|
function statusFromExitCodeAndSignal(exitCode, signal) {
|
||||||
|
var _a;
|
||||||
|
return (_a = exitCode !== null && exitCode !== void 0 ? exitCode : signal) !== null && _a !== void 0 ? _a : -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @license
|
* @license
|
||||||
* Copyright Google LLC All Rights Reserved.
|
* Copyright Google LLC All Rights Reserved.
|
||||||
|
@ -2644,7 +2753,9 @@ class Prettier extends Formatter {
|
||||||
* The configuration path of the prettier config, obtained during construction to prevent needing
|
* The configuration path of the prettier config, obtained during construction to prevent needing
|
||||||
* to discover it repeatedly for each execution.
|
* to discover it repeatedly for each execution.
|
||||||
*/
|
*/
|
||||||
this.configPath = this.config['prettier'] ? shelljs.exec(`${this.binaryFilePath} --find-config-path .`).trim() : '';
|
this.configPath = this.config['prettier'] ?
|
||||||
|
spawnSync(this.binaryFilePath, ['--find-config-path', '.']).stdout.trim() :
|
||||||
|
'';
|
||||||
this.actions = {
|
this.actions = {
|
||||||
check: {
|
check: {
|
||||||
commandFlags: `--config ${this.configPath} --check`,
|
commandFlags: `--config ${this.configPath} --check`,
|
||||||
|
@ -2747,9 +2858,11 @@ function runFormatterInParallel(allFiles, action) {
|
||||||
}
|
}
|
||||||
// Get the file and formatter for the next command.
|
// Get the file and formatter for the next command.
|
||||||
const { file, formatter } = nextCommand;
|
const { file, formatter } = nextCommand;
|
||||||
shelljs.exec(`${formatter.commandFor(action)} ${file}`, { async: true, silent: true }, (code, stdout, stderr) => {
|
const [spawnCmd, ...spawnArgs] = [...formatter.commandFor(action).split(' '), file];
|
||||||
|
spawn(spawnCmd, spawnArgs, { suppressErrorOnFailingExitCode: true, mode: 'silent' })
|
||||||
|
.then(({ stdout, stderr, status }) => {
|
||||||
// Run the provided callback function.
|
// Run the provided callback function.
|
||||||
const failed = formatter.callbackFor(action)(file, code, stdout, stderr);
|
const failed = formatter.callbackFor(action)(file, status, stdout, stderr);
|
||||||
if (failed) {
|
if (failed) {
|
||||||
failures.push({ filePath: file, message: stderr });
|
failures.push({ filePath: file, message: stderr });
|
||||||
}
|
}
|
||||||
|
@ -3376,21 +3489,6 @@ const CheckoutCommandModule = {
|
||||||
describe: 'Checkout a PR from the upstream repo',
|
describe: 'Checkout a PR from the upstream repo',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @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
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Runs an given command as child process. By default, child process
|
|
||||||
* output will not be printed.
|
|
||||||
*/
|
|
||||||
function exec(cmd, opts) {
|
|
||||||
return shelljs.exec(cmd, tslib.__assign(tslib.__assign({ silent: true }, opts), { async: false }));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @license
|
* @license
|
||||||
* Copyright Google LLC All Rights Reserved.
|
* Copyright Google LLC All Rights Reserved.
|
||||||
|
@ -3494,7 +3592,9 @@ function discoverNewConflictsForPr(newPrNumber, updatedAfter) {
|
||||||
if (err instanceof GitCommandError) {
|
if (err instanceof GitCommandError) {
|
||||||
conflicts.push(pr);
|
conflicts.push(pr);
|
||||||
}
|
}
|
||||||
throw err;
|
else {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Abort any outstanding rebase attempt.
|
// Abort any outstanding rebase attempt.
|
||||||
git.runGraceful(['rebase', '--abort'], { stdio: 'ignore' });
|
git.runGraceful(['rebase', '--abort'], { stdio: 'ignore' });
|
||||||
|
@ -3504,7 +3604,7 @@ function discoverNewConflictsForPr(newPrNumber, updatedAfter) {
|
||||||
progressBar.stop();
|
progressBar.stop();
|
||||||
info();
|
info();
|
||||||
info(`Result:`);
|
info(`Result:`);
|
||||||
cleanUpGitState(previousBranchOrRevision);
|
git.checkout(previousBranchOrRevision, true);
|
||||||
// If no conflicts are found, exit successfully.
|
// If no conflicts are found, exit successfully.
|
||||||
if (conflicts.length === 0) {
|
if (conflicts.length === 0) {
|
||||||
info(`No new conflicting PRs found after #${newPrNumber} merging`);
|
info(`No new conflicting PRs found after #${newPrNumber} merging`);
|
||||||
|
@ -3519,17 +3619,6 @@ function discoverNewConflictsForPr(newPrNumber, updatedAfter) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/** Reset git back to the provided branch or revision. */
|
|
||||||
function cleanUpGitState(previousBranchOrRevision) {
|
|
||||||
// Ensure that any outstanding rebases are aborted.
|
|
||||||
exec(`git rebase --abort`);
|
|
||||||
// Ensure that any changes in the current repo state are cleared.
|
|
||||||
exec(`git reset --hard`);
|
|
||||||
// Checkout the original branch from before the run began.
|
|
||||||
exec(`git checkout ${previousBranchOrRevision}`);
|
|
||||||
// Delete the generated branch.
|
|
||||||
exec(`git branch -D ${tempWorkingBranch}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @license
|
* @license
|
||||||
|
@ -5976,88 +6065,6 @@ const ReleaseNotesCommandModule = {
|
||||||
describe: 'Generate release notes',
|
describe: 'Generate release notes',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @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
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Spawns a given command with the specified arguments inside an interactive shell. All process
|
|
||||||
* stdin, stdout and stderr output is printed to the current console.
|
|
||||||
*
|
|
||||||
* @returns a Promise resolving on success, and rejecting on command failure with the status code.
|
|
||||||
*/
|
|
||||||
function spawnInteractive(command, args, options) {
|
|
||||||
if (options === void 0) { options = {}; }
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
var commandText = command + " " + args.join(' ');
|
|
||||||
debug("Executing command: " + commandText);
|
|
||||||
var childProcess = child_process.spawn(command, args, tslib.__assign(tslib.__assign({}, options), { shell: true, stdio: 'inherit' }));
|
|
||||||
childProcess.on('exit', function (status) { return status === 0 ? resolve() : reject(status); });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Spawns a given command with the specified arguments inside a shell. All process stdout
|
|
||||||
* output is captured and returned as resolution on completion. Depending on the chosen
|
|
||||||
* output mode, stdout/stderr output is also printed to the console, or only on error.
|
|
||||||
*
|
|
||||||
* @returns a Promise resolving with captured stdout and stderr on success. The promise
|
|
||||||
* rejects on command failure
|
|
||||||
*/
|
|
||||||
function spawn(command, args, options) {
|
|
||||||
if (options === void 0) { options = {}; }
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
var commandText = command + " " + args.join(' ');
|
|
||||||
var outputMode = options.mode;
|
|
||||||
debug("Executing command: " + commandText);
|
|
||||||
var childProcess = child_process.spawn(command, args, tslib.__assign(tslib.__assign({}, options), { shell: true, stdio: 'pipe' }));
|
|
||||||
var logOutput = '';
|
|
||||||
var stdout = '';
|
|
||||||
var stderr = '';
|
|
||||||
// Capture the stdout separately so that it can be passed as resolve value.
|
|
||||||
// This is useful if commands return parsable stdout.
|
|
||||||
childProcess.stderr.on('data', function (message) {
|
|
||||||
stderr += message;
|
|
||||||
logOutput += message;
|
|
||||||
// If console output is enabled, print the message directly to the stderr. Note that
|
|
||||||
// we intentionally print all output to stderr as stdout should not be polluted.
|
|
||||||
if (outputMode === undefined || outputMode === 'enabled') {
|
|
||||||
process.stderr.write(message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
childProcess.stdout.on('data', function (message) {
|
|
||||||
stdout += message;
|
|
||||||
logOutput += message;
|
|
||||||
// If console output is enabled, print the message directly to the stderr. Note that
|
|
||||||
// we intentionally print all output to stderr as stdout should not be polluted.
|
|
||||||
if (outputMode === undefined || outputMode === 'enabled') {
|
|
||||||
process.stderr.write(message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
childProcess.on('exit', function (exitCode, signal) {
|
|
||||||
var exitDescription = exitCode !== null ? "exit code \"" + exitCode + "\"" : "signal \"" + signal + "\"";
|
|
||||||
var printFn = outputMode === 'on-error' ? error : debug;
|
|
||||||
var status = statusFromExitCodeAndSignal(exitCode, signal);
|
|
||||||
printFn("Command \"" + commandText + "\" completed with " + exitDescription + ".");
|
|
||||||
printFn("Process output: \n" + logOutput);
|
|
||||||
// On success, resolve the promise. Otherwise reject with the captured stderr
|
|
||||||
// and stdout log output if the output mode was set to `silent`.
|
|
||||||
if (status === 0 || options.suppressErrorOnFailingExitCode) {
|
|
||||||
resolve({ stdout: stdout, stderr: stderr, status: status });
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reject(outputMode === 'silent' ? logOutput : undefined);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/** Convert the provided exitCode and signal to a single status code. */
|
|
||||||
function statusFromExitCodeAndSignal(exitCode, signal) {
|
|
||||||
return exitCode !== null ? exitCode : signal !== null ? signal : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @license
|
* @license
|
||||||
* Copyright Google LLC All Rights Reserved.
|
* Copyright Google LLC All Rights Reserved.
|
||||||
|
@ -7655,20 +7662,17 @@ const ReleaseSetDistTagCommand = {
|
||||||
*/
|
*/
|
||||||
function buildEnvStamp(mode) {
|
function buildEnvStamp(mode) {
|
||||||
console.info(`BUILD_SCM_BRANCH ${getCurrentBranch()}`);
|
console.info(`BUILD_SCM_BRANCH ${getCurrentBranch()}`);
|
||||||
console.info(`BUILD_SCM_COMMIT_SHA ${getCurrentSha()}`);
|
console.info(`BUILD_SCM_COMMIT_SHA ${getCurrentBranchOrRevision()}`);
|
||||||
console.info(`BUILD_SCM_HASH ${getCurrentSha()}`);
|
console.info(`BUILD_SCM_HASH ${getCurrentBranchOrRevision()}`);
|
||||||
console.info(`BUILD_SCM_LOCAL_CHANGES ${hasLocalChanges()}`);
|
console.info(`BUILD_SCM_LOCAL_CHANGES ${hasLocalChanges()}`);
|
||||||
console.info(`BUILD_SCM_USER ${getCurrentGitUser()}`);
|
console.info(`BUILD_SCM_USER ${getCurrentGitUser()}`);
|
||||||
console.info(`BUILD_SCM_VERSION ${getSCMVersion(mode)}`);
|
console.info(`BUILD_SCM_VERSION ${getSCMVersion(mode)}`);
|
||||||
process.exit(0);
|
process.exit();
|
||||||
}
|
|
||||||
/** Run the exec command and return the stdout as a trimmed string. */
|
|
||||||
function exec$1(cmd) {
|
|
||||||
return exec(cmd).trim();
|
|
||||||
}
|
}
|
||||||
/** Whether the repo has local changes. */
|
/** Whether the repo has local changes. */
|
||||||
function hasLocalChanges() {
|
function hasLocalChanges() {
|
||||||
return !!exec$1(`git status --untracked-files=no --porcelain`);
|
const git = GitClient.get();
|
||||||
|
return git.hasUncommittedChanges();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Get the version for generated packages.
|
* Get the version for generated packages.
|
||||||
|
@ -7677,30 +7681,34 @@ function hasLocalChanges() {
|
||||||
* In release mode, the version is based on the base package.json version.
|
* In release mode, the version is based on the base package.json version.
|
||||||
*/
|
*/
|
||||||
function getSCMVersion(mode) {
|
function getSCMVersion(mode) {
|
||||||
|
const git = GitClient.get();
|
||||||
if (mode === 'release') {
|
if (mode === 'release') {
|
||||||
const git = GitClient.get();
|
|
||||||
const packageJsonPath = path.join(git.baseDir, 'package.json');
|
const packageJsonPath = path.join(git.baseDir, 'package.json');
|
||||||
const { version } = require(packageJsonPath);
|
const { version } = require(packageJsonPath);
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
if (mode === 'snapshot') {
|
if (mode === 'snapshot') {
|
||||||
const version = exec$1(`git describe --match [0-9]*.[0-9]*.[0-9]* --abbrev=7 --tags HEAD`);
|
const version = git.run(['describe', '--match', '[0-9]*.[0-9]*.[0-9]*', '--abbrev=7', '--tags', 'HEAD'])
|
||||||
|
.stdout.trim();
|
||||||
return `${version.replace(/-([0-9]+)-g/, '+$1.sha-')}${(hasLocalChanges() ? '.with-local-changes' : '')}`;
|
return `${version.replace(/-([0-9]+)-g/, '+$1.sha-')}${(hasLocalChanges() ? '.with-local-changes' : '')}`;
|
||||||
}
|
}
|
||||||
return '0.0.0';
|
return '0.0.0';
|
||||||
}
|
}
|
||||||
/** Get the current SHA of HEAD. */
|
/** Get the current branch or revision of HEAD. */
|
||||||
function getCurrentSha() {
|
function getCurrentBranchOrRevision() {
|
||||||
return exec$1(`git rev-parse HEAD`);
|
const git = GitClient.get();
|
||||||
|
return git.getCurrentBranchOrRevision();
|
||||||
}
|
}
|
||||||
/** Get the currently checked out branch. */
|
/** Get the currently checked out branch. */
|
||||||
function getCurrentBranch() {
|
function getCurrentBranch() {
|
||||||
return exec$1(`git symbolic-ref --short HEAD`);
|
const git = GitClient.get();
|
||||||
|
return git.run(['symbolic-ref', '--short', 'HEAD']).stdout.trim();
|
||||||
}
|
}
|
||||||
/** Get the current git user based on the git config. */
|
/** Get the current git user based on the git config. */
|
||||||
function getCurrentGitUser() {
|
function getCurrentGitUser() {
|
||||||
const userName = exec$1(`git config user.name`);
|
const git = GitClient.get();
|
||||||
const userEmail = exec$1(`git config user.email`);
|
let userName = git.runGraceful(['config', 'user.name']).stdout.trim() || 'Unknown User';
|
||||||
|
let userEmail = git.runGraceful(['config', 'user.email']).stdout.trim() || 'unknown_email';
|
||||||
return `${userName} <${userEmail}>`;
|
return `${userName} <${userEmail}>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8187,8 +8195,8 @@ function handler$e({ projectRoot }) {
|
||||||
}
|
}
|
||||||
info(chalk.green(` ✓ Built release output.`));
|
info(chalk.green(` ✓ Built release output.`));
|
||||||
for (const { outputPath, name } of releaseOutputs) {
|
for (const { outputPath, name } of releaseOutputs) {
|
||||||
exec(`yarn link --cwd ${outputPath}`);
|
yield spawn('yarn', ['link', '--cwd', outputPath]);
|
||||||
exec(`yarn link --cwd ${projectRoot} ${name}`);
|
yield spawn('yarn', ['link', '--cwd', projectRoot, name]);
|
||||||
}
|
}
|
||||||
info(chalk.green(` ✓ Linked release packages in provided project.`));
|
info(chalk.green(` ✓ Linked release packages in provided project.`));
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,7 +11,6 @@ ts_library(
|
||||||
"//dev-infra/utils",
|
"//dev-infra/utils",
|
||||||
"@npm//@types/cli-progress",
|
"@npm//@types/cli-progress",
|
||||||
"@npm//@types/node",
|
"@npm//@types/node",
|
||||||
"@npm//@types/shelljs",
|
|
||||||
"@npm//@types/yargs",
|
"@npm//@types/yargs",
|
||||||
"@npm//typed-graphqlify",
|
"@npm//typed-graphqlify",
|
||||||
],
|
],
|
||||||
|
|
|
@ -13,7 +13,6 @@ import {error, info} from '../../utils/console';
|
||||||
import {AuthenticatedGitClient} from '../../utils/git/authenticated-git-client';
|
import {AuthenticatedGitClient} from '../../utils/git/authenticated-git-client';
|
||||||
import {GitCommandError} from '../../utils/git/git-client';
|
import {GitCommandError} from '../../utils/git/git-client';
|
||||||
import {getPendingPrs} from '../../utils/github';
|
import {getPendingPrs} from '../../utils/github';
|
||||||
import {exec} from '../../utils/shelljs';
|
|
||||||
|
|
||||||
|
|
||||||
/* Graphql schema for the response body for each pending PR. */
|
/* Graphql schema for the response body for each pending PR. */
|
||||||
|
@ -125,8 +124,9 @@ export async function discoverNewConflictsForPr(newPrNumber: number, updatedAfte
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof GitCommandError) {
|
if (err instanceof GitCommandError) {
|
||||||
conflicts.push(pr);
|
conflicts.push(pr);
|
||||||
|
} else {
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
// Abort any outstanding rebase attempt.
|
// Abort any outstanding rebase attempt.
|
||||||
git.runGraceful(['rebase', '--abort'], {stdio: 'ignore'});
|
git.runGraceful(['rebase', '--abort'], {stdio: 'ignore'});
|
||||||
|
@ -138,7 +138,7 @@ export async function discoverNewConflictsForPr(newPrNumber: number, updatedAfte
|
||||||
info();
|
info();
|
||||||
info(`Result:`);
|
info(`Result:`);
|
||||||
|
|
||||||
cleanUpGitState(previousBranchOrRevision);
|
git.checkout(previousBranchOrRevision, true);
|
||||||
|
|
||||||
// If no conflicts are found, exit successfully.
|
// If no conflicts are found, exit successfully.
|
||||||
if (conflicts.length === 0) {
|
if (conflicts.length === 0) {
|
||||||
|
@ -154,15 +154,3 @@ export async function discoverNewConflictsForPr(newPrNumber: number, updatedAfte
|
||||||
error.groupEnd();
|
error.groupEnd();
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reset git back to the provided branch or revision. */
|
|
||||||
export function cleanUpGitState(previousBranchOrRevision: string) {
|
|
||||||
// Ensure that any outstanding rebases are aborted.
|
|
||||||
exec(`git rebase --abort`);
|
|
||||||
// Ensure that any changes in the current repo state are cleared.
|
|
||||||
exec(`git reset --hard`);
|
|
||||||
// Checkout the original branch from before the run began.
|
|
||||||
exec(`git checkout ${previousBranchOrRevision}`);
|
|
||||||
// Delete the generated branch.
|
|
||||||
exec(`git branch -D ${tempWorkingBranch}`);
|
|
||||||
}
|
|
||||||
|
|
|
@ -17,11 +17,9 @@ ts_library(
|
||||||
"//dev-infra/utils",
|
"//dev-infra/utils",
|
||||||
"@npm//@types/minimatch",
|
"@npm//@types/minimatch",
|
||||||
"@npm//@types/node",
|
"@npm//@types/node",
|
||||||
"@npm//@types/shelljs",
|
|
||||||
"@npm//@types/yaml",
|
"@npm//@types/yaml",
|
||||||
"@npm//@types/yargs",
|
"@npm//@types/yargs",
|
||||||
"@npm//minimatch",
|
"@npm//minimatch",
|
||||||
"@npm//shelljs",
|
|
||||||
"@npm//yaml",
|
"@npm//yaml",
|
||||||
"@npm//yargs",
|
"@npm//yargs",
|
||||||
],
|
],
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
import {join} from 'path';
|
import {join} from 'path';
|
||||||
import {GitClient} from '../../utils/git/git-client';
|
import {GitClient} from '../../utils/git/git-client';
|
||||||
|
|
||||||
import {exec as _exec} from '../../utils/shelljs';
|
|
||||||
|
|
||||||
export type EnvStampMode = 'snapshot'|'release';
|
export type EnvStampMode = 'snapshot'|'release';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,22 +23,18 @@ export type EnvStampMode = 'snapshot'|'release';
|
||||||
*/
|
*/
|
||||||
export function buildEnvStamp(mode: EnvStampMode) {
|
export function buildEnvStamp(mode: EnvStampMode) {
|
||||||
console.info(`BUILD_SCM_BRANCH ${getCurrentBranch()}`);
|
console.info(`BUILD_SCM_BRANCH ${getCurrentBranch()}`);
|
||||||
console.info(`BUILD_SCM_COMMIT_SHA ${getCurrentSha()}`);
|
console.info(`BUILD_SCM_COMMIT_SHA ${getCurrentBranchOrRevision()}`);
|
||||||
console.info(`BUILD_SCM_HASH ${getCurrentSha()}`);
|
console.info(`BUILD_SCM_HASH ${getCurrentBranchOrRevision()}`);
|
||||||
console.info(`BUILD_SCM_LOCAL_CHANGES ${hasLocalChanges()}`);
|
console.info(`BUILD_SCM_LOCAL_CHANGES ${hasLocalChanges()}`);
|
||||||
console.info(`BUILD_SCM_USER ${getCurrentGitUser()}`);
|
console.info(`BUILD_SCM_USER ${getCurrentGitUser()}`);
|
||||||
console.info(`BUILD_SCM_VERSION ${getSCMVersion(mode)}`);
|
console.info(`BUILD_SCM_VERSION ${getSCMVersion(mode)}`);
|
||||||
process.exit(0);
|
process.exit();
|
||||||
}
|
|
||||||
|
|
||||||
/** Run the exec command and return the stdout as a trimmed string. */
|
|
||||||
function exec(cmd: string) {
|
|
||||||
return _exec(cmd).trim();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether the repo has local changes. */
|
/** Whether the repo has local changes. */
|
||||||
function hasLocalChanges() {
|
function hasLocalChanges() {
|
||||||
return !!exec(`git status --untracked-files=no --porcelain`);
|
const git = GitClient.get();
|
||||||
|
return git.hasUncommittedChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,34 +44,38 @@ function hasLocalChanges() {
|
||||||
* In release mode, the version is based on the base package.json version.
|
* In release mode, the version is based on the base package.json version.
|
||||||
*/
|
*/
|
||||||
function getSCMVersion(mode: EnvStampMode) {
|
function getSCMVersion(mode: EnvStampMode) {
|
||||||
|
const git = GitClient.get();
|
||||||
if (mode === 'release') {
|
if (mode === 'release') {
|
||||||
const git = GitClient.get();
|
|
||||||
const packageJsonPath = join(git.baseDir, 'package.json');
|
const packageJsonPath = join(git.baseDir, 'package.json');
|
||||||
const {version} = require(packageJsonPath);
|
const {version} = require(packageJsonPath);
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
if (mode === 'snapshot') {
|
if (mode === 'snapshot') {
|
||||||
const version = exec(`git describe --match [0-9]*.[0-9]*.[0-9]* --abbrev=7 --tags HEAD`);
|
const version =
|
||||||
|
git.run(['describe', '--match', '[0-9]*.[0-9]*.[0-9]*', '--abbrev=7', '--tags', 'HEAD'])
|
||||||
|
.stdout.trim();
|
||||||
return `${version.replace(/-([0-9]+)-g/, '+$1.sha-')}${
|
return `${version.replace(/-([0-9]+)-g/, '+$1.sha-')}${
|
||||||
(hasLocalChanges() ? '.with-local-changes' : '')}`;
|
(hasLocalChanges() ? '.with-local-changes' : '')}`;
|
||||||
}
|
}
|
||||||
return '0.0.0';
|
return '0.0.0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the current SHA of HEAD. */
|
/** Get the current branch or revision of HEAD. */
|
||||||
function getCurrentSha() {
|
function getCurrentBranchOrRevision() {
|
||||||
return exec(`git rev-parse HEAD`);
|
const git = GitClient.get();
|
||||||
|
return git.getCurrentBranchOrRevision();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the currently checked out branch. */
|
/** Get the currently checked out branch. */
|
||||||
function getCurrentBranch() {
|
function getCurrentBranch() {
|
||||||
return exec(`git symbolic-ref --short HEAD`);
|
const git = GitClient.get();
|
||||||
|
return git.run(['symbolic-ref', '--short', 'HEAD']).stdout.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the current git user based on the git config. */
|
/** Get the current git user based on the git config. */
|
||||||
function getCurrentGitUser() {
|
function getCurrentGitUser() {
|
||||||
const userName = exec(`git config user.name`);
|
const git = GitClient.get();
|
||||||
const userEmail = exec(`git config user.email`);
|
let userName = git.runGraceful(['config', 'user.name']).stdout.trim() || 'Unknown User';
|
||||||
|
let userEmail = git.runGraceful(['config', 'user.email']).stdout.trim() || 'unknown_email';
|
||||||
return `${userName} <${userEmail}>`;
|
return `${userName} <${userEmail}>`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
"protractor": "<from-root>",
|
"protractor": "<from-root>",
|
||||||
"selenium-webdriver": "<from-root>",
|
"selenium-webdriver": "<from-root>",
|
||||||
"semver": "<from-root>",
|
"semver": "<from-root>",
|
||||||
"shelljs": "<from-root>",
|
|
||||||
"ts-node": "<from-root>",
|
"ts-node": "<from-root>",
|
||||||
"tslib": "<from-root>",
|
"tslib": "<from-root>",
|
||||||
"typed-graphqlify": "<from-root>",
|
"typed-graphqlify": "<from-root>",
|
||||||
|
|
|
@ -21,12 +21,10 @@ ts_library(
|
||||||
"@npm//@types/inquirer",
|
"@npm//@types/inquirer",
|
||||||
"@npm//@types/node",
|
"@npm//@types/node",
|
||||||
"@npm//@types/semver",
|
"@npm//@types/semver",
|
||||||
"@npm//@types/shelljs",
|
|
||||||
"@npm//@types/yargs",
|
"@npm//@types/yargs",
|
||||||
"@npm//chalk",
|
"@npm//chalk",
|
||||||
"@npm//inquirer",
|
"@npm//inquirer",
|
||||||
"@npm//semver",
|
"@npm//semver",
|
||||||
"@npm//shelljs",
|
|
||||||
"@npm//tslib",
|
"@npm//tslib",
|
||||||
"@npm//typed-graphqlify",
|
"@npm//typed-graphqlify",
|
||||||
"@npm//yargs",
|
"@npm//yargs",
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {spawn as _spawn, SpawnOptions as _SpawnOptions, spawnSync as _spawnSync,
|
||||||
import {debug, error} from './console';
|
import {debug, error} from './console';
|
||||||
|
|
||||||
|
|
||||||
|
/** Interface describing the options for spawning a process synchronously. */
|
||||||
export interface SpawnSyncOptions extends Omit<_SpawnSyncOptions, 'shell'|'stdio'> {
|
export interface SpawnSyncOptions extends Omit<_SpawnSyncOptions, 'shell'|'stdio'> {
|
||||||
/** Whether to prevent exit codes being treated as failures. */
|
/** Whether to prevent exit codes being treated as failures. */
|
||||||
suppressErrorOnFailingExitCode?: boolean;
|
suppressErrorOnFailingExitCode?: boolean;
|
||||||
|
@ -58,7 +59,7 @@ export function spawnInteractive(
|
||||||
* output mode, stdout/stderr output is also printed to the console, or only on error.
|
* output mode, stdout/stderr output is also printed to the console, or only on error.
|
||||||
*
|
*
|
||||||
* @returns a Promise resolving with captured stdout and stderr on success. The promise
|
* @returns a Promise resolving with captured stdout and stderr on success. The promise
|
||||||
* rejects on command failure
|
* rejects on command failure.
|
||||||
*/
|
*/
|
||||||
export function spawn(
|
export function spawn(
|
||||||
command: string, args: string[], options: SpawnOptions = {}): Promise<SpawnResult> {
|
command: string, args: string[], options: SpawnOptions = {}): Promise<SpawnResult> {
|
||||||
|
@ -115,12 +116,12 @@ export function spawn(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawns a given command with the specified arguments inside a shell syncronously.
|
* Spawns a given command with the specified arguments inside a shell synchronously.
|
||||||
*
|
*
|
||||||
* @returns The command's stdout and stderr.
|
* @returns The command's stdout and stderr.
|
||||||
*/
|
*/
|
||||||
export function spawnSync(
|
export function spawnSync(
|
||||||
command: string, args: string[], options: SpawnOptions = {}): SpawnResult {
|
command: string, args: string[], options: SpawnSyncOptions = {}): SpawnResult {
|
||||||
const commandText = `${command} ${args.join(' ')}`;
|
const commandText = `${command} ${args.join(' ')}`;
|
||||||
debug(`Executing command: ${commandText}`);
|
debug(`Executing command: ${commandText}`);
|
||||||
|
|
||||||
|
@ -137,9 +138,14 @@ export function spawnSync(
|
||||||
throw new Error(stderr);
|
throw new Error(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the provided exitCode and signal to a single status code.
|
||||||
/** Convert the provided exitCode and signal to a single status code. */
|
*
|
||||||
|
* During `exit` node provides either a `code` or `signal`, one of which is guaranteed to be
|
||||||
|
* non-null.
|
||||||
|
*
|
||||||
|
* For more details see: https://nodejs.org/api/child_process.html#child_process_event_exit
|
||||||
|
*/
|
||||||
function statusFromExitCodeAndSignal(exitCode: number|null, signal: NodeJS.Signals|null) {
|
function statusFromExitCodeAndSignal(exitCode: number|null, signal: NodeJS.Signals|null) {
|
||||||
return exitCode !== null ? exitCode : signal !== null ? signal : -1;
|
return exitCode ?? signal ?? -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,10 @@ export class GitCommandError extends Error {
|
||||||
// accidentally leak the Github token that might be used in a command,
|
// accidentally leak the Github token that might be used in a command,
|
||||||
// we sanitize the command that will be part of the error message.
|
// we sanitize the command that will be part of the error message.
|
||||||
super(`Command failed: git ${client.sanitizeConsoleOutput(args.join(' '))}`);
|
super(`Command failed: git ${client.sanitizeConsoleOutput(args.join(' '))}`);
|
||||||
|
|
||||||
|
// Set the prototype explicitly because in ES5, the prototype is accidentally lost due to
|
||||||
|
// a limitation in down-leveling.
|
||||||
|
// https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work.
|
||||||
Object.setPrototypeOf(this, GitCommandError.prototype);
|
Object.setPrototypeOf(this, GitCommandError.prototype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
/**
|
|
||||||
* @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
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {exec as _exec, ExecOptions, ShellString} from 'shelljs';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs an given command as child process. By default, child process
|
|
||||||
* output will not be printed.
|
|
||||||
*/
|
|
||||||
export function exec(cmd: string, opts?: Omit<ExecOptions, 'async'>): ShellString {
|
|
||||||
return _exec(cmd, {silent: true, ...opts, async: false});
|
|
||||||
}
|
|
Loading…
Reference in New Issue