Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions tools/release/prompt/new-version-prompt.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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(
Expand All @@ -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',
Expand All @@ -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',
Expand Down
14 changes: 7 additions & 7 deletions tools/release/publish-release.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}
Expand Down
20 changes: 15 additions & 5 deletions tools/release/stage-release.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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));

Expand All @@ -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}".`));
Expand Down
42 changes: 22 additions & 20 deletions tools/release/version-name/parse-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,49 @@
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 {
return serializeVersion(this);
}

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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just equals?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh just saw this. I'm fine going with equals. Will update this as part of a follow-up PR that touches the release tools 👍

return this.major === other.major && this.minor === other.minor && this.patch === other.patch &&
this.prereleaseLabel === other.prereleaseLabel &&
this.prereleaseNumber === other.prereleaseNumber;
}
}

/**
* 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) {
return 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. */
Expand All @@ -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}`;
}

Expand Down