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
73 lines
2.9 KiB
TypeScript
73 lines
2.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 semver from 'semver';
|
|
|
|
import {semverInc} from '../../versioning/inc-semver';
|
|
import {computeNewPrereleaseVersionForNext} from '../../versioning/next-prerelease-version';
|
|
import {ReleaseTrain} from '../../versioning/release-trains';
|
|
import {ReleaseAction} from '../actions';
|
|
|
|
/**
|
|
* Release action that cuts a prerelease for the next branch. A version in the next
|
|
* branch can have an arbitrary amount of next pre-releases.
|
|
*/
|
|
export class CutNextPrereleaseAction extends ReleaseAction {
|
|
/** Promise resolving with the new version if a NPM next pre-release is cut. */
|
|
private _newVersion: Promise<semver.SemVer> = this._computeNewVersion();
|
|
|
|
async getDescription() {
|
|
const {branchName} = this._getActivePrereleaseTrain();
|
|
const newVersion = await this._newVersion;
|
|
return `Cut a new next pre-release for the "${branchName}" branch (v${newVersion}).`;
|
|
}
|
|
|
|
async perform() {
|
|
const releaseTrain = this._getActivePrereleaseTrain();
|
|
const {branchName} = releaseTrain;
|
|
const newVersion = await this._newVersion;
|
|
|
|
const {id} = await this.checkoutBranchAndStageVersion(newVersion, branchName);
|
|
|
|
await this.waitForPullRequestToBeMerged(id);
|
|
await this.buildAndPublish(newVersion, branchName, 'next');
|
|
|
|
// If the pre-release has been cut from a branch that is not corresponding
|
|
// to the next release-train, cherry-pick the changelog into the primary
|
|
// development branch. i.e. the `next` branch that is usually `master`.
|
|
if (releaseTrain !== this.active.next) {
|
|
await this.cherryPickChangelogIntoNextBranch(newVersion, branchName);
|
|
}
|
|
}
|
|
|
|
/** Gets the release train for which NPM next pre-releases should be cut. */
|
|
private _getActivePrereleaseTrain(): ReleaseTrain {
|
|
return this.active.releaseCandidate ?? this.active.next;
|
|
}
|
|
|
|
/** Gets the new pre-release version for this release action. */
|
|
private async _computeNewVersion(): Promise<semver.SemVer> {
|
|
const releaseTrain = this._getActivePrereleaseTrain();
|
|
// If a pre-release is cut for the next release-train, the new version is computed
|
|
// with respect to special cases surfacing with FF/RC branches. Otherwise, the basic
|
|
// pre-release increment of the version is used as new version.
|
|
if (releaseTrain === this.active.next) {
|
|
return await computeNewPrereleaseVersionForNext(this.active, this.config);
|
|
} else {
|
|
return semverInc(releaseTrain.version, 'prerelease');
|
|
}
|
|
}
|
|
|
|
static async isActive() {
|
|
// Pre-releases for the `next` NPM dist tag can always be cut. Depending on whether
|
|
// there is a feature-freeze/release-candidate branch, the next pre-releases are either
|
|
// cut from such a branch, or from the actual `next` release-train branch (i.e. master).
|
|
return true;
|
|
}
|
|
}
|