diff --git a/scripts/release/__tests__/createReleasePR.test.ts b/scripts/release/__tests__/createReleasePR.test.ts index bff5c8b5881..b14cc0ec94f 100644 --- a/scripts/release/__tests__/createReleasePR.test.ts +++ b/scripts/release/__tests__/createReleasePR.test.ts @@ -5,6 +5,7 @@ import { getSkippedCommitsText, decideReleaseStrategy, readVersions, + getNextVersion, } from '../createReleasePR'; describe('createReleasePR', () => { @@ -79,16 +80,19 @@ describe('createReleasePR', () => { javascript: { current: '0.0.1', releaseType: 'patch', + next: getNextVersion('0.0.1', 'patch'), }, php: { current: '0.0.1', releaseType: 'patch', + next: getNextVersion('0.0.1', 'patch'), }, java: { current: '0.0.1', releaseType: 'patch', + next: getNextVersion('0.0.1', 'patch'), }, }) ).toMatchInlineSnapshot(` @@ -104,6 +108,7 @@ describe('createReleasePR', () => { javascript: { current: '0.0.1', releaseType: 'patch', + next: getNextVersion('0.0.1', 'patch'), }, php: { @@ -115,6 +120,7 @@ describe('createReleasePR', () => { java: { current: '0.0.1', releaseType: 'patch', + next: getNextVersion('0.0.1', 'patch'), }, }) ).toMatchInlineSnapshot(` @@ -130,22 +136,25 @@ describe('createReleasePR', () => { javascript: { current: '0.0.1', releaseType: 'patch', + next: getNextVersion('0.0.1', 'patch'), }, php: { current: '0.0.1', releaseType: 'minor', + next: getNextVersion('0.0.1', 'minor'), }, java: { current: '0.0.1', - releaseType: 'patch', + releaseType: null, skipRelease: true, + next: getNextVersion('0.0.1', null), }, }) ).toMatchInlineSnapshot(` "- javascript: 0.0.1 -> **\`patch\` _(e.g. 0.0.2)_** - - ~java: 0.0.1 -> **\`patch\` _(e.g. 0.0.2)_**~ + - ~java: 0.0.1 -> **\`null\` _(e.g. 0.0.1)_**~ - No \`feat\` or \`fix\` commit, thus unchecked by default. - php: 0.0.1 -> **\`minor\` _(e.g. 0.1.0)_**" `); @@ -178,6 +187,7 @@ describe('createReleasePR', () => { }); expect(versions.javascript.releaseType).toEqual('major'); + expect(versions.javascript.next).toEqual('1.0.0'); }); it('bumps minor version for feat', () => { @@ -205,6 +215,7 @@ describe('createReleasePR', () => { }); expect(versions.php.releaseType).toEqual('minor'); + expect(versions.php.next).toEqual('0.1.0'); }); it('bumps patch version for fix', () => { @@ -232,6 +243,7 @@ describe('createReleasePR', () => { }); expect(versions.java.releaseType).toEqual('patch'); + expect(versions.java.next).toEqual('0.0.2'); }); it('marks noCommit for languages without any commit', () => { @@ -261,6 +273,8 @@ describe('createReleasePR', () => { expect(versions.javascript.noCommit).toEqual(true); expect(versions.php.noCommit).toEqual(true); expect(versions.java.noCommit).toBeUndefined(); + expect(versions.java.releaseType).toEqual('patch'); + expect(versions.java.next).toEqual('0.0.2'); }); it('releases every languages if a `specs` commit is present', () => { @@ -289,10 +303,13 @@ describe('createReleasePR', () => { expect(versions.javascript.noCommit).toBeUndefined(); expect(versions.javascript.releaseType).toEqual('patch'); + expect(versions.javascript.next).toEqual('0.0.2'); expect(versions.php.noCommit).toBeUndefined(); expect(versions.php.releaseType).toEqual('patch'); + expect(versions.php.next).toEqual('0.0.2'); expect(versions.java.noCommit).toBeUndefined(); expect(versions.java.releaseType).toEqual('patch'); + expect(versions.java.next).toEqual('0.0.2'); }); it('bumps for `specs` feat with only language `fix` commits', () => { @@ -328,10 +345,13 @@ describe('createReleasePR', () => { expect(versions.javascript.noCommit).toBeUndefined(); expect(versions.javascript.releaseType).toEqual('minor'); + expect(versions.javascript.next).toEqual('0.1.0'); expect(versions.php.noCommit).toBeUndefined(); expect(versions.php.releaseType).toEqual('minor'); + expect(versions.php.next).toEqual('0.1.0'); expect(versions.java.noCommit).toBeUndefined(); expect(versions.java.releaseType).toEqual('minor'); + expect(versions.java.next).toEqual('0.1.0'); }); it('marks skipRelease for patch upgrade without fix commit', () => { @@ -361,6 +381,76 @@ describe('createReleasePR', () => { expect(versions.java.skipRelease).toBeUndefined(); expect(versions.php.skipRelease).toBeUndefined(); }); + + it('consider prerelease version and correctly bumps them', () => { + const versions = decideReleaseStrategy({ + versions: { + javascript: { + current: '0.0.1-alpha', + }, + java: { + current: '0.0.1-beta', + }, + php: { + current: '0.0.1-algolia', + }, + }, + commits: [ + { + hash: 'b2501882', + type: 'feat', + scope: 'specs', + message: 'add some descriptions', + raw: 'b2501882 feat(specs): add some descriptions', + }, + ], + }); + + expect(versions.javascript.noCommit).toBeUndefined(); + expect(versions.javascript.releaseType).toEqual('prerelease'); + expect(versions.javascript.next).toEqual('0.0.1-alpha.0'); + expect(versions.php.noCommit).toBeUndefined(); + expect(versions.php.releaseType).toEqual('prerelease'); + expect(versions.php.next).toEqual('0.0.1-algolia.0'); + expect(versions.java.noCommit).toBeUndefined(); + expect(versions.java.releaseType).toEqual('prerelease'); + expect(versions.java.next).toEqual('0.0.1-beta.0'); + }); + + it('bumps SNAPSHOT versions correctly', () => { + const versions = decideReleaseStrategy({ + versions: { + javascript: { + current: '0.0.1-alpha', + }, + java: { + current: '0.0.1-SNAPSHOT', + }, + php: { + current: '0.0.1-beta', + }, + }, + commits: [ + { + hash: 'b2501882', + type: 'feat', + scope: 'specs', + message: 'add some descriptions', + raw: 'b2501882 feat(specs): add some descriptions', + }, + ], + }); + + expect(versions.javascript.noCommit).toBeUndefined(); + expect(versions.javascript.releaseType).toEqual('prerelease'); + expect(versions.javascript.next).toEqual('0.0.1-alpha.0'); + expect(versions.php.noCommit).toBeUndefined(); + expect(versions.php.releaseType).toEqual('prerelease'); + expect(versions.php.next).toEqual('0.0.1-beta.0'); + expect(versions.java.noCommit).toBeUndefined(); + expect(versions.java.releaseType).toEqual('minor'); + expect(versions.java.next).toEqual('0.1.0-SNAPSHOT'); + }); }); describe('getSkippedCommitsText', () => { diff --git a/scripts/release/createReleasePR.ts b/scripts/release/createReleasePR.ts index 41ead58e7ef..55adf8fbd43 100755 --- a/scripts/release/createReleasePR.ts +++ b/scripts/release/createReleasePR.ts @@ -42,7 +42,8 @@ export function readVersions(): VersionsWithoutReleaseType { export function getVersionChangesText(versions: Versions): string { return LANGUAGES.map((lang) => { - const { current, releaseType, noCommit, skipRelease } = versions[lang]; + const { current, releaseType, noCommit, skipRelease, next } = + versions[lang]; if (noCommit) { return `- ~${lang}: ${current} (${TEXT.noCommit})~`; @@ -52,8 +53,6 @@ export function getVersionChangesText(versions: Versions): string { return `- ~${lang}: (${TEXT.currentVersionNotFound})~`; } - const next = semver.inc(current, releaseType!); - if (skipRelease) { return [ `- ~${lang}: ${current} -> **\`${releaseType}\` _(e.g. ${next})_**~`, @@ -149,6 +148,38 @@ export function parseCommit(commit: string): Commit { }; } +/** + * Returns the next version of the client. + */ +export function getNextVersion( + current: string, + releaseType: semver.ReleaseType | null +): string { + if (releaseType === null) { + return current; + } + + let nextVersion: string | null = current; + + // snapshots should not be bumped as prerelease + if (!current.endsWith('-SNAPSHOT')) { + nextVersion = semver.inc(current, releaseType); + } else { + nextVersion = `${semver.inc( + current.replace('-SNAPSHOT', ''), + releaseType + )}-SNAPSHOT`; + } + + if (!nextVersion) { + throw new Error( + `Unable to bump version: '${current}' with release type: '${releaseType}'` + ); + } + + return nextVersion; +} + /* eslint-disable no-param-reassign */ export function decideReleaseStrategy({ versions, @@ -170,15 +201,23 @@ export function decideReleaseStrategy({ ...version, noCommit: true, releaseType: null, + next: getNextVersion(currentVersion, null), }; return versionsWithReleaseType; } - if (semver.prerelease(currentVersion)) { + console.log(`Deciding next version bump for ${lang}.`); + + // snapshots should not be bumped as prerelease + if ( + semver.prerelease(currentVersion) && + !currentVersion.endsWith('-SNAPSHOT') + ) { // if version is like 0.1.2-beta.1, it increases to 0.1.2-beta.2, even if there's a breaking change. versionsWithReleaseType[lang] = { ...version, releaseType: 'prerelease', + next: getNextVersion(currentVersion, 'prerelease'), }; return versionsWithReleaseType; } @@ -191,6 +230,7 @@ export function decideReleaseStrategy({ versionsWithReleaseType[lang] = { ...version, releaseType: 'major', + next: getNextVersion(currentVersion, 'major'), }; return versionsWithReleaseType; } @@ -200,6 +240,7 @@ export function decideReleaseStrategy({ versionsWithReleaseType[lang] = { ...version, releaseType: 'minor', + next: getNextVersion(currentVersion, 'minor'), }; return versionsWithReleaseType; } @@ -208,6 +249,7 @@ export function decideReleaseStrategy({ ...version, releaseType: 'patch', ...(commitTypes.has('fix') ? undefined : { skipRelease: true }), + next: getNextVersion(currentVersion, 'patch'), }; return versionsWithReleaseType; }, diff --git a/scripts/release/types.ts b/scripts/release/types.ts index 6d124c9d1eb..f4221bf0e81 100644 --- a/scripts/release/types.ts +++ b/scripts/release/types.ts @@ -5,6 +5,7 @@ import type { Language } from '../types'; export type Version = { current: string; releaseType: ReleaseType | null; + next?: string; skipRelease?: boolean; noCommit?: boolean; };