diff --git a/README.md b/README.md index ec41a2e4e..7fac24625 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ jobs: - **custom_tag** _(optional)_ - Custom tag name. If specified, it overrides bump settings. - **create_annotated_tag** _(optional)_ - Boolean to create an annotated rather than a lightweight one (default: `false`). - **tag_prefix** _(optional)_ - A prefix to the tag name (default: `v`). +- **prefix_match_tag** _(optional)_ - Enhance tag validity check: given tag mush MATCH with tag_prefix + SemVer notation. (default: `false`). - **append_to_pre_release_tag** _(optional)_ - A suffix to the pre-release tag name (default: ``). #### Customize the conventional commit messages & titles of changelog sections diff --git a/action.yml b/action.yml index ea5310ff2..91397e5ae 100644 --- a/action.yml +++ b/action.yml @@ -28,6 +28,10 @@ inputs: description: "A prefix to the tag name (default: `v`)." required: false default: "v" + prefix_match_tag: + description: "Enhance tag validity check: given tag mush MATCH with tag_prefix + SemVer notation." + required: false + default: "false" append_to_pre_release_tag: description: "A suffix to a pre-release tag name (default: ``)." required: false diff --git a/package.json b/package.json index 95f407249..b7b664f9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "github-tag-action", - "version": "6.0.0", + "version": "6.1.0", "private": true, "description": "A GitHub Action to automatically bump and tag master, on merge, with the latest SemVer formatted version.", "main": "lib/main.js", diff --git a/src/action.ts b/src/action.ts index b1dff7c24..059d8299e 100644 --- a/src/action.ts +++ b/src/action.ts @@ -21,6 +21,7 @@ export default async function main() { | ReleaseType | 'false'; const tagPrefix = core.getInput('tag_prefix'); + const prefixMatchTag = core.getInput('prefix_match_tag'); const customTag = core.getInput('custom_tag'); const releaseBranches = core.getInput('release_branches'); const preReleaseBranches = core.getInput('pre_release_branches'); @@ -69,7 +70,8 @@ export default async function main() { const validTags = await getValidTags( prefixRegex, - /true/i.test(shouldFetchAllTags) + /true/i.test(shouldFetchAllTags), + /true/i.test(prefixMatchTag) ); const latestTag = getLatestTag(validTags, prefixRegex, tagPrefix); const latestPrereleaseTag = getLatestPrereleaseTag( diff --git a/src/utils.ts b/src/utils.ts index 05b1247f3..97ed97aec 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -10,7 +10,8 @@ type Tags = Await>; export async function getValidTags( prefixRegex: RegExp, - shouldFetchAllTags: boolean + shouldFetchAllTags: boolean, + prefixMatchTag: boolean = false ) { const tags = await listTags(shouldFetchAllTags); @@ -20,8 +21,17 @@ export async function getValidTags( invalidTags.forEach((name) => core.debug(`Found Invalid Tag: ${name}.`)); + let prefixRegexMatchSemver: RegExp = RegExp( + prefixRegex.toString().slice(1, -1) + '[0-9]+', + 'g' + ); + const validTags = tags - .filter((tag) => valid(tag.name.replace(prefixRegex, ''))) + .filter( + (tag) => + valid(tag.name.replace(prefixRegex, '')) && + (!prefixMatchTag || tag.name.match(prefixRegexMatchSemver)) + ) .sort((a, b) => rcompare(a.name.replace(prefixRegex, ''), b.name.replace(prefixRegex, '')) ); diff --git a/tests/utils.test.ts b/tests/utils.test.ts index 417d8791e..14b413119 100644 --- a/tests/utils.test.ts +++ b/tests/utils.test.ts @@ -80,6 +80,96 @@ describe('utils', () => { expect(validTags).toHaveLength(1); }); + it('returns valid tags #2', async () => { + /* + * Given + */ + const testTags = [ + { + name: 'v1.0.0', + commit: { sha: 'string', url: 'string' }, + zipball_url: 'string', + tarball_url: 'string', + node_id: 'string', + }, + { + name: '0.0.91', + commit: { sha: 'string', url: 'string' }, + zipball_url: 'string', + tarball_url: 'string', + node_id: 'string', + }, + ]; + const mockListTags = jest + .spyOn(github, 'listTags') + .mockImplementation(async () => testTags); + + const regex_2 = /^/; + + /* + * When + */ + const validTags = await getValidTags(regex_2, false, true); + + /* + * Then + */ + expect(mockListTags).toHaveBeenCalled(); + expect(validTags).toHaveLength(1); + expect(validTags[0]).toEqual({ + name: '0.0.91', + commit: { sha: 'string', url: 'string' }, + zipball_url: 'string', + tarball_url: 'string', + node_id: 'string', + }); + }); + + it('returns valid tags #3', async () => { + /* + * Given + */ + const testTags = [ + { + name: 'v1.0.0', + commit: { sha: 'string', url: 'string' }, + zipball_url: 'string', + tarball_url: 'string', + node_id: 'string', + }, + { + name: '1.0.91', + commit: { sha: 'string', url: 'string' }, + zipball_url: 'string', + tarball_url: 'string', + node_id: 'string', + }, + ]; + const mockListTags = jest + .spyOn(github, 'listTags') + .mockImplementation(async () => testTags); + + const regex_2 = /^v/; + + /* + * When + */ + const validTags = await getValidTags(regex_2, false, true); + + /* + * Then + */ + expect(mockListTags).toHaveBeenCalled(); + expect(validTags).toHaveLength(1); + expect(validTags[0]).toEqual({ + name: 'v1.0.0', + commit: { sha: 'string', url: 'string' }, + zipball_url: 'string', + tarball_url: 'string', + node_id: 'string', + }); + }); + it('returns sorted tags', async () => { /* * Given