Creates a tool for staging and publishing releases as per the new branching and versioning that has been outlined in the following document. The tool is intended to be used across the organization to ensure consistent branching/versioning and labeling: https://docs.google.com/document/d/197kVillDwx-RZtSVOBtPb4BBIAw0E9RT3q3v6DZkykU/edit#heading=h.s3qlps8f4zq7dd The tool implements the actions as outlined in the following initial plan: https://hackmd.io/2Le8leq0S6G_R5VEVTNK9A. The implementation slightly diverged in so far that it performs staging and publishing together so that releasing is a single convenient command. In case of errors for which re-running the full command is not sufficient, we want to consider adding recover functionality. e.g. when the staging completed, but the actual NPM publishing aborted unexpectedly due to build errors. PR Close #38656
93 lines
3.9 KiB
TypeScript
93 lines
3.9 KiB
TypeScript
/**
|
|
* @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 * as Ora from 'ora';
|
|
import * as semver from 'semver';
|
|
|
|
import {spawnWithDebugOutput} from '../../utils/child-process';
|
|
import {error, green, info, red} from '../../utils/console';
|
|
import {BuiltPackage} from '../config/index';
|
|
|
|
import {FatalReleaseActionError} from './actions-error';
|
|
|
|
/*
|
|
* ###############################################################
|
|
*
|
|
* This file contains helpers for invoking external `ng-dev` commands. A subset of actions,
|
|
* like building release output or setting a NPM dist tag for release packages, cannot be
|
|
* performed directly as part of the release tool and need to be delegated to external `ng-dev`
|
|
* commands that exist across arbitrary version branches.
|
|
*
|
|
* In an concrete example: Consider a new patch version is released and that a new release
|
|
* package has been added to the `next` branch. The patch branch will not contain the new
|
|
* release package, so we could not build the release output for it. To work around this, we
|
|
* call the ng-dev build command for the patch version branch and expect it to return a list
|
|
* of built packages that need to be released as part of this release train.
|
|
*
|
|
* ###############################################################
|
|
*/
|
|
|
|
/**
|
|
* Invokes the `ng-dev release set-dist-tag` command in order to set the specified
|
|
* NPM dist tag for all packages in the checked out branch to the given version.
|
|
*/
|
|
export async function invokeSetNpmDistCommand(npmDistTag: string, version: semver.SemVer) {
|
|
try {
|
|
// Note: No progress indicator needed as that is the responsibility of the command.
|
|
await spawnWithDebugOutput(
|
|
'yarn', ['--silent', 'ng-dev', 'release', 'set-dist-tag', npmDistTag, version.format()]);
|
|
info(green(` ✓ Set "${npmDistTag}" NPM dist tag for all packages to v${version}.`));
|
|
} catch (e) {
|
|
error(e);
|
|
error(red(` ✘ An error occurred while setting the NPM dist tag for ${npmDistTag}.`));
|
|
throw new FatalReleaseActionError();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Invokes the `ng-dev release build` command in order to build the release
|
|
* packages for the currently checked out branch.
|
|
*/
|
|
export async function invokeReleaseBuildCommand(): Promise<BuiltPackage[]> {
|
|
const spinner = Ora().start('Building release output.');
|
|
try {
|
|
// 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.
|
|
const {stdout} = await spawnWithDebugOutput(
|
|
'yarn', ['--silent', 'ng-dev', 'release', 'build', '--json'], {mode: 'silent'});
|
|
spinner.stop();
|
|
info(green(` ✓ Built release output for all packages.`));
|
|
// The `ng-dev release build` command prints a JSON array to stdout
|
|
// that represents the built release packages and their output paths.
|
|
return JSON.parse(stdout.trim());
|
|
} catch (e) {
|
|
spinner.stop();
|
|
error(e);
|
|
error(red(` ✘ An error occurred while building the release packages.`));
|
|
throw new FatalReleaseActionError();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Invokes the `yarn install` command in order to install dependencies for
|
|
* the configured project with the currently checked out revision.
|
|
*/
|
|
export async function invokeYarnInstallCommand(projectDir: string): Promise<void> {
|
|
try {
|
|
// Note: No progress indicator needed as that is the responsibility of the command.
|
|
// TODO: Consider using an Ora spinner instead to ensure minimal console output.
|
|
await spawnWithDebugOutput(
|
|
'yarn', ['install', '--frozen-lockfile', '--non-interactive'], {cwd: projectDir});
|
|
info(green(` ✓ Installed project dependencies.`));
|
|
} catch (e) {
|
|
error(e);
|
|
error(red(` ✘ An error occurred while installing dependencies.`));
|
|
throw new FatalReleaseActionError();
|
|
}
|
|
}
|