Skip to content

Commit acedb48

Browse files
devversionandrewseguin
authored andcommitted
chore(stage-release) allow selecting pre-release labels (#14070)
Implements the functionality to select a pre-release label (as discussed in: #13621 (comment))
1 parent 3e2d0a7 commit acedb48

File tree

4 files changed

+80
-22
lines changed

4 files changed

+80
-22
lines changed

tools/release/prompt/new-version-prompt.ts

+49-19
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,79 @@
1-
import {ChoiceType, prompt, Separator} from 'inquirer';
1+
import {ChoiceType, prompt} from 'inquirer';
22
import {createNewVersion, ReleaseType} from '../version-name/create-version';
33
import {parseVersionName, Version} from '../version-name/parse-version';
4+
import {determineAllowedPrereleaseLabels} from './prerelease-labels';
45

56
/** Answers that will be prompted for. */
67
type VersionPromptAnswers = {
7-
versionName: string;
8-
manualCustomVersion: string;
8+
proposedVersion: string;
9+
isPrerelease: boolean;
10+
prereleaseLabel: string;
911
};
1012

1113
/**
1214
* Prompts the current user-input interface for a new version name. The new version will be
1315
* validated to be a proper increment of the specified current version.
1416
*/
1517
export async function promptForNewVersion(currentVersion: Version): Promise<Version> {
16-
const versionChoices: ChoiceType[] = [
17-
new Separator(),
18-
{value: 'custom-release', name: 'Release w/ custom version'}
19-
];
18+
const allowedPrereleaseChoices = determineAllowedPrereleaseLabels(currentVersion);
19+
const versionChoices: ChoiceType[] = [];
2020

2121
if (currentVersion.prereleaseLabel) {
22-
versionChoices.unshift(
23-
createVersionChoice(currentVersion, 'pre-release', 'Pre-release'),
24-
createVersionChoice(currentVersion, 'stable-release', 'Stable release'));
22+
versionChoices.push(
23+
createVersionChoice(currentVersion, 'stable-release', 'Stable release'),
24+
createVersionChoice(currentVersion, 'bump-prerelease', 'Bump pre-release number'));
25+
26+
// Only add the option to change the prerelease label if the current version can be
27+
// changed to a new label. e.g. a version that is already marked as release candidate
28+
// shouldn't be changed to a beta or alpha version.
29+
if (allowedPrereleaseChoices) {
30+
versionChoices.push({
31+
value: 'new-prerelease-label',
32+
name: `New pre-release (${allowedPrereleaseChoices.map(c => c.value).join(', ')})`
33+
});
34+
}
2535
} else {
26-
versionChoices.unshift(
36+
versionChoices.push(
2737
createVersionChoice(currentVersion, 'major', 'Major release'),
2838
createVersionChoice(currentVersion, 'minor', 'Minor release'),
2939
createVersionChoice(currentVersion, 'patch', 'Patch release'));
3040
}
3141

3242
const answers = await prompt<VersionPromptAnswers>([{
3343
type: 'list',
34-
name: 'versionName',
44+
name: 'proposedVersion',
3545
message: `What's the type of the new release?`,
3646
choices: versionChoices,
3747
}, {
38-
type: 'input',
39-
name: 'manualCustomVersion',
40-
message: 'Please provide a custom release name:',
41-
validate: enteredVersion =>
42-
!!parseVersionName(enteredVersion) || 'This is not a valid Semver version',
43-
when: ({versionName}) => versionName === 'custom-release'
48+
type: 'prompt',
49+
name: 'isPrerelease',
50+
message: 'Should this be a pre-release?',
51+
// Prompt whether this should a pre-release if the current release is not a pre-release
52+
when: !currentVersion.prereleaseLabel,
53+
}, {
54+
type: 'list',
55+
name: 'prereleaseLabel',
56+
message: 'Please select a pre-release label:',
57+
choices: allowedPrereleaseChoices,
58+
when: ({isPrerelease, proposedVersion}) =>
59+
// Only prompt for selecting a pre-release label if the current release is a pre-release,
60+
// or the existing pre-release label should be changed.
61+
isPrerelease || proposedVersion === 'new-prerelease-label',
4462
}]);
4563

46-
return parseVersionName(answers.manualCustomVersion || answers.versionName);
64+
// In case the new version just changes the pre-release label, we base the new version
65+
// on top of the current version. Otherwise, we use the proposed version from the
66+
// prompt answers.
67+
const newVersion = answers.proposedVersion === 'new-prerelease-label' ?
68+
currentVersion.clone() :
69+
parseVersionName(answers.proposedVersion);
70+
71+
if (answers.prereleaseLabel) {
72+
newVersion.prereleaseLabel = answers.prereleaseLabel;
73+
newVersion.prereleaseNumber = 0;
74+
}
75+
76+
return newVersion;
4777
}
4878

4979
/** Creates a new choice for selecting a version inside of an Inquirer list prompt. */
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {Version} from '../version-name/parse-version';
2+
3+
/** Inquirer choice for selecting an alpha pre-release label. */
4+
const ALPHA_CHOICE = {value: 'alpha', name: 'Alpha pre-release'};
5+
6+
/** Inquirer choice for selecting an beta pre-release label. */
7+
const BETA_CHOICE = {value: 'beta', name: 'Beta pre-release'};
8+
9+
/** Inquirer choice for selecting a release candidate label. */
10+
const RC_CHOICE = {value: 'rc', name: 'Release candidate'};
11+
12+
/**
13+
* Determines all allowed pre-release labels for a given version. For example, a
14+
* release-candidate version cannot be changed to an alpha or beta pre-release.
15+
*/
16+
export function determineAllowedPrereleaseLabels(version: Version) {
17+
const {prereleaseLabel} = version;
18+
19+
if (!prereleaseLabel) {
20+
return [ALPHA_CHOICE, BETA_CHOICE, RC_CHOICE];
21+
} else if (prereleaseLabel === 'alpha') {
22+
return [BETA_CHOICE, RC_CHOICE];
23+
} else if (prereleaseLabel === 'beta') {
24+
return [RC_CHOICE];
25+
}
26+
27+
return null;
28+
}

tools/release/version-name/create-version.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ import {Version} from './parse-version';
22
import {VersionType} from './publish-branch';
33

44
/** Type of a new release */
5-
export type ReleaseType = VersionType | 'stable-release' | 'pre-release' | 'custom-release';
5+
export type ReleaseType = VersionType | 'stable-release' | 'bump-prerelease';
66

77
/** Creates a new version that can be used for the given release type. */
88
export function createNewVersion(currentVersion: Version, releaseType: ReleaseType):
99
Version {
1010
// Clone the version object in order to keep the original version info un-modified.
1111
const newVersion = currentVersion.clone();
1212

13-
if (releaseType === 'pre-release') {
13+
if (releaseType === 'bump-prerelease') {
1414
newVersion.prereleaseNumber++;
1515
} else {
1616
// For all other release types, the pre-release label and number should be removed

tools/release/version-name/parse-version.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export function serializeVersion(newVersion: Version): string {
5151

5252
let versionString = `${major}.${minor}.${patch}`;
5353

54-
if (prereleaseLabel && prereleaseNumber) {
54+
if (prereleaseLabel && !isNaN(prereleaseNumber)) {
5555
versionString += `-${prereleaseLabel}.${prereleaseNumber}`;
5656
}
5757

0 commit comments

Comments
 (0)