From afcc27d20dec64e7d22193b04aa9225c060d9771 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Fri, 9 Nov 2018 21:30:20 +0100 Subject: [PATCH] chore(stage-release) allow selecting pre-release labels Implements the functionality to select a pre-release label (as discussed in: https://github.com/angular/material2/pull/13621#discussion_r225705238) --- tools/release/prompt/new-version-prompt.ts | 68 ++++++++++++++------ tools/release/prompt/prerelease-labels.ts | 28 ++++++++ tools/release/version-name/create-version.ts | 4 +- tools/release/version-name/parse-version.ts | 2 +- 4 files changed, 80 insertions(+), 22 deletions(-) create mode 100644 tools/release/prompt/prerelease-labels.ts diff --git a/tools/release/prompt/new-version-prompt.ts b/tools/release/prompt/new-version-prompt.ts index 4a9dbc5e99f7..50d57b1d36c8 100644 --- a/tools/release/prompt/new-version-prompt.ts +++ b/tools/release/prompt/new-version-prompt.ts @@ -1,11 +1,13 @@ -import {ChoiceType, prompt, Separator} from 'inquirer'; +import {ChoiceType, prompt} from 'inquirer'; import {createNewVersion, ReleaseType} from '../version-name/create-version'; import {parseVersionName, Version} from '../version-name/parse-version'; +import {determineAllowedPrereleaseLabels} from './prerelease-labels'; /** Answers that will be prompted for. */ type VersionPromptAnswers = { - versionName: string; - manualCustomVersion: string; + proposedVersion: string; + isPrerelease: boolean; + prereleaseLabel: string; }; /** @@ -13,17 +15,25 @@ type VersionPromptAnswers = { * validated to be a proper increment of the specified current version. */ export async function promptForNewVersion(currentVersion: Version): Promise { - const versionChoices: ChoiceType[] = [ - new Separator(), - {value: 'custom-release', name: 'Release w/ custom version'} - ]; + const allowedPrereleaseChoices = determineAllowedPrereleaseLabels(currentVersion); + const versionChoices: ChoiceType[] = []; if (currentVersion.prereleaseLabel) { - versionChoices.unshift( - createVersionChoice(currentVersion, 'pre-release', 'Pre-release'), - createVersionChoice(currentVersion, 'stable-release', 'Stable release')); + versionChoices.push( + createVersionChoice(currentVersion, 'stable-release', 'Stable release'), + createVersionChoice(currentVersion, 'bump-prerelease', 'Bump pre-release number')); + + // Only add the option to change the prerelease label if the current version can be + // changed to a new label. e.g. a version that is already marked as release candidate + // shouldn't be changed to a beta or alpha version. + if (allowedPrereleaseChoices) { + versionChoices.push({ + value: 'new-prerelease-label', + name: `New pre-release (${allowedPrereleaseChoices.map(c => c.value).join(', ')})` + }); + } } else { - versionChoices.unshift( + versionChoices.push( createVersionChoice(currentVersion, 'major', 'Major release'), createVersionChoice(currentVersion, 'minor', 'Minor release'), createVersionChoice(currentVersion, 'patch', 'Patch release')); @@ -31,19 +41,39 @@ export async function promptForNewVersion(currentVersion: Version): Promise([{ type: 'list', - name: 'versionName', + name: 'proposedVersion', message: `What's the type of the new release?`, choices: versionChoices, }, { - type: 'input', - name: 'manualCustomVersion', - message: 'Please provide a custom release name:', - validate: enteredVersion => - !!parseVersionName(enteredVersion) || 'This is not a valid Semver version', - when: ({versionName}) => versionName === 'custom-release' + type: 'prompt', + 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, + }, { + type: 'list', + name: 'prereleaseLabel', + message: 'Please select a pre-release label:', + choices: allowedPrereleaseChoices, + when: ({isPrerelease, proposedVersion}) => + // Only prompt for selecting a pre-release label if the current release is a pre-release, + // or the existing pre-release label should be changed. + isPrerelease || proposedVersion === 'new-prerelease-label', }]); - return parseVersionName(answers.manualCustomVersion || answers.versionName); + // In case the new version just changes the pre-release label, we base the new version + // on top of the current version. Otherwise, we use the proposed version from the + // prompt answers. + const newVersion = answers.proposedVersion === 'new-prerelease-label' ? + currentVersion.clone() : + parseVersionName(answers.proposedVersion); + + if (answers.prereleaseLabel) { + newVersion.prereleaseLabel = answers.prereleaseLabel; + newVersion.prereleaseNumber = 0; + } + + return newVersion; } /** Creates a new choice for selecting a version inside of an Inquirer list prompt. */ diff --git a/tools/release/prompt/prerelease-labels.ts b/tools/release/prompt/prerelease-labels.ts new file mode 100644 index 000000000000..290fc36eabde --- /dev/null +++ b/tools/release/prompt/prerelease-labels.ts @@ -0,0 +1,28 @@ +import {Version} from '../version-name/parse-version'; + +/** Inquirer choice for selecting an alpha pre-release label. */ +const ALPHA_CHOICE = {value: 'alpha', name: 'Alpha pre-release'}; + +/** Inquirer choice for selecting an beta pre-release label. */ +const BETA_CHOICE = {value: 'beta', name: 'Beta pre-release'}; + +/** Inquirer choice for selecting a release candidate label. */ +const RC_CHOICE = {value: 'rc', name: 'Release candidate'}; + +/** + * Determines all allowed pre-release labels for a given version. For example, a + * release-candidate version cannot be changed to an alpha or beta pre-release. + */ +export function determineAllowedPrereleaseLabels(version: Version) { + const {prereleaseLabel} = version; + + if (!prereleaseLabel) { + return [ALPHA_CHOICE, BETA_CHOICE, RC_CHOICE]; + } else if (prereleaseLabel === 'alpha') { + return [BETA_CHOICE, RC_CHOICE]; + } else if (prereleaseLabel === 'beta') { + return [RC_CHOICE]; + } + + return null; +} diff --git a/tools/release/version-name/create-version.ts b/tools/release/version-name/create-version.ts index f65798da5853..e58aba65e147 100644 --- a/tools/release/version-name/create-version.ts +++ b/tools/release/version-name/create-version.ts @@ -2,7 +2,7 @@ import {Version} from './parse-version'; import {VersionType} from './publish-branch'; /** Type of a new release */ -export type ReleaseType = VersionType | 'stable-release' | 'pre-release' | 'custom-release'; +export type ReleaseType = VersionType | 'stable-release' | 'bump-prerelease'; /** Creates a new version that can be used for the given release type. */ export function createNewVersion(currentVersion: Version, releaseType: ReleaseType): @@ -10,7 +10,7 @@ export function createNewVersion(currentVersion: Version, releaseType: ReleaseTy // Clone the version object in order to keep the original version info un-modified. const newVersion = currentVersion.clone(); - if (releaseType === 'pre-release') { + if (releaseType === 'bump-prerelease') { newVersion.prereleaseNumber++; } else { // For all other release types, the pre-release label and number should be removed diff --git a/tools/release/version-name/parse-version.ts b/tools/release/version-name/parse-version.ts index 3b75fe0086ff..bc9fba5bf76f 100644 --- a/tools/release/version-name/parse-version.ts +++ b/tools/release/version-name/parse-version.ts @@ -51,7 +51,7 @@ export function serializeVersion(newVersion: Version): string { let versionString = `${major}.${minor}.${patch}`; - if (prereleaseLabel && prereleaseNumber) { + if (prereleaseLabel && !isNaN(prereleaseNumber)) { versionString += `-${prereleaseLabel}.${prereleaseNumber}`; }