diff --git a/cli.js b/cli.js index 9040236228..c427355520 100755 --- a/cli.js +++ b/cli.js @@ -22,6 +22,7 @@ Usage: .option('b', {alias: 'branches', describe: 'Git branches to release from', ...stringList, group: 'Options'}) .option('r', {alias: 'repository-url', describe: 'Git repository URL', type: 'string', group: 'Options'}) .option('t', {alias: 'tag-format', describe: 'Git tag format', type: 'string', group: 'Options'}) + .option('prerelease-build-format', {describe: 'Prerelease build number format', type: 'string', group: 'Options'}) .option('p', {alias: 'plugins', describe: 'Plugins', ...stringList, group: 'Options'}) .option('e', {alias: 'extends', describe: 'Shareable configurations', ...stringList, group: 'Options'}) .option('ci', {describe: 'Toggle CI verifications', type: 'boolean', group: 'Options'}) diff --git a/docs/usage/configuration.md b/docs/usage/configuration.md index 38e2213cde..53c657c8d8 100644 --- a/docs/usage/configuration.md +++ b/docs/usage/configuration.md @@ -98,6 +98,25 @@ The [Git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) format used by **Note**: The `tagFormat` must contain the `version` variable exactly once and compile to a [valid Git reference](https://git-scm.com/docs/git-check-ref-format#_description). +### prereleaseBuildFormat + +Type: `String`
+Default: `undefined`
+CLI arguments: `--prerelease-build-format` + +The format used by **semantic-release** when appending prerelease build information after the auto increment prerelease number. If left unspecified, no build information will be appended, otherwise the parsed value of this formatter will be appended after a `+` in the resulting version, so there is no need to add one yourself. Using this option is useful if you want extra insight into which version of the project has been released, or if you need to avoid tag conflicts caused by more complex git workflows, like ones that utilize history rewrites. The build number is generated with [Lodash template](https://lodash.com/docs#template) and will be compiled with the following variables. + +- `gitHead` The current commit hash. Can use `gitHead.substr(0,7)` to use the short hash. +- `build` The current CI build number. This is useful when you need atomically increasing build numbers. + +**Examples**: + +| Previous Version | Prerelease Build Format | Branch | Commit Sha | Result | +| ---------------------- | ----------------------- | ------- | ---------- | ----------------------- | +| `1.1.3` | `${gitHead}` | `alpha` | `1a2b3c4` | `1.2.3-alpha.1+1a2b3c4` | +| `1.2.3-alpha.1+abcdef` | `${gitHead}` | `alpha` | `4d5e6f7` | `1.2.3-alpha.2+4d5e6f7` | +| `1.1.3` | | `alpha` | `1a2b3c4` | `1.2.3-alpha.1` | + ### plugins Type: `Array`
diff --git a/index.js b/index.js index 4d5aaedc73..e0d45901d3 100644 --- a/index.js +++ b/index.js @@ -165,6 +165,7 @@ async function run(context, plugins) { } context.nextRelease = nextRelease; + context.prereleaseBuildFormat = options.prereleaseBuildFormat; nextRelease.version = getNextVersion(context); nextRelease.gitTag = makeTag(options.tagFormat, nextRelease.version); nextRelease.name = nextRelease.gitTag; diff --git a/lib/get-next-version.js b/lib/get-next-version.js index 8734922d3e..3edbb288c6 100644 --- a/lib/get-next-version.js +++ b/lib/get-next-version.js @@ -1,8 +1,15 @@ const semver = require('semver'); +const {template} = require('lodash'); const {FIRST_RELEASE, FIRSTPRERELEASE} = require('./definitions/constants'); const {isSameChannel, getLatestVersion, tagsToVersions, highest} = require('./utils'); -module.exports = ({branch, nextRelease: {type, channel}, lastRelease, logger}) => { +module.exports = ({ + branch, + nextRelease: {type, channel, gitHead, build}, + lastRelease, + logger, + prereleaseBuildFormat, +}) => { let version; if (lastRelease.version) { const {major, minor, patch} = semver.parse(lastRelease.version); @@ -24,12 +31,16 @@ module.exports = ({branch, nextRelease: {type, channel}, lastRelease, logger}) = } else { version = semver.inc(lastRelease.version, type); } - - logger.log('The next release version is %s', version); } else { version = branch.type === 'prerelease' ? `${FIRST_RELEASE}-${branch.prerelease}.${FIRSTPRERELEASE}` : FIRST_RELEASE; - logger.log(`There is no previous release, the next release version is ${version}`); + logger.log(`There is no previous release`); + } + + if (branch.type === 'prerelease' && prereleaseBuildFormat) { + version += `+${template(prereleaseBuildFormat)({build, gitHead})}`; } + logger.log('The next release version is %s', version); + return version; }; diff --git a/test/get-next-version.test.js b/test/get-next-version.test.js index 63c906f078..d76b1101f2 100644 --- a/test/get-next-version.test.js +++ b/test/get-next-version.test.js @@ -275,3 +275,57 @@ test('Increase version for release on prerelease branch when there is no regular '1.0.0-beta.2' ); }); + +test('Append gitHead build number to prerelease version', (t) => { + t.is( + getNextVersion({ + branch: { + name: 'beta', + type: 'prerelease', + prerelease: 'beta', + tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]}], + }, + nextRelease: {type: 'minor', gitHead: '1a2b3c4d'}, + lastRelease: {version: '1.0.0', channels: [null]}, + logger: t.context.logger, + prereleaseBuildFormat: `\${gitHead}`, + }), + '1.1.0-beta.1+1a2b3c4d' + ); +}); + +test('Append CI build number to prerelease version', (t) => { + t.is( + getNextVersion({ + branch: { + name: 'beta', + type: 'prerelease', + prerelease: 'beta', + tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]}], + }, + nextRelease: {type: 'minor', build: '1234'}, + lastRelease: {version: '1.0.0', channels: [null]}, + logger: t.context.logger, + prereleaseBuildFormat: `\${build}`, + }), + '1.1.0-beta.1+1234' + ); +}); + +test('Append new gitHead build number to next prerelease version', (t) => { + t.is( + getNextVersion({ + branch: { + name: 'beta', + type: 'prerelease', + prerelease: 'beta', + tags: [{gitTag: 'v1.1.0-beta.1+1a2b3c4', version: '1.1.0-beta.1+1a2b3c4', channels: ['beta']}], + }, + nextRelease: {type: 'minor', channel: 'beta', gitHead: '4d5e6f7'}, + lastRelease: {version: 'v1.1.0-beta.1+1a2b3c4', channels: ['beta']}, + logger: t.context.logger, + prereleaseBuildFormat: `\${gitHead}`, + }), + '1.1.0-beta.2+4d5e6f7' + ); +});