From df81f9a925979a1e645e49215852140b208e0bf2 Mon Sep 17 00:00:00 2001 From: Joseph Earl Date: Mon, 22 Apr 2024 21:20:33 +0100 Subject: [PATCH] feat: add build info --- README.md | 11 ++- build/action.cjs | 27 +++---- src/core/action.test.ts | 24 ++++-- src/core/action.ts | 5 +- src/core/version.test.ts | 156 ++++++++++++++++++++++++++++++--------- src/core/version.ts | 28 +++---- 6 files changed, 170 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index 595d212..cd05c93 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ Otherwise the version and its components are avaialbe through action outputs. echo "v${{ steps.semver.outputs.major }}" echo "v${{ steps.semver.outputs.minor }}" echo "v${{ steps.semver.outputs.patch }}" - echo "v${{ steps.semver.outputs.extra }}" + echo "v${{ steps.semver.outputs.prerelease }}" + echo "v${{ steps.semver.outputs.build }}" ``` ## Inputs @@ -48,15 +49,17 @@ The following outputs are available through `steps..outputs` when the action | Name | Type | Description | Example | | ---- | --- | ------------ | ------- | -| `version` | `string` | The full version wihout prefixes | `2.13.34-dev` | +| `version` | `string` | The full version without prefixes | `2.13.34-dev+001` | | `major` | `string` | The major version number | `2` | | `minor` | `string` | The minor version number | `13` | | `patch` | `string` | The patch version number | `34` | -| `extra` | `string` | The prerelease version or extra | `dev` | +| `prerelease` | `string` | The prerelease version | `dev` | +| `build` | `string` | The build metadata | `001` | > [!TIP] > The version is coerced in to a semantic version as per the [resolution strategy](#resolution-strategy), therefore all outputs will be present assuming the action succeeds. -> In all cases the `extra` output will always be an empty string (`""`) unless provided in the [prerelease version](https://semver.org/#spec-item-9). +> In all cases the `prerelease` output will always be an empty string (`""`) unless provided in the [prerelease version](https://semver.org/#spec-item-9). +> Similarly the `build` output will always be an empty string (`""`) unless provided in the [build metadata](https://semver.org/#spec-item-10). ## Resolution Strategy diff --git a/build/action.cjs b/build/action.cjs index 079b302..4049ebf 100644 --- a/build/action.cjs +++ b/build/action.cjs @@ -2685,25 +2685,18 @@ var normaliseInputStringValue = (value) => { // src/core/version.ts var import_coerce = __toESM(require_coerce()); var resolveVersionFromString = (value) => { - const refless = value.replace(/^refs\/tags\//, ""); - const coerced = (0, import_coerce.default)(refless); - if (coerced === null) { + const version2 = (0, import_coerce.default)(value, { includePrerelease: true }); + if (version2 === null) { return void 0; } - let extra = ""; - let version2 = coerced.format(); - const prerelease = refless.indexOf("-"); - if (prerelease > -1) { - extra = refless.slice(prerelease + 1); - version2 = `${version2}-${extra}`; - } return { - version: version2, + version: version2.format(), part: { - major: coerced.major.toString(), - minor: coerced.minor.toString(), - patch: coerced.patch.toString(), - extra + major: version2.major.toString(), + minor: version2.minor.toString(), + patch: version2.patch.toString(), + prerelease: version2.prerelease.join("."), + build: version2.build.join(".") } }; }; @@ -2725,7 +2718,9 @@ var action = async (action2) => { action2.output("major", validated.part.major); action2.output("minor", validated.part.minor); action2.output("patch", validated.part.patch); - action2.output("extra", validated.part.extra); + action2.output("extra", validated.part.prerelease); + action2.output("prerelease", validated.part.prerelease); + action2.output("build", validated.part.build); } catch (error) { action2.fail(`An unexpected error occured: ${error}`); } diff --git a/src/core/action.test.ts b/src/core/action.test.ts index 6381947..9cb96e8 100644 --- a/src/core/action.test.ts +++ b/src/core/action.test.ts @@ -19,12 +19,14 @@ describe('action()', (): void => { expect(input).toBeCalledTimes(1); expect(input).toHaveBeenNthCalledWith<[string, ActionInputFunctionOptions]>(1, 'version', { required: true }); - expect(output).toBeCalledTimes(5); + expect(output).toBeCalledTimes(7); expect(output).toHaveBeenNthCalledWith<[string, string]>(1, 'version', '1.2.3'); expect(output).toHaveBeenNthCalledWith<[string, string]>(2, 'major', '1'); expect(output).toHaveBeenNthCalledWith<[string, string]>(3, 'minor', '2'); expect(output).toHaveBeenNthCalledWith<[string, string]>(4, 'patch', '3'); expect(output).toHaveBeenNthCalledWith<[string, string]>(5, 'extra', ''); + expect(output).toHaveBeenNthCalledWith<[string, string]>(6, 'prerelease', ''); + expect(output).toHaveBeenNthCalledWith<[string, string]>(7, 'build', ''); expect(fail).toBeCalledTimes(0); }); @@ -34,7 +36,7 @@ describe('action()', (): void => { const output = fn(); const fail = fn(); - input.mockReturnValueOnce('10.23.4'); + input.mockReturnValueOnce('v10.23.4'); await action({ input, @@ -45,12 +47,14 @@ describe('action()', (): void => { expect(input).toBeCalledTimes(1); expect(input).toHaveBeenNthCalledWith<[string, ActionInputFunctionOptions]>(1, 'version', { required: true }); - expect(output).toBeCalledTimes(5); + expect(output).toBeCalledTimes(7); expect(output).toHaveBeenNthCalledWith<[string, string]>(1, 'version', '10.23.4'); expect(output).toHaveBeenNthCalledWith<[string, string]>(2, 'major', '10'); expect(output).toHaveBeenNthCalledWith<[string, string]>(3, 'minor', '23'); expect(output).toHaveBeenNthCalledWith<[string, string]>(4, 'patch', '4'); expect(output).toHaveBeenNthCalledWith<[string, string]>(5, 'extra', ''); + expect(output).toHaveBeenNthCalledWith<[string, string]>(6, 'prerelease', ''); + expect(output).toHaveBeenNthCalledWith<[string, string]>(7, 'build', ''); expect(fail).toBeCalledTimes(0); }); @@ -60,7 +64,7 @@ describe('action()', (): void => { const output = fn(); const fail = fn(); - input.mockReturnValueOnce('2.3-alpha.2'); + input.mockReturnValueOnce('2.3-alpha.2+001'); await action({ input, @@ -71,12 +75,14 @@ describe('action()', (): void => { expect(input).toBeCalledTimes(1); expect(input).toHaveBeenNthCalledWith<[string, ActionInputFunctionOptions]>(1, 'version', { required: true }); - expect(output).toBeCalledTimes(5); + expect(output).toBeCalledTimes(7); expect(output).toHaveBeenNthCalledWith<[string, string]>(1, 'version', '2.3.0-alpha.2'); expect(output).toHaveBeenNthCalledWith<[string, string]>(2, 'major', '2'); expect(output).toHaveBeenNthCalledWith<[string, string]>(3, 'minor', '3'); expect(output).toHaveBeenNthCalledWith<[string, string]>(4, 'patch', '0'); expect(output).toHaveBeenNthCalledWith<[string, string]>(5, 'extra', 'alpha.2'); + expect(output).toHaveBeenNthCalledWith<[string, string]>(6, 'prerelease', 'alpha.2'); + expect(output).toHaveBeenNthCalledWith<[string, string]>(7, 'build', '001'); expect(fail).toBeCalledTimes(0); }); @@ -97,12 +103,14 @@ describe('action()', (): void => { expect(input).toBeCalledTimes(1); expect(input).toHaveBeenNthCalledWith<[string, ActionInputFunctionOptions]>(1, 'version', { required: true }); - expect(output).toBeCalledTimes(5); + expect(output).toBeCalledTimes(7); expect(output).toHaveBeenNthCalledWith<[string, string]>(1, 'version', '4.36.14'); expect(output).toHaveBeenNthCalledWith<[string, string]>(2, 'major', '4'); expect(output).toHaveBeenNthCalledWith<[string, string]>(3, 'minor', '36'); expect(output).toHaveBeenNthCalledWith<[string, string]>(4, 'patch', '14'); expect(output).toHaveBeenNthCalledWith<[string, string]>(5, 'extra', ''); + expect(output).toHaveBeenNthCalledWith<[string, string]>(6, 'prerelease', ''); + expect(output).toHaveBeenNthCalledWith<[string, string]>(7, 'build', ''); expect(fail).toBeCalledTimes(0); }); @@ -123,12 +131,14 @@ describe('action()', (): void => { expect(input).toBeCalledTimes(1); expect(input).toHaveBeenNthCalledWith<[string, ActionInputFunctionOptions]>(1, 'version', { required: true }); - expect(output).toBeCalledTimes(5); + expect(output).toBeCalledTimes(7); expect(output).toHaveBeenNthCalledWith<[string, string]>(1, 'version', '5.31.12-beta.1'); expect(output).toHaveBeenNthCalledWith<[string, string]>(2, 'major', '5'); expect(output).toHaveBeenNthCalledWith<[string, string]>(3, 'minor', '31'); expect(output).toHaveBeenNthCalledWith<[string, string]>(4, 'patch', '12'); expect(output).toHaveBeenNthCalledWith<[string, string]>(5, 'extra', 'beta.1'); + expect(output).toHaveBeenNthCalledWith<[string, string]>(6, 'prerelease', 'beta.1'); + expect(output).toHaveBeenNthCalledWith<[string, string]>(7, 'build', ''); expect(fail).toBeCalledTimes(0); }); diff --git a/src/core/action.ts b/src/core/action.ts index 03943a7..c9e4a96 100644 --- a/src/core/action.ts +++ b/src/core/action.ts @@ -54,7 +54,10 @@ export const action = async (action: ActionDependencies): Promise => { action.output('major', validated.part.major); action.output('minor', validated.part.minor); action.output('patch', validated.part.patch); - action.output('extra', validated.part.extra); + // TODO: Remove `extra` in v3, replaced with `prerelease` + action.output('extra', validated.part.prerelease); + action.output('prerelease', validated.part.prerelease); + action.output('build', validated.part.build); } catch (error: unknown) { action.fail(`An unexpected error occured: ${error}`); } diff --git a/src/core/version.test.ts b/src/core/version.test.ts index d14a090..2bb1e58 100644 --- a/src/core/version.test.ts +++ b/src/core/version.test.ts @@ -9,47 +9,129 @@ describe('resolve()', (): void => { major: string; minor: string; patch: string; - extra: string; + prerelease: string; + build: string; }; it.each([ - { input: '1', version: '1.0.0', major: '1', minor: '0', patch: '0', extra: '' }, - { input: 'v3', version: '3.0.0', major: '3', minor: '0', patch: '0', extra: '' }, + /* Release */ + { input: '1', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'v1', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'refs/tags/v1', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'release/v1', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: '1.2', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'v1.2', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'refs/tags/v1.2', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'release/v1.2', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1.2', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: '1.2.3', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'v1.2.3', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'refs/tags/v1.2.3', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'release/v1.2.3', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1.2.3', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, - { input: '1.0', version: '1.0.0', major: '1', minor: '0', patch: '0', extra: '' }, - { input: '1.1', version: '1.1.0', major: '1', minor: '1', patch: '0', extra: '' }, - { input: 'v3.4', version: '3.4.0', major: '3', minor: '4', patch: '0', extra: '' }, + /* Pre-release */ + { input: '1-beta.1', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', prerelease: 'beta.1', build: '' }, + { input: 'v1-beta.1', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', prerelease: 'beta.1', build: '' }, + { input: 'refs/tags/v1-beta.1', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', prerelease: 'beta.1', build: '' }, + { input: 'release/v1-beta.1', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', prerelease: 'beta.1', build: '' }, + { input: 'refs/heads/release/v1-beta.1', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', prerelease: 'beta.1', build: '' }, + { input: '1.2-dev', version: '1.2.0-dev', major: '1', minor: '2', patch: '0', prerelease: 'dev', build: '' }, + { input: 'v1.2-dev', version: '1.2.0-dev', major: '1', minor: '2', patch: '0', prerelease: 'dev', build: '' }, + { input: 'refs/tags/v1.2-dev', version: '1.2.0-dev', major: '1', minor: '2', patch: '0', prerelease: 'dev', build: '' }, + { input: 'release/v1.2-dev', version: '1.2.0-dev', major: '1', minor: '2', patch: '0', prerelease: 'dev', build: '' }, + { input: 'refs/heads/release/v1.2-dev', version: '1.2.0-dev', major: '1', minor: '2', patch: '0', prerelease: 'dev', build: '' }, + { input: '1.2.3-dev-2022-01-01', version: '1.2.3-dev-2022-01-01', major: '1', minor: '2', patch: '3', prerelease: 'dev-2022-01-01', build: '' }, + { input: 'v1.2.3-dev-2022-01-01', version: '1.2.3-dev-2022-01-01', major: '1', minor: '2', patch: '3', prerelease: 'dev-2022-01-01', build: '' }, + { input: 'refs/tags/v1.2.3-dev-2022-01-01', version: '1.2.3-dev-2022-01-01', major: '1', minor: '2', patch: '3', prerelease: 'dev-2022-01-01', build: '' }, + { input: 'release/v1.2.3-dev-2022-01-01', version: '1.2.3-dev-2022-01-01', major: '1', minor: '2', patch: '3', prerelease: 'dev-2022-01-01', build: '' }, + { input: 'refs/heads/release/v1.2.3-dev-2022-01-01', version: '1.2.3-dev-2022-01-01', major: '1', minor: '2', patch: '3', prerelease: 'dev-2022-01-01', build: '' }, - { input: 'v1.0.0', version: '1.0.0', major: '1', minor: '0', patch: '0', extra: '' }, - { input: 'v1.2.3', version: '1.2.3', major: '1', minor: '2', patch: '3', extra: '' }, - { input: 'v3.4.2', version: '3.4.2', major: '3', minor: '4', patch: '2', extra: '' }, + /* Empty pre-release */ + { input: '1-', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'v1-', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'refs/tags/v1-', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'release/v1-', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1-', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: '1.2-', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'v1.2-', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'refs/tags/v1.2-', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'release/v1.2-', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1.2-', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: '1.2.3-', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'v1.2.3-', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'refs/tags/v1.2.3-', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'release/v1.2.3-', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1.2.3-', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, - { input: 'refs/tags/1', version: '1.0.0', major: '1', minor: '0', patch: '0', extra: '' }, - { input: 'refs/tags/3', version: '3.0.0', major: '3', minor: '0', patch: '0', extra: '' }, - { input: 'refs/tags/v3', version: '3.0.0', major: '3', minor: '0', patch: '0', extra: '' }, + /* Build */ + { input: '1+21AF26D3----117B344092BD', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '21AF26D3----117B344092BD' }, + { input: 'v1+21AF26D3----117B344092BD', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '21AF26D3----117B344092BD' }, + { input: 'refs/tags/v1+21AF26D3----117B344092BD', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '21AF26D3----117B344092BD' }, + { input: 'release/v1+21AF26D3----117B344092BD', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '21AF26D3----117B344092BD' }, + { input: 'refs/heads/release/v1+21AF26D3----117B344092BD', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '21AF26D3----117B344092BD' }, + { input: '1.2+001', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '001' }, + { input: 'v1.2+001', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '001' }, + { input: 'refs/tags/v1.2+001', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '001' }, + { input: 'release/v1.2+001', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '001' }, + { input: 'refs/heads/release/v1.2+001', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '001' }, + { input: '1.2.3+exp.sha.5114f85', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: 'exp.sha.5114f85' }, + { input: 'v1.2.3+exp.sha.5114f85', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: 'exp.sha.5114f85' }, + { input: 'refs/tags/v1.2.3+exp.sha.5114f85', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: 'exp.sha.5114f85' }, + { input: 'release/v1.2.3+exp.sha.5114f85', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: 'exp.sha.5114f85' }, + { input: 'refs/heads/release/v1.2.3+exp.sha.5114f85', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: 'exp.sha.5114f85' }, - { input: 'refs/tags/1.0', version: '1.0.0', major: '1', minor: '0', patch: '0', extra: '' }, - { input: 'refs/tags/3.4', version: '3.4.0', major: '3', minor: '4', patch: '0', extra: '' }, - { input: 'refs/tags/v5.3', version: '5.3.0', major: '5', minor: '3', patch: '0', extra: '' }, + /* Empty build */ + { input: '1+', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'v1+', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'refs/tags/v1+', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'release/v1+', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1+', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: '1.2+', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'v1.2+', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'refs/tags/v1.2+', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'release/v1.2+', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1.2+', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: '1.2.3+', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'v1.2.3+', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'refs/tags/v1.2.3+', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'release/v1.2.3+', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1.2.3+', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, - { input: 'refs/tags/1.0.0', version: '1.0.0', major: '1', minor: '0', patch: '0', extra: '' }, - { input: 'refs/tags/3.4.2', version: '3.4.2', major: '3', minor: '4', patch: '2', extra: '' }, - { input: 'refs/tags/v4.6.1', version: '4.6.1', major: '4', minor: '6', patch: '1', extra: '' }, + /* Pre-release and build */ + { input: '1-beta.1+21AF26D3----117B344092BD', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', prerelease: 'beta.1', build: '21AF26D3----117B344092BD' }, + { input: 'v1-beta.1+21AF26D3----117B344092BD', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', prerelease: 'beta.1', build: '21AF26D3----117B344092BD' }, + { input: 'refs/tags/v1-beta.1+21AF26D3----117B344092BD', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', prerelease: 'beta.1', build: '21AF26D3----117B344092BD' }, + { input: 'release/v1-beta.1+21AF26D3----117B344092BD', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', prerelease: 'beta.1', build: '21AF26D3----117B344092BD' }, + { input: 'refs/heads/release/v1-beta.1+21AF26D3----117B344092BD', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', prerelease: 'beta.1', build: '21AF26D3----117B344092BD' }, + { input: '1.2-dev+001', version: '1.2.0-dev', major: '1', minor: '2', patch: '0', prerelease: 'dev', build: '001' }, + { input: 'v1.2-dev+001', version: '1.2.0-dev', major: '1', minor: '2', patch: '0', prerelease: 'dev', build: '001' }, + { input: 'refs/tags/v1.2-dev+001', version: '1.2.0-dev', major: '1', minor: '2', patch: '0', prerelease: 'dev', build: '001' }, + { input: 'release/v1.2-dev+001', version: '1.2.0-dev', major: '1', minor: '2', patch: '0', prerelease: 'dev', build: '001' }, + { input: 'refs/heads/release/v1.2-dev+001', version: '1.2.0-dev', major: '1', minor: '2', patch: '0', prerelease: 'dev', build: '001' }, + { input: '1.2.3-dev-2022-01-01+exp.sha.5114f85', version: '1.2.3-dev-2022-01-01', major: '1', minor: '2', patch: '3', prerelease: 'dev-2022-01-01', build: 'exp.sha.5114f85' }, + { input: 'v1.2.3-dev-2022-01-01+exp.sha.5114f85', version: '1.2.3-dev-2022-01-01', major: '1', minor: '2', patch: '3', prerelease: 'dev-2022-01-01', build: 'exp.sha.5114f85' }, + { input: 'refs/tags/v1.2.3-dev-2022-01-01+exp.sha.5114f85', version: '1.2.3-dev-2022-01-01', major: '1', minor: '2', patch: '3', prerelease: 'dev-2022-01-01', build: 'exp.sha.5114f85' }, + { input: 'release/v1.2.3-dev-2022-01-01+exp.sha.5114f85', version: '1.2.3-dev-2022-01-01', major: '1', minor: '2', patch: '3', prerelease: 'dev-2022-01-01', build: 'exp.sha.5114f85' }, + { input: 'refs/heads/release/v1.2.3-dev-2022-01-01+exp.sha.5114f85', version: '1.2.3-dev-2022-01-01', major: '1', minor: '2', patch: '3', prerelease: 'dev-2022-01-01', build: 'exp.sha.5114f85' }, - { input: '1-beta.1', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', extra: 'beta.1' }, - { input: '1.2-beta.2', version: '1.2.0-beta.2', major: '1', minor: '2', patch: '0', extra: 'beta.2' }, - { input: '1.2.3-beta.3', version: '1.2.3-beta.3', major: '1', minor: '2', patch: '3', extra: 'beta.3' }, - - { input: 'v1-beta.1', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', extra: 'beta.1' }, - { input: 'v1.2-beta.2', version: '1.2.0-beta.2', major: '1', minor: '2', patch: '0', extra: 'beta.2' }, - { input: 'v1.2.3-beta.3', version: '1.2.3-beta.3', major: '1', minor: '2', patch: '3', extra: 'beta.3' }, - - { input: 'refs/tags/v1-beta.1', version: '1.0.0-beta.1', major: '1', minor: '0', patch: '0', extra: 'beta.1' }, - { input: 'refs/tags/v1.2-beta.2', version: '1.2.0-beta.2', major: '1', minor: '2', patch: '0', extra: 'beta.2' }, - { input: 'refs/tags/v1.2.3-beta.3', version: '1.2.3-beta.3', major: '1', minor: '2', patch: '3', extra: 'beta.3' }, - - { input: '1.2.3-dev', version: '1.2.3-dev', major: '1', minor: '2', patch: '3', extra: 'dev' }, - { input: '1.2.3-dev-2022-01-01', version: '1.2.3-dev-2022-01-01', major: '1', minor: '2', patch: '3', extra: 'dev-2022-01-01' }, + /* Empty pre-release and build */ + { input: '1-+', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'v1-+', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'refs/tags/v1-+', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'release/v1-+', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1-+', version: '1.0.0', major: '1', minor: '0', patch: '0', prerelease: '', build: '' }, + { input: '1.2-+', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'v1.2-+', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'refs/tags/v1.2-+', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'release/v1.2-+', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1.2-+', version: '1.2.0', major: '1', minor: '2', patch: '0', prerelease: '', build: '' }, + { input: '1.2.3-+', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'v1.2.3-+', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'refs/tags/v1.2.3-+', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'release/v1.2.3-+', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, + { input: 'refs/heads/release/v1.2.3-+', version: '1.2.3', major: '1', minor: '2', patch: '3', prerelease: '', build: '' }, ])('with value, can cleanse, $input', (data): void => { const value = resolveVersionFromString(data.input); @@ -58,12 +140,16 @@ describe('resolve()', (): void => { expect(value?.part.major).toStrictEqual(data.major); expect(value?.part.minor).toStrictEqual(data.minor); expect(value?.part.patch).toStrictEqual(data.patch); - expect(value?.part.extra).toStrictEqual(data.extra); + expect(value?.part.prerelease).toStrictEqual(data.prerelease); + expect(value?.part.build).toStrictEqual(data.build); }); - it('with value, invalid, return null', (): void => { + it.each([ + 'a.b.c', + 'testing', + ])('with value, invalid, return null, $input', (version): void => { expect( - resolveVersionFromString('testing'), + resolveVersionFromString(version), ).toBeUndefined(); }); }); diff --git a/src/core/version.ts b/src/core/version.ts index 09af7bc..d211491 100644 --- a/src/core/version.ts +++ b/src/core/version.ts @@ -10,7 +10,8 @@ export type VersionBreakdown = { readonly major: string; readonly minor: string; readonly patch: string; - readonly extra: string; + readonly prerelease: string; + readonly build: string; }; }; @@ -18,30 +19,21 @@ export type VersionBreakdown = { * Resolve and cleanse the given {@link value} and coerce to a version. */ export const resolveVersionFromString = (value: string): VersionBreakdown | undefined => { - const refless = value.replace(/^refs\/tags\//, ''); - const coerced = coerce(refless); + const version = coerce(value, { includePrerelease: true }); - if (coerced === null) { + if (version === null) { return undefined; } - let extra = ''; - let version = coerced.format(); - - const prerelease = refless.indexOf('-'); - if (prerelease > -1) { - extra = refless.slice(prerelease + 1); - version = `${version}-${extra}`; - } - return { - version, + version: version.format(), part: { - major: coerced.major.toString(), - minor: coerced.minor.toString(), - patch: coerced.patch.toString(), - extra, + major: version.major.toString(), + minor: version.minor.toString(), + patch: version.patch.toString(), + prerelease: version.prerelease.join('.'), + build: version.build.join('.'), }, }; };