build: release-staging script should have option to not bump version (#16147)

Adds a new prompt choice when staging a new release that can
be used if the version has been updated before. In that case we
don't want to bump the version automatically but rather use the
existing version and generate the changelog for it.

Closes #16136
This commit is contained in:
Paul Gschwendtner
2019-05-31 22:58:11 +02:00
committed by Andrew Seguin
parent 04a95c7f4e
commit 2b07377b35
4 changed files with 55 additions and 35 deletions
+11 -3
View File
@@ -1,4 +1,4 @@
import {ChoiceType, prompt} from 'inquirer';
import {ChoiceType, prompt, Separator} from 'inquirer';
import {createNewVersion, ReleaseType} from '../version-name/create-version';
import {parseVersionName, Version} from '../version-name/parse-version';
import {determineAllowedPrereleaseLabels} from './prerelease-labels';
@@ -17,6 +17,7 @@ type VersionPromptAnswers = {
export async function promptForNewVersion(currentVersion: Version): Promise<Version> {
const allowedPrereleaseChoices = determineAllowedPrereleaseLabels(currentVersion);
const versionChoices: ChoiceType[] = [];
const currentVersionName = currentVersion.format();
if (currentVersion.prereleaseLabel) {
versionChoices.push(
@@ -39,6 +40,11 @@ export async function promptForNewVersion(currentVersion: Version): Promise<Vers
createVersionChoice(currentVersion, 'patch', 'Patch release'));
}
// We always want to provide the option to use the current version. This is useful
// if the version got bumped manually before.
versionChoices.push(new Separator(),
{name: `Use current version (${currentVersionName})`, value: currentVersionName});
const answers = await prompt<VersionPromptAnswers>([{
type: 'list',
name: 'proposedVersion',
@@ -48,8 +54,10 @@ export async function promptForNewVersion(currentVersion: Version): Promise<Vers
type: 'confirm',
name: 'isPrerelease',
message: 'Should this be a pre-release?',
// Prompt whether this should a pre-release if the current release is not a pre-release
when: !currentVersion.prereleaseLabel,
// We don't want to prompt whether this should be a pre-release if the current version
// is already a pre-release or if the version has been already bumped manually.
when: ({proposedVersion}) =>
!currentVersion.prereleaseLabel && proposedVersion !== currentVersionName,
default: false,
}, {
type: 'list',
+7 -7
View File
@@ -79,7 +79,7 @@ class PublishReleaseTask extends BaseReleaseTask {
// Branch that will be used to build the output for the release of the current version.
const publishBranch = this.switchToPublishBranch(newVersion);
this._verifyLastCommitVersionBump();
this._verifyLastCommitFromStagingScript();
this.verifyLocalCommitsMatchUpstream(publishBranch);
const upstreamRemote = await this._getProjectUpstreamRemote();
@@ -147,13 +147,13 @@ class PublishReleaseTask extends BaseReleaseTask {
}
/**
* Verifies that the latest commit on the current branch is a version bump from the
* staging script.
* Verifies that the latest commit on the current branch has been created
* through the release staging script.
*/
private _verifyLastCommitVersionBump() {
if (!/chore: bump version/.test(this.git.getCommitTitle('HEAD'))) {
console.error(red(` ✘ The latest commit of the current branch does not seem to be a ` +
`version bump.`));
private _verifyLastCommitFromStagingScript() {
if (!/chore: (bump version|update changelog for)/.test(this.git.getCommitTitle('HEAD'))) {
console.error(red(` ✘ The latest commit of the current branch does not seem to be ` +
` created by the release staging script.`));
console.error(red(` Please stage the release using the staging script.`));
process.exit(1);
}
+15 -5
View File
@@ -76,6 +76,7 @@ class StageReleaseTask extends BaseReleaseTask {
const newVersion = await promptForNewVersion(this.currentVersion);
const newVersionName = newVersion.format();
const needsVersionBump = !newVersion.equalsTo(this.currentVersion);
const stagingBranch = `release-stage/${newVersionName}`;
// After the prompt for the new version, we print a new line because we want the
@@ -97,11 +98,13 @@ class StageReleaseTask extends BaseReleaseTask {
process.exit(1);
}
this._updatePackageJsonVersion(newVersionName);
if (needsVersionBump) {
this._updatePackageJsonVersion(newVersionName);
console.log(green(` ✓ Updated the version to "${bold(newVersionName)}" inside of the ` +
`${italic('package.json')}`));
console.log();
console.log(green(` ✓ Updated the version to "${bold(newVersionName)}" inside of the ` +
`${italic('package.json')}`));
console.log();
}
await promptAndGenerateChangelog(join(this.projectDir, CHANGELOG_FILE_NAME));
@@ -119,7 +122,14 @@ class StageReleaseTask extends BaseReleaseTask {
}
this.git.stageAllChanges();
this.git.createNewCommit(`chore: bump version to ${newVersionName} w/ changelog`);
// Note: When updating the commit messages here. Please also update the
// release publish script to detect the new commit messages.
if (needsVersionBump) {
this.git.createNewCommit(`chore: bump version to ${newVersionName} w/ changelog`);
} else {
this.git.createNewCommit(`chore: update changelog for ${newVersionName}`);
}
console.info();
console.info(green(` ✓ Created the staging commit for: "${newVersionName}".`));
+22 -20
View File
@@ -2,18 +2,17 @@
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) {}
/** 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|null,
/** Number for the pre-release. There can be multiple pre-releases for a version. */
public prereleaseNumber: number|null) {}
/** Serializes the version info into a string formatted version name. */
format(): string {
@@ -21,8 +20,14 @@ export class Version {
}
clone(): Version {
return new Version(this.major, this.minor, this.patch, this.prereleaseLabel,
this.prereleaseNumber);
return new Version(
this.major, this.minor, this.patch, this.prereleaseLabel, this.prereleaseNumber);
}
equalsTo(other: Version): boolean {
return this.major === other.major && this.minor === other.minor && this.patch === other.patch &&
this.prereleaseLabel === other.prereleaseLabel &&
this.prereleaseNumber === other.prereleaseNumber;
}
}
@@ -30,7 +35,7 @@ export class Version {
* Parses the specified version and returns an object that represents the individual
* version segments.
*/
export function parseVersionName(version: string): Version | null {
export function parseVersionName(version: string): Version|null {
const matches = version.match(versionNameRegex);
if (!matches) {
@@ -38,11 +43,8 @@ export function parseVersionName(version: string): Version | null {
}
return new Version(
Number(matches[1]),
Number(matches[2]),
Number(matches[3]),
matches[4],
Number(matches[5]));
Number(matches[1]), Number(matches[2]), Number(matches[3]), matches[4] || null,
Number(matches[5]) || null);
}
/** Serializes the specified version into a string. */
@@ -51,7 +53,7 @@ export function serializeVersion(newVersion: Version): string {
let versionString = `${major}.${minor}.${patch}`;
if (prereleaseLabel && !isNaN(prereleaseNumber)) {
if (prereleaseLabel && prereleaseNumber !== null) {
versionString += `-${prereleaseLabel}.${prereleaseNumber}`;
}