diff --git a/README.md b/README.md index 53bf3ad3e..3246acee3 100644 --- a/README.md +++ b/README.md @@ -338,6 +338,16 @@ autolabeler: - '/JIRA-[0-9]{1,4}/' ``` +## Pre-release increment + +When creating Pre-release (`prerelease: true`), you can add a pre-release identifier to increment the pre-release version number, with the `pre-release-identifier` option. It accept any string, but it's recommended to use [Semantic Versioning](https://semver.org/) pre-release identifiers (alpha, beta, rc, etc). + +Using `pre-release-identifier` automatically enable `include-pre-releases`. + +```yml +pre-release-identifier: 'alpha' # will create a pre-release with version number x.x.x-alpha.x +``` + ## Projects that don't use Semantic Versioning If your project doesn't follow [Semantic Versioning](https://semver.org) you can still use Release Drafter, but you may want to set the `version-template` option to customize how the `$NEXT_{PATCH,MINOR,MAJOR}_VERSION` environment variables are generated. diff --git a/dist/index.js b/dist/index.js index 9e8840d74..55e467e9d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -142365,9 +142365,14 @@ module.exports = (app, { getRouter }) => { const { 'filter-by-commitish': filterByCommitish, 'include-pre-releases': includePreReleases, + 'pre-release-identifier': preReleaseIdentifier, 'tag-prefix': tagPrefix, } = config + const shouldIncludePreReleases = Boolean( + includePreReleases || preReleaseIdentifier + ) + // override header and footer when passed as input const header = core.getInput('header') const footer = core.getInput('footer') @@ -142382,7 +142387,7 @@ module.exports = (app, { getRouter }) => { context, targetCommitish, filterByCommitish, - includePreReleases, + includePreReleases: shouldIncludePreReleases, tagPrefix, }) @@ -142775,7 +142780,7 @@ const DEFAULT_CONFIG = Object.freeze({ 'change-template': `* $TITLE (#$NUMBER) @$AUTHOR`, 'change-title-escapes': '', 'no-changes-template': `* No changes`, - 'version-template': `$MAJOR.$MINOR.$PATCH`, + 'version-template': `$MAJOR.$MINOR.$PATCH$PRERELEASE`, 'version-resolver': { major: { labels: [] }, minor: { labels: [] }, @@ -142795,6 +142800,7 @@ const DEFAULT_CONFIG = Object.freeze({ prerelease: false, 'filter-by-commitish': false, 'include-pre-releases': false, + 'pre-release-identifier': '', commitish: '', 'category-template': `## $TITLE`, header: '', @@ -142888,6 +142894,7 @@ exports.paginate = paginate const compareVersions = __nccwpck_require__(89296) const regexEscape = __nccwpck_require__(98691) +const core = __nccwpck_require__(42186) const { getVersionInfo } = __nccwpck_require__(49914) const { template } = __nccwpck_require__(47282) @@ -142896,19 +142903,17 @@ const { log } = __nccwpck_require__(71911) const sortReleases = (releases, tagPrefix) => { // For semver, we find the greatest release number // For non-semver, we use the most recently merged - try { - const tagPrefixRexExp = new RegExp(`^${regexEscape(tagPrefix)}`) - return releases.sort((r1, r2) => - compareVersions( + const tagPrefixRexExp = new RegExp(`^${regexEscape(tagPrefix)}`) + return releases.sort((r1, r2) => { + try { + return compareVersions( r1.tag_name.replace(tagPrefixRexExp, ''), r2.tag_name.replace(tagPrefixRexExp, '') ) - ) - } catch { - return releases.sort( - (r1, r2) => new Date(r1.created_at) - new Date(r2.created_at) - ) - } + } catch { + return new Date(r1.created_at) - new Date(r2.created_at) + } + }) } // GitHub API currently returns a 500 HTTP response if you attempt to fetch over 1000 releases. @@ -142967,7 +142972,12 @@ const findReleases = async ({ } if (lastRelease) { - log({ context, message: `Last release: ${lastRelease.tag_name}` }) + log({ + context, + message: `Last release${ + includePreReleases ? ' (including prerelease)' : '' + }: ${lastRelease.tag_name}`, + }) } else { log({ context, message: `No last release found` }) } @@ -143178,12 +143188,17 @@ const generateChangeLog = (mergedPullRequests, config) => { return changeLog.join('').trim() } -const resolveVersionKeyIncrement = (mergedPullRequests, config) => { +const resolveVersionKeyIncrement = ( + mergedPullRequests, + config, + isPreRelease +) => { const priorityMap = { patch: 1, minor: 2, major: 3, } + const labelToKeyMap = Object.fromEntries( Object.keys(priorityMap) .flatMap((key) => [ @@ -143191,17 +143206,35 @@ const resolveVersionKeyIncrement = (mergedPullRequests, config) => { ]) .flat() ) + + core.debug('labelToKeyMap: ' + JSON.stringify(labelToKeyMap)) + const keys = mergedPullRequests .filter(getFilterExcludedPullRequests(config['exclude-labels'])) .filter(getFilterIncludedPullRequests(config['include-labels'])) .flatMap((pr) => pr.labels.nodes.map((node) => labelToKeyMap[node.name])) .filter(Boolean) + + core.debug('keys: ' + JSON.stringify(keys)) + const keyPriorities = keys.map((key) => priorityMap[key]) const priority = Math.max(...keyPriorities) const versionKey = Object.keys(priorityMap).find( (key) => priorityMap[key] === priority ) - return versionKey || config['version-resolver'].default + + core.debug('versionKey: ' + versionKey) + + const versionKeyIncrement = versionKey || config['version-resolver'].default + + const shouldIncrementAsPrerelease = + isPreRelease && config['pre-release-identifier'] + + if (!shouldIncrementAsPrerelease) { + return versionKeyIncrement + } + + return `pre${versionKeyIncrement}` } const generateReleaseInfo = ({ @@ -143236,16 +143269,27 @@ const generateReleaseInfo = ({ config.replacers ) + const versionKeyIncrement = resolveVersionKeyIncrement( + mergedPullRequests, + config, + isPreRelease + ) + + core.debug('versionKeyIncrement: ' + versionKeyIncrement) + const versionInfo = getVersionInfo( lastRelease, config['version-template'], // Use the first override parameter to identify // a version, from the most accurate to the least version || tag || name, - resolveVersionKeyIncrement(mergedPullRequests, config), - config['tag-prefix'] + versionKeyIncrement, + config['tag-prefix'], + config['pre-release-identifier'] ) + core.debug('versionInfo: ' + JSON.stringify(versionInfo, null, 2)) + if (versionInfo) { body = template(body, versionInfo) } @@ -143256,6 +143300,8 @@ const generateReleaseInfo = ({ tag = template(tag, versionInfo) } + core.debug('tag: ' + tag) + if (name === undefined) { name = versionInfo ? template(config['name-template'] || '', versionInfo) @@ -143264,6 +143310,8 @@ const generateReleaseInfo = ({ name = template(name, versionInfo) } + core.debug('name: ' + name) + // Tags are not supported as `target_commitish` by Github API. // GITHUB_REF or the ref from webhook start with `refs/tags/`, so we handle // those here. If it doesn't but is still a tag - it must have been set @@ -143428,6 +143476,10 @@ const schema = (context) => { prerelease: Joi.boolean().default(DEFAULT_CONFIG.prerelease), + 'pre-release-identifier': Joi.string() + .allow('') + .default(DEFAULT_CONFIG['pre-release-identifier']), + 'filter-by-commitish': Joi.boolean().default( DEFAULT_CONFIG['filter-by-commitish'] ), @@ -143764,6 +143816,7 @@ exports.runnerIsActions = runnerIsActions /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { const semver = __nccwpck_require__(11383) +const core = __nccwpck_require__(42186) const splitSemVersion = (input, versionKey = 'version') => { if (!input[versionKey]) { @@ -143771,15 +143824,18 @@ const splitSemVersion = (input, versionKey = 'version') => { } const version = input.inc - ? semver.inc(input[versionKey], input.inc, true) + ? semver.inc(input[versionKey], input.inc, true, input.preReleaseIdentifier) : input[versionKey].version + const prereleaseVersion = semver.prerelease(version)?.join('.') || '' + return { ...input, version, $MAJOR: semver.major(version), $MINOR: semver.minor(version), $PATCH: semver.patch(version), + $PRERELEASE: prereleaseVersion ? `-${prereleaseVersion}` : '', $COMPLETE: version, } } @@ -143794,6 +143850,7 @@ const defaultVersionInfo = { $MAJOR: 1, $MINOR: 0, $PATCH: 0, + $PRERELEASE: '', }, $NEXT_MINOR_VERSION: { version: '0.1.0', @@ -143804,6 +143861,7 @@ const defaultVersionInfo = { $MAJOR: 0, $MINOR: 1, $PATCH: 0, + $PRERELEASE: '', }, $NEXT_PATCH_VERSION: { version: '0.1.0', @@ -143814,6 +143872,19 @@ const defaultVersionInfo = { $MAJOR: 0, $MINOR: 1, $PATCH: 0, + $PRERELEASE: '', + }, + $NEXT_PRERELEASE_VERSION: { + version: '0.1.0-rc.0', + template: '$MAJOR.$MINOR.$PATCH$PRERELEASE', + inputVersion: null, + versionKeyIncrement: 'prerelease', + inc: 'prerelease', + preReleaseIdentifier: 'rc', + $MAJOR: 0, + $MINOR: 1, + $PATCH: 0, + $PRERELEASE: '-rc.0', }, $INPUT_VERSION: null, $RESOLVED_VERSION: { @@ -143825,6 +143896,7 @@ const defaultVersionInfo = { $MAJOR: 0, $MINOR: 1, $PATCH: 0, + $PRERELEASE: '', }, } @@ -143878,6 +143950,11 @@ const getTemplatableVersion = (input) => { inc: 'patch', template: '$PATCH', }), + $NEXT_PRERELEASE_VERSION: splitSemVersion({ + ...input, + inc: 'prerelease', + template: '$PRERELEASE', + }), $INPUT_VERSION: splitSemVersion(input, 'inputVersion'), $RESOLVED_VERSION: splitSemVersion({ ...input, @@ -143921,21 +143998,53 @@ const getVersionInfo = ( template, inputVersion, versionKeyIncrement, - tagPrefix + tagPrefix, + preReleaseIdentifier ) => { const version = coerceVersion(release, tagPrefix) inputVersion = coerceVersion(inputVersion, tagPrefix) + const isPreVersionKeyIncrement = versionKeyIncrement?.startsWith('pre') + if (!version && !inputVersion) { + if (isPreVersionKeyIncrement) { + defaultVersionInfo['$RESOLVED_VERSION'] = { + ...defaultVersionInfo['$NEXT_PRERELEASE_VERSION'], + } + } + return defaultVersionInfo } + const shouldIncrementAsPrerelease = + isPreVersionKeyIncrement && version?.prerelease + + if (shouldIncrementAsPrerelease) { + versionKeyIncrement = 'prerelease' + } + + core.debug( + `version template params: ` + + JSON.stringify( + { + version, + template, + inputVersion, + versionKeyIncrement, + preReleaseIdentifier, + }, + null, + true + ) + ) + return { ...getTemplatableVersion({ version, template, inputVersion, versionKeyIncrement, + preReleaseIdentifier, }), } } diff --git a/index.js b/index.js index d0f8c81c9..7300a3245 100644 --- a/index.js +++ b/index.js @@ -162,9 +162,14 @@ module.exports = (app, { getRouter }) => { const { 'filter-by-commitish': filterByCommitish, 'include-pre-releases': includePreReleases, + 'pre-release-identifier': preReleaseIdentifier, 'tag-prefix': tagPrefix, } = config + const shouldIncludePreReleases = Boolean( + includePreReleases || preReleaseIdentifier + ) + // override header and footer when passed as input const header = core.getInput('header') const footer = core.getInput('footer') @@ -179,7 +184,7 @@ module.exports = (app, { getRouter }) => { context, targetCommitish, filterByCommitish, - includePreReleases, + includePreReleases: shouldIncludePreReleases, tagPrefix, }) diff --git a/lib/default-config.js b/lib/default-config.js index bc65a4508..680387e36 100644 --- a/lib/default-config.js +++ b/lib/default-config.js @@ -7,7 +7,7 @@ const DEFAULT_CONFIG = Object.freeze({ 'change-template': `* $TITLE (#$NUMBER) @$AUTHOR`, 'change-title-escapes': '', 'no-changes-template': `* No changes`, - 'version-template': `$MAJOR.$MINOR.$PATCH`, + 'version-template': `$MAJOR.$MINOR.$PATCH$PRERELEASE`, 'version-resolver': { major: { labels: [] }, minor: { labels: [] }, @@ -27,6 +27,7 @@ const DEFAULT_CONFIG = Object.freeze({ prerelease: false, 'filter-by-commitish': false, 'include-pre-releases': false, + 'pre-release-identifier': '', commitish: '', 'category-template': `## $TITLE`, header: '', diff --git a/lib/releases.js b/lib/releases.js index f1686376f..2868ffffb 100644 --- a/lib/releases.js +++ b/lib/releases.js @@ -1,5 +1,6 @@ const compareVersions = require('compare-versions') const regexEscape = require('escape-string-regexp') +const core = require('@actions/core') const { getVersionInfo } = require('./versions') const { template } = require('./template') @@ -8,19 +9,17 @@ const { log } = require('./log') const sortReleases = (releases, tagPrefix) => { // For semver, we find the greatest release number // For non-semver, we use the most recently merged - try { - const tagPrefixRexExp = new RegExp(`^${regexEscape(tagPrefix)}`) - return releases.sort((r1, r2) => - compareVersions( + const tagPrefixRexExp = new RegExp(`^${regexEscape(tagPrefix)}`) + return releases.sort((r1, r2) => { + try { + return compareVersions( r1.tag_name.replace(tagPrefixRexExp, ''), r2.tag_name.replace(tagPrefixRexExp, '') ) - ) - } catch { - return releases.sort( - (r1, r2) => new Date(r1.created_at) - new Date(r2.created_at) - ) - } + } catch { + return new Date(r1.created_at) - new Date(r2.created_at) + } + }) } // GitHub API currently returns a 500 HTTP response if you attempt to fetch over 1000 releases. @@ -79,7 +78,12 @@ const findReleases = async ({ } if (lastRelease) { - log({ context, message: `Last release: ${lastRelease.tag_name}` }) + log({ + context, + message: `Last release${ + includePreReleases ? ' (including prerelease)' : '' + }: ${lastRelease.tag_name}`, + }) } else { log({ context, message: `No last release found` }) } @@ -290,12 +294,17 @@ const generateChangeLog = (mergedPullRequests, config) => { return changeLog.join('').trim() } -const resolveVersionKeyIncrement = (mergedPullRequests, config) => { +const resolveVersionKeyIncrement = ( + mergedPullRequests, + config, + isPreRelease +) => { const priorityMap = { patch: 1, minor: 2, major: 3, } + const labelToKeyMap = Object.fromEntries( Object.keys(priorityMap) .flatMap((key) => [ @@ -303,17 +312,35 @@ const resolveVersionKeyIncrement = (mergedPullRequests, config) => { ]) .flat() ) + + core.debug('labelToKeyMap: ' + JSON.stringify(labelToKeyMap)) + const keys = mergedPullRequests .filter(getFilterExcludedPullRequests(config['exclude-labels'])) .filter(getFilterIncludedPullRequests(config['include-labels'])) .flatMap((pr) => pr.labels.nodes.map((node) => labelToKeyMap[node.name])) .filter(Boolean) + + core.debug('keys: ' + JSON.stringify(keys)) + const keyPriorities = keys.map((key) => priorityMap[key]) const priority = Math.max(...keyPriorities) const versionKey = Object.keys(priorityMap).find( (key) => priorityMap[key] === priority ) - return versionKey || config['version-resolver'].default + + core.debug('versionKey: ' + versionKey) + + const versionKeyIncrement = versionKey || config['version-resolver'].default + + const shouldIncrementAsPrerelease = + isPreRelease && config['pre-release-identifier'] + + if (!shouldIncrementAsPrerelease) { + return versionKeyIncrement + } + + return `pre${versionKeyIncrement}` } const generateReleaseInfo = ({ @@ -348,16 +375,27 @@ const generateReleaseInfo = ({ config.replacers ) + const versionKeyIncrement = resolveVersionKeyIncrement( + mergedPullRequests, + config, + isPreRelease + ) + + core.debug('versionKeyIncrement: ' + versionKeyIncrement) + const versionInfo = getVersionInfo( lastRelease, config['version-template'], // Use the first override parameter to identify // a version, from the most accurate to the least version || tag || name, - resolveVersionKeyIncrement(mergedPullRequests, config), - config['tag-prefix'] + versionKeyIncrement, + config['tag-prefix'], + config['pre-release-identifier'] ) + core.debug('versionInfo: ' + JSON.stringify(versionInfo, null, 2)) + if (versionInfo) { body = template(body, versionInfo) } @@ -368,6 +406,8 @@ const generateReleaseInfo = ({ tag = template(tag, versionInfo) } + core.debug('tag: ' + tag) + if (name === undefined) { name = versionInfo ? template(config['name-template'] || '', versionInfo) @@ -376,6 +416,8 @@ const generateReleaseInfo = ({ name = template(name, versionInfo) } + core.debug('name: ' + name) + // Tags are not supported as `target_commitish` by Github API. // GITHUB_REF or the ref from webhook start with `refs/tags/`, so we handle // those here. If it doesn't but is still a tag - it must have been set diff --git a/lib/schema.js b/lib/schema.js index b17e40620..b6056518c 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -77,6 +77,10 @@ const schema = (context) => { prerelease: Joi.boolean().default(DEFAULT_CONFIG.prerelease), + 'pre-release-identifier': Joi.string() + .allow('') + .default(DEFAULT_CONFIG['pre-release-identifier']), + 'filter-by-commitish': Joi.boolean().default( DEFAULT_CONFIG['filter-by-commitish'] ), diff --git a/lib/versions.js b/lib/versions.js index 83c8dbd5b..6c22e28ae 100644 --- a/lib/versions.js +++ b/lib/versions.js @@ -1,4 +1,5 @@ const semver = require('semver') +const core = require('@actions/core') const splitSemVersion = (input, versionKey = 'version') => { if (!input[versionKey]) { @@ -6,15 +7,18 @@ const splitSemVersion = (input, versionKey = 'version') => { } const version = input.inc - ? semver.inc(input[versionKey], input.inc, true) + ? semver.inc(input[versionKey], input.inc, true, input.preReleaseIdentifier) : input[versionKey].version + const prereleaseVersion = semver.prerelease(version)?.join('.') || '' + return { ...input, version, $MAJOR: semver.major(version), $MINOR: semver.minor(version), $PATCH: semver.patch(version), + $PRERELEASE: prereleaseVersion ? `-${prereleaseVersion}` : '', $COMPLETE: version, } } @@ -29,6 +33,7 @@ const defaultVersionInfo = { $MAJOR: 1, $MINOR: 0, $PATCH: 0, + $PRERELEASE: '', }, $NEXT_MINOR_VERSION: { version: '0.1.0', @@ -39,6 +44,7 @@ const defaultVersionInfo = { $MAJOR: 0, $MINOR: 1, $PATCH: 0, + $PRERELEASE: '', }, $NEXT_PATCH_VERSION: { version: '0.1.0', @@ -49,6 +55,19 @@ const defaultVersionInfo = { $MAJOR: 0, $MINOR: 1, $PATCH: 0, + $PRERELEASE: '', + }, + $NEXT_PRERELEASE_VERSION: { + version: '0.1.0-rc.0', + template: '$MAJOR.$MINOR.$PATCH$PRERELEASE', + inputVersion: null, + versionKeyIncrement: 'prerelease', + inc: 'prerelease', + preReleaseIdentifier: 'rc', + $MAJOR: 0, + $MINOR: 1, + $PATCH: 0, + $PRERELEASE: '-rc.0', }, $INPUT_VERSION: null, $RESOLVED_VERSION: { @@ -60,6 +79,7 @@ const defaultVersionInfo = { $MAJOR: 0, $MINOR: 1, $PATCH: 0, + $PRERELEASE: '', }, } @@ -113,6 +133,11 @@ const getTemplatableVersion = (input) => { inc: 'patch', template: '$PATCH', }), + $NEXT_PRERELEASE_VERSION: splitSemVersion({ + ...input, + inc: 'prerelease', + template: '$PRERELEASE', + }), $INPUT_VERSION: splitSemVersion(input, 'inputVersion'), $RESOLVED_VERSION: splitSemVersion({ ...input, @@ -156,21 +181,53 @@ const getVersionInfo = ( template, inputVersion, versionKeyIncrement, - tagPrefix + tagPrefix, + preReleaseIdentifier ) => { const version = coerceVersion(release, tagPrefix) inputVersion = coerceVersion(inputVersion, tagPrefix) + const isPreVersionKeyIncrement = versionKeyIncrement?.startsWith('pre') + if (!version && !inputVersion) { + if (isPreVersionKeyIncrement) { + defaultVersionInfo['$RESOLVED_VERSION'] = { + ...defaultVersionInfo['$NEXT_PRERELEASE_VERSION'], + } + } + return defaultVersionInfo } + const shouldIncrementAsPrerelease = + isPreVersionKeyIncrement && version?.prerelease + + if (shouldIncrementAsPrerelease) { + versionKeyIncrement = 'prerelease' + } + + core.debug( + `version template params: ` + + JSON.stringify( + { + version, + template, + inputVersion, + versionKeyIncrement, + preReleaseIdentifier, + }, + null, + true + ) + ) + return { ...getTemplatableVersion({ version, template, inputVersion, versionKeyIncrement, + preReleaseIdentifier, }), } } diff --git a/schema.json b/schema.json index 66ab1148e..cad69f6df 100644 --- a/schema.json +++ b/schema.json @@ -32,7 +32,7 @@ "type": "string" }, "version-template": { - "default": "$MAJOR.$MINOR.$PATCH", + "default": "$MAJOR.$MINOR.$PATCH$PRERELEASE", "type": "string" }, "name-template": { @@ -125,6 +125,18 @@ "default": false, "type": "boolean" }, + "pre-release-identifier": { + "anyOf": [ + { + "type": "string", + "enum": [""] + }, + { + "default": "", + "type": "string" + } + ] + }, "commitish": { "anyOf": [ { diff --git a/test/fixtures/config/config-with-pre-release-identifier.yml b/test/fixtures/config/config-with-pre-release-identifier.yml new file mode 100644 index 000000000..577b95aa6 --- /dev/null +++ b/test/fixtures/config/config-with-pre-release-identifier.yml @@ -0,0 +1,4 @@ +template: This is a Pre-release with identifier. +name-template: 'v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' +pre-release-identifier: alpha diff --git a/test/index.test.js b/test/index.test.js index bba6dbed8..5b81f88ca 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -2661,6 +2661,20 @@ describe('release-drafter', () => { } ) }) + + it('resolves tag with incremented pre-release identifier', async () => { + return overridesTest( + { + prerelease: 'true', + configName: 'config-with-pre-release-identifier.yml', + }, + { + prerelease: true, + name: 'v2.0.1-alpha.0', + tag_name: 'v2.0.1-alpha.0', + } + ) + }) }) describe('with input prerelease: false', () => { diff --git a/test/releases.test.js b/test/releases.test.js index 3d8e80f80..67b329fc3 100644 --- a/test/releases.test.js +++ b/test/releases.test.js @@ -211,6 +211,7 @@ describe('releases', () => { " `) }) + it('does not add proper details/summary markdown when collapse-after is set and less than 3 PRs', () => { const config = { ...baseConfig, @@ -275,5 +276,77 @@ describe('releases', () => { }) expect(lastRelease.tag_name).toEqual('test-1.0.1') }) + + const paginateMock = jest.fn() + const context = { + payload: { repository: { full_name: 'test' } }, + octokit: { + paginate: paginateMock, + repos: { listReleases: { endpoint: { merge: jest.fn() } } }, + }, + repo: jest.fn(), + log: { info: jest.fn(), warn: jest.fn() }, + } + + it('should return last release without draft and prerelease', async () => { + paginateMock.mockResolvedValueOnce([ + { tag_name: 'v1.0.0', draft: true, prerelease: false }, + { tag_name: 'v1.0.1', draft: false, prerelease: false }, + { tag_name: 'v1.0.2-rc.1', draft: false, prerelease: true }, + ]) + + const { lastRelease } = await findReleases({ + context, + targetCommitish: 'refs/heads/master', + tagPrefix: '', + }) + + expect(lastRelease).toEqual({ + tag_name: 'v1.0.1', + draft: false, + prerelease: false, + }) + }) + + it('should return last draft release', async () => { + paginateMock.mockResolvedValueOnce([ + { tag_name: 'v1.0.0', draft: true, prerelease: false }, + { tag_name: 'v1.0.1', draft: false, prerelease: false }, + { tag_name: 'v1.0.2-rc.1', draft: false, prerelease: true }, + ]) + + const { draftRelease } = await findReleases({ + context, + targetCommitish: 'refs/heads/master', + tagPrefix: '', + }) + + expect(draftRelease).toEqual({ + tag_name: 'v1.0.0', + draft: true, + prerelease: false, + }) + }) + + it('should return last prerelease as last release when includePreReleases is true', async () => { + paginateMock.mockResolvedValueOnce([ + { tag_name: 'v1.0.0', draft: true, prerelease: false }, + { tag_name: 'v1.0.1', draft: false, prerelease: false }, + { tag_name: 'v1.0.2-rc.1', draft: false, prerelease: true }, + ]) + + const { lastRelease } = await findReleases({ + context, + targetCommitish: 'refs/heads/master', + tagPrefix: '', + includePreReleases: true, + }) + + expect(lastRelease).toEqual({ + tag_name: 'v1.0.2-rc.1', + draft: false, + prerelease: true, + }) + }) }) }) diff --git a/test/versions.test.js b/test/versions.test.js index d524989ac..3f5b8d790 100644 --- a/test/versions.test.js +++ b/test/versions.test.js @@ -16,6 +16,7 @@ describe('versions', () => { $MAJOR: '11.0.0', $MINOR: '10.1.0', $PATCH: '10.0.4', + $PRERELEASE: '10.0.4-0', $RESOLVED: '10.0.4', }, }, @@ -33,6 +34,7 @@ describe('versions', () => { $MINOR: '10.1.0', $PATCH: '10.0.4', $RESOLVED: '10.0.4', + $PRERELEASE: '10.0.4-0', }, }, ], @@ -48,6 +50,7 @@ describe('versions', () => { $MAJOR: '11.0.0', $MINOR: '10.1.0', $PATCH: '10.0.4', + $PRERELEASE: '10.0.4-0', $RESOLVED: '10.0.4', }, }, @@ -65,72 +68,123 @@ describe('versions', () => { $MAJOR: '11.0.0', $MINOR: '10.1.0', $PATCH: '10.0.3', + $PRERELEASE: '10.0.3-alpha.0', $RESOLVED: '10.0.3-alpha', $INPUT: '10.0.3-alpha', }, }, ], - ])(`%s`, (name, { release, template, inputVersion, expected }) => { - const versionInfo = getVersionInfo(release, template, inputVersion) + [ + 'handles incremental pre-releases', + { + release: { + tag_name: 'v10.0.3', + name: 'Some release', + }, + template: '$MAJOR.$MINOR.$PATCH', + preReleaseIdentifier: 'alpha', + expected: { + $MAJOR: '11.0.0', + $MINOR: '10.1.0', + $PATCH: '10.0.4', + $PRERELEASE: '10.0.4-alpha.0', + $RESOLVED: '10.0.4', + }, + }, + ], + [ + 'handles incremental pre-releases on existing pre-releases', + { + release: { + tag_name: 'v10.0.3-alpha.2', + name: 'Some release', + }, + template: '$MAJOR.$MINOR.$PATCH', + expected: { + $MAJOR: '11.0.0', + $MINOR: '10.1.0', + $PATCH: '10.0.3', + $PRERELEASE: '10.0.3-alpha.3', + $RESOLVED: '10.0.3', + }, + }, + ], + ])( + `%s`, + ( + name, + { release, template, inputVersion, preReleaseIdentifier, expected } + ) => { + const versionInfo = getVersionInfo( + release, + template, + inputVersion, + undefined, + undefined, + preReleaseIdentifier + ) - // Next major version checks - expect(versionInfo.$NEXT_MAJOR_VERSION.version).toEqual(expected.$MAJOR) - expect(versionInfo.$NEXT_MAJOR_VERSION.template).toEqual( - '$MAJOR.$MINOR.$PATCH' - ) - expect(versionInfo.$NEXT_MAJOR_VERSION_MAJOR.version).toEqual( - expected.$MAJOR - ) - expect(versionInfo.$NEXT_MAJOR_VERSION_MAJOR.template).toEqual('$MAJOR') - expect(versionInfo.$NEXT_MAJOR_VERSION_MINOR.version).toEqual( - expected.$MAJOR - ) - expect(versionInfo.$NEXT_MAJOR_VERSION_MINOR.template).toEqual('$MINOR') - expect(versionInfo.$NEXT_MAJOR_VERSION_PATCH.version).toEqual( - expected.$MAJOR - ) - expect(versionInfo.$NEXT_MAJOR_VERSION_PATCH.template).toEqual('$PATCH') + // Next major version checks + expect(versionInfo.$NEXT_MAJOR_VERSION.version).toEqual(expected.$MAJOR) + expect(versionInfo.$NEXT_MAJOR_VERSION.template).toEqual(template) + expect(versionInfo.$NEXT_MAJOR_VERSION_MAJOR.version).toEqual( + expected.$MAJOR + ) + expect(versionInfo.$NEXT_MAJOR_VERSION_MAJOR.template).toEqual('$MAJOR') + expect(versionInfo.$NEXT_MAJOR_VERSION_MINOR.version).toEqual( + expected.$MAJOR + ) + expect(versionInfo.$NEXT_MAJOR_VERSION_MINOR.template).toEqual('$MINOR') + expect(versionInfo.$NEXT_MAJOR_VERSION_PATCH.version).toEqual( + expected.$MAJOR + ) + expect(versionInfo.$NEXT_MAJOR_VERSION_PATCH.template).toEqual('$PATCH') - // Next minor version checks - expect(versionInfo.$NEXT_MINOR_VERSION.version).toEqual(expected.$MINOR) - expect(versionInfo.$NEXT_MINOR_VERSION.template).toEqual( - '$MAJOR.$MINOR.$PATCH' - ) - expect(versionInfo.$NEXT_MINOR_VERSION_MAJOR.version).toEqual( - expected.$MINOR - ) - expect(versionInfo.$NEXT_MINOR_VERSION_MAJOR.template).toEqual('$MAJOR') - expect(versionInfo.$NEXT_MINOR_VERSION_MINOR.version).toEqual( - expected.$MINOR - ) - expect(versionInfo.$NEXT_MINOR_VERSION_MINOR.template).toEqual('$MINOR') - expect(versionInfo.$NEXT_MINOR_VERSION_PATCH.version).toEqual( - expected.$MINOR - ) - expect(versionInfo.$NEXT_MINOR_VERSION_PATCH.template).toEqual('$PATCH') + // Next minor version checks + expect(versionInfo.$NEXT_MINOR_VERSION.version).toEqual(expected.$MINOR) + expect(versionInfo.$NEXT_MINOR_VERSION.template).toEqual(template) + expect(versionInfo.$NEXT_MINOR_VERSION_MAJOR.version).toEqual( + expected.$MINOR + ) + expect(versionInfo.$NEXT_MINOR_VERSION_MAJOR.template).toEqual('$MAJOR') + expect(versionInfo.$NEXT_MINOR_VERSION_MINOR.version).toEqual( + expected.$MINOR + ) + expect(versionInfo.$NEXT_MINOR_VERSION_MINOR.template).toEqual('$MINOR') + expect(versionInfo.$NEXT_MINOR_VERSION_PATCH.version).toEqual( + expected.$MINOR + ) + expect(versionInfo.$NEXT_MINOR_VERSION_PATCH.template).toEqual('$PATCH') - // Next patch version checks - expect(versionInfo.$NEXT_PATCH_VERSION.version).toEqual(expected.$PATCH) - expect(versionInfo.$NEXT_PATCH_VERSION.template).toEqual( - '$MAJOR.$MINOR.$PATCH' - ) - expect(versionInfo.$NEXT_PATCH_VERSION_MAJOR.version).toEqual( - expected.$PATCH - ) - expect(versionInfo.$NEXT_PATCH_VERSION_MAJOR.template).toEqual('$MAJOR') - expect(versionInfo.$NEXT_PATCH_VERSION_MINOR.version).toEqual( - expected.$PATCH - ) - expect(versionInfo.$NEXT_PATCH_VERSION_MINOR.template).toEqual('$MINOR') - expect(versionInfo.$NEXT_PATCH_VERSION_PATCH.version).toEqual( - expected.$PATCH - ) - expect(versionInfo.$NEXT_PATCH_VERSION_PATCH.template).toEqual('$PATCH') + // Next patch version checks + expect(versionInfo.$NEXT_PATCH_VERSION.version).toEqual(expected.$PATCH) + expect(versionInfo.$NEXT_PATCH_VERSION.template).toEqual(template) + expect(versionInfo.$NEXT_PATCH_VERSION_MAJOR.version).toEqual( + expected.$PATCH + ) + expect(versionInfo.$NEXT_PATCH_VERSION_MAJOR.template).toEqual('$MAJOR') + expect(versionInfo.$NEXT_PATCH_VERSION_MINOR.version).toEqual( + expected.$PATCH + ) + expect(versionInfo.$NEXT_PATCH_VERSION_MINOR.template).toEqual('$MINOR') + expect(versionInfo.$NEXT_PATCH_VERSION_PATCH.version).toEqual( + expected.$PATCH + ) + expect(versionInfo.$NEXT_PATCH_VERSION_PATCH.template).toEqual('$PATCH') - expect(versionInfo.$NEXT_PATCH_VERSION.version).toEqual(expected.$PATCH) - expect(versionInfo.$INPUT_VERSION?.version).toEqual(expected.$INPUT) - expect(versionInfo.$RESOLVED_VERSION.version).toEqual(expected.$RESOLVED) - }) + // Next pre-release version checks + expect(versionInfo.$NEXT_PRERELEASE_VERSION.version).toEqual( + expected.$PRERELEASE + ) + expect(versionInfo.$NEXT_PRERELEASE_VERSION.template).toEqual( + '$PRERELEASE' + ) + + // Input & Resolved version checks + expect(versionInfo.$INPUT_VERSION?.version).toEqual(expected.$INPUT) + expect(versionInfo.$RESOLVED_VERSION.version).toEqual(expected.$RESOLVED) + } + ) it('returns default version info if no version was found in tag or name', () => { const versionInfo = getVersionInfo({})