build: initial release staging script (#13621)

This commit is contained in:
Paul Gschwendtner
2018-10-17 16:05:58 +02:00
committed by Joey Perrott
parent 97703be459
commit aaac266c6d
11 changed files with 652 additions and 6 deletions
+4 -1
View File
@@ -23,7 +23,8 @@
"docs": "gulp docs",
"api": "gulp api-docs",
"breaking-changes": "gulp breaking-changes",
"gulp": "gulp"
"gulp": "gulp",
"stage-release": "bash ./tools/release/stage-release-bin.sh"
},
"version": "7.0.0-rc.2",
"requiredAngularVersion": ">=7.0.0-rc.0",
@@ -65,6 +66,7 @@
"@types/gulp": "3.8.32",
"@types/gulp-util": "^3.0.34",
"@types/hammerjs": "^2.0.35",
"@types/inquirer": "^0.0.43",
"@types/jasmine": "^2.8.8",
"@types/merge2": "^0.3.30",
"@types/minimist": "^1.2.0",
@@ -104,6 +106,7 @@
"hammerjs": "^2.0.8",
"highlight.js": "^9.11.0",
"http-rewrite-middleware": "^0.1.6",
"inquirer": "^6.2.0",
"jasmine-core": "^3.2.0",
"karma": "^3.0.0",
"karma-browserstack-launcher": "^1.3.0",
+25
View File
@@ -0,0 +1,25 @@
package(default_visibility=["//visibility:public"])
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
ts_library(
name = "release-sources",
srcs = glob(["**/*.ts"]),
deps = [
"@npm//@types/node",
"@npm//@types/inquirer",
"@npm//chalk",
"@npm//inquirer"
],
tsconfig = ":tsconfig.json"
)
nodejs_binary(
name = "stage-release",
data = [
"@npm//source-map-support",
":release-sources",
],
entry_point = "angular_material/tools/release/stage-release.js",
)
+51
View File
@@ -0,0 +1,51 @@
import {spawnSync} from 'child_process';
/**
* Class that can be used to execute Git commands within a given project directory.
*
* Relying on the working directory of the current process is not good because it's not
* guaranteed that the working directory is always the target project directory.
*/
export class GitClient {
constructor(public projectDir: string, public remoteGitUrl: string) {}
/** Gets the currently checked out branch for the project directory. */
getCurrentBranch() {
return spawnSync('git', ['symbolic-ref', '--short', 'HEAD'], {cwd: this.projectDir})
.stdout.toString().trim();
}
/** Gets the commit SHA for the specified remote repository branch. */
getRemoteCommitSha(branchName: string): string {
return spawnSync('git', ['ls-remote', this.remoteGitUrl, '-h', `refs/heads/${branchName}`],
{cwd: this.projectDir}).stdout.toString().trim();
}
/** Gets the latest commit SHA for the specified git reference. */
getLocalCommitSha(refName: string) {
return spawnSync('git', ['rev-parse', refName], {cwd: this.projectDir})
.stdout.toString().trim();
}
/** Gets whether the current Git repository has uncommitted changes. */
hasUncommittedChanges(): boolean {
return spawnSync('git', ['diff-index', '--quiet', 'HEAD'], {cwd: this.projectDir}).status !== 0;
}
/** Creates a new branch which is based on the previous active branch. */
checkoutNewBranch(branchName: string): boolean {
return spawnSync('git', ['checkout', '-b', branchName], {cwd: this.projectDir}).status === 0;
}
/** Stages all changes by running `git add -A`. */
stageAllChanges(): boolean {
return spawnSync('git', ['add', '-A'], {cwd: this.projectDir}).status === 0;
}
/** Creates a new commit within the current branch with the given commit message. */
createNewCommit(message: string): boolean {
return spawnSync('git', ['commit', '-m', message], {cwd: this.projectDir}).status === 0;
}
}
@@ -0,0 +1,57 @@
import {ChoiceType, prompt, Separator} from 'inquirer';
import {createNewVersion, ReleaseType} from '../version-name/create-version';
import {parseVersionName, Version} from '../version-name/parse-version';
/** Answers that will be prompted for. */
type VersionPromptAnswers = {
versionName: string;
manualCustomVersion: string;
};
/**
* Prompts the current user-input interface for a new version name. The new version will be
* validated to be a proper increment of the specified current version.
*/
export async function promptForNewVersion(currentVersion: Version): Promise<Version> {
const versionChoices: ChoiceType[] = [
new Separator(),
{value: 'custom-release', name: 'Release w/ custom version'}
];
if (currentVersion.prereleaseLabel) {
versionChoices.unshift(
createVersionChoice(currentVersion, 'pre-release', 'Pre-release'),
createVersionChoice(currentVersion, 'stable-release', 'Stable release'));
} else {
versionChoices.unshift(
createVersionChoice(currentVersion, 'major', 'Major release'),
createVersionChoice(currentVersion, 'minor', 'Minor release'),
createVersionChoice(currentVersion, 'patch', 'Patch release'));
}
const answers = await prompt<VersionPromptAnswers>([{
type: 'list',
name: 'versionName',
message: `What's the type of the new release?`,
choices: versionChoices,
}, {
type: 'input',
name: 'manualCustomVersion',
message: 'Please provide a custom release name:',
validate: enteredVersion =>
!!parseVersionName(enteredVersion) || 'This is not a valid Semver version',
when: ({versionName}) => versionName === 'custom-release'
}]);
return parseVersionName(answers.manualCustomVersion || answers.versionName);
}
/** Creates a new choice for selecting a version inside of an Inquirer list prompt. */
function createVersionChoice(currentVersion: Version, releaseType: ReleaseType, message: string) {
const versionName = createNewVersion(currentVersion, releaseType).format();
return {
value: versionName,
name: `${message} (${versionName})`
};
}
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
# Script that builds and launches the stage release script through Bazel. An additional script is
# needed because environment variables (like $PWD) are not being interpolated within NPM scripts.
# Go to project directory.
cd $(dirname ${0})/../..
# Build and run the stage release script.
bazel run //tools/release:stage-release -- $PWD
+184
View File
@@ -0,0 +1,184 @@
import {bold, cyan, green, italic, red, yellow} from 'chalk';
import {existsSync, readFileSync, writeFileSync} from 'fs';
import {prompt} from 'inquirer';
import {join} from 'path';
import {GitClient} from './git/git-client';
import {promptForNewVersion} from './prompt/new-version-prompt';
import {parseVersionName, Version} from './version-name/parse-version';
import {getExpectedPublishBranch} from './version-name/publish-branch';
/**
* Class that can be instantiated in order to stage a new release. The tasks requires user
* interaction/input through command line prompts.
*
* Staging a release involves the following the steps:
*
* 1) Prompt for release type (with version suggestion)
* 2) Prompt for version name if no suggestions has been selected
* 3) Assert that the proper publish branch is checked out (e.g. 6.4.x for patches)
* 4) Assert that there are no local changes which are uncommitted.
* 5) Assert that the local branch is up to date with the remote branch.
* 6) Creates a new branch for the release staging (release-stage/{VERSION})
* 7) Switches to the staging branch and updates the package.json
* 8) Waits for the user to continue (users can generate the changelog in the meanwhile)
* 9) Create a commit that includes all changes in the staging branch.
*/
class StageReleaseTask {
/** Path to the project package JSON. */
packageJsonPath: string;
/** Serialized package.json of the specified project. */
packageJson: any;
/** Parsed current version of the project. */
currentVersion: Version;
/** Instance of a wrapper that can execute Git commands. */
git: GitClient;
constructor(public projectDir: string) {
this.packageJsonPath = join(projectDir, 'package.json');
console.log(this.projectDir);
if (!existsSync(this.packageJsonPath)) {
console.error(red(`The specified directory is not referring to a project directory. ` +
`There must be a ${italic('package.json')} file in the project directory.`));
process.exit(1);
}
this.packageJson = JSON.parse(readFileSync(this.packageJsonPath, 'utf-8'));
this.currentVersion = parseVersionName(this.packageJson.version);
if (!this.currentVersion) {
console.error(red(`Cannot parse current version in ${italic('package.json')}. Please ` +
`make sure "${this.packageJson.version}" is a valid Semver version.`));
process.exit(1);
}
this.git = new GitClient(projectDir, this.packageJson.repository.url);
}
async run() {
console.log();
console.log(cyan('-----------------------------------------'));
console.log(cyan(' Angular Material stage release script'));
console.log(cyan('-----------------------------------------'));
console.log();
const newVersion = await promptForNewVersion(this.currentVersion);
const expectedPublishBranch = getExpectedPublishBranch(newVersion);
// After the prompt for the new version, we print a new line because we want the
// new log messages to be more in the foreground.
console.log();
this.verifyPublishBranch(expectedPublishBranch);
this.verifyLocalCommitsMatchUpstream(expectedPublishBranch);
this.verifyNoUncommittedChanges();
// TODO(devversion): Assert that GitHub statuses succeed for this branch.
const newVersionName = newVersion.format();
const stagingBranch = `release-stage/${newVersionName}`;
if (!this.git.checkoutNewBranch(stagingBranch)) {
console.error(red(`Could not create release staging branch: ${stagingBranch}. Aborting...`));
process.exit(1);
}
this.updatePackageJsonVersion(newVersionName);
console.log(green(` ✓ Updated the version to "${bold(newVersionName)}" inside of the ` +
`${italic('package.json')}`));
// TODO(devversion): run changelog script w/prompts in the future.
// For now, we just let users make modifications and stage the changes.
console.log(yellow(` ⚠ Please generate the ${bold('CHANGELOG')} for the new version. ` +
`You can also make other unrelated modifications. After the changes have been made, ` +
`just continue here.`));
console.log();
const {shouldContinue} = await prompt<{shouldContinue: boolean}>({
type: 'confirm',
name: 'shouldContinue',
message: 'Do you want to proceed and commit the changes?'
});
if (!shouldContinue) {
console.log();
console.log(yellow('Aborting release staging...'));
process.exit(1);
}
this.git.stageAllChanges();
// this.git.createNewCommit(`chore: bump version to ${newVersionName} w/ changelog`);
console.info();
console.info(green(` ✓ Created the staging commit for: "${newVersionName}".`));
console.info(green(` ✓ Please push the changes and submit a PR on GitHub.`));
console.info();
// TODO(devversion): automatic push and PR open URL shortcut.
}
/** Verifies that the user is on the specified publish branch. */
private verifyPublishBranch(expectedPublishBranch: string) {
const currentBranchName = this.git.getCurrentBranch();
// Check if current branch matches the expected publish branch.
if (expectedPublishBranch !== currentBranchName) {
console.error(red(`Cannot stage release from "${italic(currentBranchName)}". Please stage ` +
`the release from "${bold(expectedPublishBranch)}".`));
process.exit(1);
}
}
/** Verifies that the local branch is up to date with the given publish branch. */
private verifyLocalCommitsMatchUpstream(publishBranch: string) {
const upstreamCommitSha = this.git.getRemoteCommitSha(publishBranch);
const localCommitSha = this.git.getLocalCommitSha('HEAD');
// Check if the current branch is in sync with the remote branch.
if (upstreamCommitSha !== localCommitSha) {
console.error(red(`Cannot stage release. The current branch is not in sync with the remote ` +
`branch. Please make sure your local branch "${italic(publishBranch)}" is up to date.`));
process.exit(1);
}
}
/** Verifies that there are no uncommitted changes in the project. */
private verifyNoUncommittedChanges() {
if (this.git.hasUncommittedChanges()) {
console.error(red(`Cannot stage release. There are changes which are not committed and ` +
`should be stashed.`));
process.exit(1);
}
}
/** Updates the version of the project package.json and writes the changes to disk. */
private updatePackageJsonVersion(newVersionName: string) {
const newPackageJson = {...this.packageJson, version: newVersionName};
writeFileSync(this.packageJsonPath, JSON.stringify(newPackageJson, null, 2));
}
}
/** Entry-point for the release staging script. */
async function main() {
const projectDir = process.argv.slice(2)[0];
if (!projectDir) {
console.error(red(`You specified no project directory. Cannot run stage release script.`));
console.error(red(`Usage: bazel run //tools/release:stage-release <project-directory>`));
process.exit(1);
}
return new StageReleaseTask(projectDir).run();
}
if (require.main === module) {
main();
}
+6
View File
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"lib": ["es2015"],
"types": ["node"]
}
}
@@ -0,0 +1,34 @@
import {Version} from './parse-version';
import {VersionType} from './publish-branch';
/** Type of a new release */
export type ReleaseType = VersionType | 'stable-release' | 'pre-release' | 'custom-release';
/** Creates a new version that can be used for the given release type. */
export function createNewVersion(currentVersion: Version, releaseType: ReleaseType):
Version {
// Clone the version object in order to keep the original version info un-modified.
const newVersion = currentVersion.clone();
if (releaseType === 'pre-release') {
newVersion.prereleaseNumber++;
} else {
// For all other release types, the pre-release label and number should be removed
// because the new version is not another pre-release.
newVersion.prereleaseLabel = null;
newVersion.prereleaseNumber = null;
}
if (releaseType === 'major') {
newVersion.major++;
newVersion.minor = 0;
newVersion.patch = 0;
} else if (releaseType === 'minor') {
newVersion.minor++;
newVersion.patch = 0;
} else if (releaseType === 'patch') {
newVersion.patch++;
}
return newVersion;
}
@@ -0,0 +1,59 @@
/** Regular expression that matches version names and the individual version segments. */
const versionNameRegex = /^(\d+)\.(\d+)\.(\d+)(?:-(alpha|beta|rc)\.(\d)+)?$/;
export class Version {
constructor(
/** Major version number */
public major: number,
/** Minor version number */
public minor: number,
/** Patch version number */
public patch: number,
/** Pre-release label for the version (e.g. alpha, beta, rc) */
public prereleaseLabel?: string,
/** Number for the pre-release. There can be multiple pre-releases for a version. */
public prereleaseNumber?: number) {}
/** Serializes the version info into a string formatted version name. */
format(): string {
return serializeVersion(this);
}
clone(): Version {
return new Version(this.major, this.minor, this.patch, this.prereleaseLabel,
this.prereleaseNumber);
}
}
/**
* Parses the specified version and returns an object that represents the individual
* version segments.
*/
export function parseVersionName(version: string): Version | null {
const matches = version.match(versionNameRegex);
if (!matches) {
return null;
}
return new Version(
Number(matches[1]),
Number(matches[2]),
Number(matches[3]),
matches[4],
Number(matches[5]));
}
/** Serializes the specified version into a string. */
export function serializeVersion(newVersion: Version): string {
const {major, minor, patch, prereleaseLabel, prereleaseNumber} = newVersion;
let versionString = `${major}.${minor}.${patch}`;
if (prereleaseLabel && prereleaseNumber) {
versionString += `-${prereleaseLabel}.${prereleaseNumber}`;
}
return versionString;
}
@@ -0,0 +1,27 @@
import {Version} from './parse-version';
export type VersionType = 'major' | 'minor' | 'patch';
/** Determines the expected branch name for publishing the specified version. */
export function getExpectedPublishBranch(version: Version): string {
const versionType = getSemverVersionType(version);
if (versionType === 'major') {
return 'master';
} else if (versionType === 'minor') {
return `${version.major}.x`;
} else if (versionType === 'patch') {
return `${version.major}.${version.minor}.x`;
}
}
/** Determines the type of the specified Semver version. */
export function getSemverVersionType(version: Version): VersionType {
if (version.minor === 0 && version.patch === 0) {
return 'major';
} else if (version.patch === 0) {
return 'minor';
} else {
return 'patch';
}
}
+195 -5
View File
@@ -720,6 +720,14 @@
resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.36.tgz#17ce0a235e9ffbcdcdf5095646b374c2bf615a4c"
integrity sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ==
"@types/inquirer@^0.0.43":
version "0.0.43"
resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-0.0.43.tgz#1eb0bbb4648e6cc568bd396c1e989f620ad01273"
integrity sha512-xgyfKZVMFqE8aIKy1xfFVsX2MxyXUNgjgmbF6dRbR3sL+ZM5K4ka/9L4mmTwX8eTeVYtduyXu0gUVwVJa1HbNw==
dependencies:
"@types/rx" "*"
"@types/through" "*"
"@types/jasmine@^2.8.8":
version "2.8.9"
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.8.9.tgz#e028c891e8551fdf6de905d959581fc4fa0b5509"
@@ -815,6 +823,107 @@
"@types/gulp" "*"
"@types/node" "*"
"@types/rx-core-binding@*":
version "4.0.4"
resolved "https://registry.yarnpkg.com/@types/rx-core-binding/-/rx-core-binding-4.0.4.tgz#d969d32f15a62b89e2862c17b3ee78fe329818d3"
integrity sha512-5pkfxnC4w810LqBPUwP5bg7SFR/USwhMSaAeZQQbEHeBp57pjKXRlXmqpMrLJB4y1oglR/c2502853uN0I+DAQ==
dependencies:
"@types/rx-core" "*"
"@types/rx-core@*":
version "4.0.3"
resolved "https://registry.yarnpkg.com/@types/rx-core/-/rx-core-4.0.3.tgz#0b3354b1238cedbe2b74f6326f139dbc7a591d60"
integrity sha1-CzNUsSOM7b4rdPYybxOdvHpZHWA=
"@types/rx-lite-aggregates@*":
version "4.0.3"
resolved "https://registry.yarnpkg.com/@types/rx-lite-aggregates/-/rx-lite-aggregates-4.0.3.tgz#6efb2b7f3d5f07183a1cb2bd4b1371d7073384c2"
integrity sha512-MAGDAHy8cRatm94FDduhJF+iNS5//jrZ/PIfm+QYw9OCeDgbymFHChM8YVIvN2zArwsRftKgE33QfRWvQk4DPg==
dependencies:
"@types/rx-lite" "*"
"@types/rx-lite-async@*":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/rx-lite-async/-/rx-lite-async-4.0.2.tgz#27fbf0caeff029f41e2d2aae638b05e91ceb600c"
integrity sha512-vTEv5o8l6702ZwfAM5aOeVDfUwBSDOs+ARoGmWAKQ6LOInQ8J4/zjM7ov12fuTpktUKdMQjkeCp07Vd73mPkxw==
dependencies:
"@types/rx-lite" "*"
"@types/rx-lite-backpressure@*":
version "4.0.3"
resolved "https://registry.yarnpkg.com/@types/rx-lite-backpressure/-/rx-lite-backpressure-4.0.3.tgz#05abb19bdf87cc740196c355e5d0b37bb50b5d56"
integrity sha512-Y6aIeQCtNban5XSAF4B8dffhIKu6aAy/TXFlScHzSxh6ivfQBQw6UjxyEJxIOt3IT49YkS+siuayM2H/Q0cmgA==
dependencies:
"@types/rx-lite" "*"
"@types/rx-lite-coincidence@*":
version "4.0.3"
resolved "https://registry.yarnpkg.com/@types/rx-lite-coincidence/-/rx-lite-coincidence-4.0.3.tgz#80bd69acc4054a15cdc1638e2dc8843498cd85c0"
integrity sha512-1VNJqzE9gALUyMGypDXZZXzR0Tt7LC9DdAZQ3Ou/Q0MubNU35agVUNXKGHKpNTba+fr8GdIdkC26bRDqtCQBeQ==
dependencies:
"@types/rx-lite" "*"
"@types/rx-lite-experimental@*":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/rx-lite-experimental/-/rx-lite-experimental-4.0.1.tgz#c532f5cbdf3f2c15da16ded8930d1b2984023cbd"
integrity sha1-xTL1y98/LBXaFt7Ykw0bKYQCPL0=
dependencies:
"@types/rx-lite" "*"
"@types/rx-lite-joinpatterns@*":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/rx-lite-joinpatterns/-/rx-lite-joinpatterns-4.0.1.tgz#f70fe370518a8432f29158cc92ffb56b4e4afc3e"
integrity sha1-9w/jcFGKhDLykVjMkv+1a05K/D4=
dependencies:
"@types/rx-lite" "*"
"@types/rx-lite-testing@*":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/rx-lite-testing/-/rx-lite-testing-4.0.1.tgz#21b19d11f4dfd6ffef5a9d1648e9c8879bfe21e9"
integrity sha1-IbGdEfTf1v/vWp0WSOnIh5v+Iek=
dependencies:
"@types/rx-lite-virtualtime" "*"
"@types/rx-lite-time@*":
version "4.0.3"
resolved "https://registry.yarnpkg.com/@types/rx-lite-time/-/rx-lite-time-4.0.3.tgz#0eda65474570237598f3448b845d2696f2dbb1c4"
integrity sha512-ukO5sPKDRwCGWRZRqPlaAU0SKVxmWwSjiOrLhoQDoWxZWg6vyB9XLEZViKOzIO6LnTIQBlk4UylYV0rnhJLxQw==
dependencies:
"@types/rx-lite" "*"
"@types/rx-lite-virtualtime@*":
version "4.0.3"
resolved "https://registry.yarnpkg.com/@types/rx-lite-virtualtime/-/rx-lite-virtualtime-4.0.3.tgz#4b30cacd0fe2e53af29f04f7438584c7d3959537"
integrity sha512-3uC6sGmjpOKatZSVHI2xB1+dedgml669ZRvqxy+WqmGJDVusOdyxcKfyzjW0P3/GrCiN4nmRkLVMhPwHCc5QLg==
dependencies:
"@types/rx-lite" "*"
"@types/rx-lite@*":
version "4.0.5"
resolved "https://registry.yarnpkg.com/@types/rx-lite/-/rx-lite-4.0.5.tgz#b3581525dff69423798daa9a0d33c1e66a5e8c4c"
integrity sha512-KZk5XTR1dm/kNgBx8iVpjno6fRYtAUQWBOmj+O8j724+nk097sz4fOoHJNpCkOJUtHUurZlJC7QvSFCZHbkC+w==
dependencies:
"@types/rx-core" "*"
"@types/rx-core-binding" "*"
"@types/rx@*":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@types/rx/-/rx-4.1.1.tgz#598fc94a56baed975f194574e0f572fd8e627a48"
integrity sha1-WY/JSla67ZdfGUV04PVy/Y5iekg=
dependencies:
"@types/rx-core" "*"
"@types/rx-core-binding" "*"
"@types/rx-lite" "*"
"@types/rx-lite-aggregates" "*"
"@types/rx-lite-async" "*"
"@types/rx-lite-backpressure" "*"
"@types/rx-lite-coincidence" "*"
"@types/rx-lite-experimental" "*"
"@types/rx-lite-joinpatterns" "*"
"@types/rx-lite-testing" "*"
"@types/rx-lite-time" "*"
"@types/rx-lite-virtualtime" "*"
"@types/selenium-webdriver@^3.0.0":
version "3.0.12"
resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.12.tgz#6affe5aed1ba379175075a889adbe2bc3aa62159"
@@ -827,6 +936,13 @@
dependencies:
"@types/node" "*"
"@types/through@*":
version "0.0.29"
resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.29.tgz#72943aac922e179339c651fa34a4428a4d722f93"
integrity sha512-9a7C5VHh+1BKblaYiq+7Tfc+EOmjMdZaD1MYtkQjSoxgB69tBjW98ry6SKsi4zEIWztLOMRuL87A3bdT/Fc/4w==
dependencies:
"@types/node" "*"
"@types/tough-cookie@*":
version "2.3.3"
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.3.tgz#7f226d67d654ec9070e755f46daebf014628e9d9"
@@ -1039,6 +1155,11 @@ ansi-escapes@^1.1.0:
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
integrity sha1-06ioOzGapneTZisT52HHkRQiMG4=
ansi-escapes@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30"
integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==
ansi-gray@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251"
@@ -2107,6 +2228,11 @@ character-reference-invalid@^1.0.0:
resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed"
integrity sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
chokidar@2.0.4, chokidar@^2.0.0, chokidar@^2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26"
@@ -2211,6 +2337,13 @@ cli-cursor@^1.0.1, cli-cursor@^1.0.2:
dependencies:
restore-cursor "^1.0.1"
cli-cursor@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
dependencies:
restore-cursor "^2.0.0"
cli-spinners@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c"
@@ -3848,6 +3981,15 @@ extend@3, extend@^3.0.0, extend@^3.0.1, extend@~3.0.0, extend@~3.0.1, extend@~3.
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
external-editor@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27"
integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==
dependencies:
chardet "^0.7.0"
iconv-lite "^0.4.24"
tmp "^0.0.33"
extglob@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
@@ -3959,6 +4101,13 @@ figures@^1.3.5:
escape-string-regexp "^1.0.5"
object-assign "^4.1.0"
figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
dependencies:
escape-string-regexp "^1.0.5"
file-entry-cache@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
@@ -5612,7 +5761,7 @@ iconv-lite@0.4.23:
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@0.4.24, iconv-lite@^0.4.13, iconv-lite@^0.4.4, iconv-lite@~0.4.11, iconv-lite@~0.4.13:
iconv-lite@0.4.24, iconv-lite@^0.4.13, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.11, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -5745,6 +5894,25 @@ inquirer@^0.12.0:
strip-ansi "^3.0.0"
through "^2.3.6"
inquirer@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8"
integrity sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==
dependencies:
ansi-escapes "^3.0.0"
chalk "^2.0.0"
cli-cursor "^2.1.0"
cli-width "^2.0.0"
external-editor "^3.0.0"
figures "^2.0.0"
lodash "^4.17.10"
mute-stream "0.0.7"
run-async "^2.2.0"
rxjs "^6.1.0"
string-width "^2.1.0"
strip-ansi "^4.0.0"
through "^2.3.6"
interpret@^1.0.0, interpret@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
@@ -6081,7 +6249,7 @@ is-primitive@^2.0.0:
resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
is-promise@^2.1:
is-promise@^2.1, is-promise@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
@@ -7741,7 +7909,7 @@ mute-stream@0.0.5:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
integrity sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=
mute-stream@~0.0.4:
mute-stream@0.0.7, mute-stream@~0.0.4:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
@@ -8219,6 +8387,13 @@ onetime@^1.0.0:
resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=
onetime@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=
dependencies:
mimic-fn "^1.0.0"
opn@^5.3.0:
version "5.4.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.4.0.tgz#cb545e7aab78562beb11aa3bfabc7042e1761035"
@@ -9772,6 +9947,14 @@ restore-cursor@^1.0.1:
exit-hook "^1.0.0"
onetime "^1.0.0"
restore-cursor@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368=
dependencies:
onetime "^2.0.0"
signal-exit "^3.0.2"
ret@~0.1.10:
version "0.1.15"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
@@ -9867,6 +10050,13 @@ run-async@^0.1.0:
dependencies:
once "^1.3.0"
run-async@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA=
dependencies:
is-promise "^2.1.0"
run-sequence@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/run-sequence/-/run-sequence-1.2.2.tgz#5095a0bebe98733b0140bd08dd80ec030ddacdeb"
@@ -9880,7 +10070,7 @@ rx-lite@^3.1.2:
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=
rxjs@6.3.3, rxjs@^6.3.3:
rxjs@6.3.3, rxjs@^6.1.0, rxjs@^6.3.3:
version "6.3.3"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55"
integrity sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==
@@ -11133,7 +11323,7 @@ tmp@0.0.30:
dependencies:
os-tmpdir "~1.0.1"
tmp@0.0.33, tmp@0.0.x:
tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==