Skip to content

Commit 03c1842

Browse files
feat: add support for providing patterns to match tags (#2098)
Co-authored-by: GitHub Action <[email protected]>
1 parent 5f01393 commit 03c1842

File tree

9 files changed

+277
-10
lines changed

9 files changed

+277
-10
lines changed

action.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,15 @@ inputs:
235235
description: "Use POSIX path separator `/` for output file paths on Windows."
236236
required: false
237237
default: "false"
238+
tags_pattern:
239+
description: "Tags pattern to include."
240+
required: false
241+
default: "*"
242+
tags_ignore_pattern:
243+
description: "Tags pattern to ignore."
244+
required: false
245+
default: ""
246+
238247

239248
outputs:
240249
added_files:

dist/index.js

Lines changed: 26 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/__tests__/__snapshots__/inputs.test.ts.snap

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ exports[`getInputs should correctly parse boolean inputs 1`] = `
5353
"since": "",
5454
"sinceLastRemoteCommit": "false",
5555
"skipInitialFetch": "true",
56+
"tagsIgnorePattern": "",
57+
"tagsPattern": "*",
5658
"token": "",
5759
"until": "",
5860
"usePosixPathSeparator": "false",
@@ -113,6 +115,8 @@ exports[`getInputs should correctly parse numeric inputs 1`] = `
113115
"since": "",
114116
"sinceLastRemoteCommit": false,
115117
"skipInitialFetch": false,
118+
"tagsIgnorePattern": "",
119+
"tagsPattern": "",
116120
"token": "",
117121
"until": "",
118122
"usePosixPathSeparator": false,
@@ -171,6 +175,8 @@ exports[`getInputs should correctly parse string inputs 1`] = `
171175
"since": "",
172176
"sinceLastRemoteCommit": false,
173177
"skipInitialFetch": false,
178+
"tagsIgnorePattern": "",
179+
"tagsPattern": "",
174180
"token": "token",
175181
"until": "",
176182
"usePosixPathSeparator": false,
@@ -231,6 +237,8 @@ exports[`getInputs should handle invalid numeric inputs correctly 1`] = `
231237
"since": "",
232238
"sinceLastRemoteCommit": false,
233239
"skipInitialFetch": false,
240+
"tagsIgnorePattern": "",
241+
"tagsPattern": "",
234242
"token": "",
235243
"until": "",
236244
"usePosixPathSeparator": false,
@@ -291,6 +299,8 @@ exports[`getInputs should handle negative numeric inputs correctly 1`] = `
291299
"since": "",
292300
"sinceLastRemoteCommit": false,
293301
"skipInitialFetch": false,
302+
"tagsIgnorePattern": "",
303+
"tagsPattern": "",
294304
"token": "",
295305
"until": "",
296306
"usePosixPathSeparator": false,
@@ -352,6 +362,8 @@ exports[`getInputs should return default values when no inputs are provided 1`]
352362
"since": "",
353363
"sinceLastRemoteCommit": false,
354364
"skipInitialFetch": false,
365+
"tagsIgnorePattern": "",
366+
"tagsPattern": "*",
355367
"token": "",
356368
"until": "",
357369
"usePosixPathSeparator": false,

src/__tests__/utils.test.ts

Lines changed: 194 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import * as core from '@actions/core'
2+
import * as exec from '@actions/exec'
23
import {ChangeTypeEnum} from '../changedFiles'
34
import {Inputs} from '../inputs'
45
import {
56
getDirname,
67
getDirnameMaxDepth,
78
getFilteredChangedFiles,
9+
getPreviousGitTag,
810
normalizeSeparators,
911
warnUnsupportedRESTAPIInputs
1012
} from '../utils'
@@ -638,7 +640,9 @@ describe('utils test', () => {
638640
useRestApi: false,
639641
excludeSubmodules: false,
640642
fetchMissingHistoryMaxRetries: 10,
641-
usePosixPathSeparator: false
643+
usePosixPathSeparator: false,
644+
tagsPattern: '*',
645+
tagsIgnorePattern: ''
642646
}
643647

644648
const coreWarningSpy = jest.spyOn(core, 'warning')
@@ -654,4 +658,193 @@ describe('utils test', () => {
654658
expect(coreWarningSpy).toHaveBeenCalledTimes(1)
655659
})
656660
})
661+
describe('getPreviousGitTag', () => {
662+
// Function returns the second latest tag and its SHA
663+
it('should return the second latest tag and its SHA when multiple tags are present', async () => {
664+
jest
665+
.spyOn(exec, 'getExecOutput')
666+
.mockResolvedValueOnce({
667+
stdout: 'v1.0.1\nv1.0.0\nv0.9.9',
668+
stderr: '',
669+
exitCode: 0
670+
})
671+
.mockResolvedValueOnce({
672+
stdout: 'abc123',
673+
stderr: '',
674+
exitCode: 0
675+
})
676+
const result = await getPreviousGitTag({
677+
cwd: '.',
678+
tagsPattern: '*',
679+
tagsIgnorePattern: ''
680+
})
681+
expect(result).toEqual({tag: 'v1.0.0', sha: 'abc123'})
682+
})
683+
684+
// Tags are filtered by a specified pattern when 'tagsPattern' is provided
685+
it('should filter tags by the specified pattern', async () => {
686+
jest
687+
.spyOn(exec, 'getExecOutput')
688+
.mockResolvedValueOnce({
689+
stdout: 'v1.0.1\nv1.0.0\nv0.9.9',
690+
stderr: '',
691+
exitCode: 0
692+
})
693+
.mockResolvedValueOnce({
694+
stdout: 'def456',
695+
stderr: '',
696+
exitCode: 0
697+
})
698+
const result = await getPreviousGitTag({
699+
cwd: '.',
700+
tagsPattern: 'v1.*',
701+
tagsIgnorePattern: ''
702+
})
703+
expect(result).toEqual({tag: 'v1.0.0', sha: 'def456'})
704+
})
705+
706+
// Tags are excluded by a specified ignore pattern when 'tagsIgnorePattern' is provided
707+
it('should exclude tags by the specified ignore pattern', async () => {
708+
jest
709+
.spyOn(exec, 'getExecOutput')
710+
.mockResolvedValueOnce({
711+
stdout: 'v1.0.1\nv1.0.0\nv0.9.9',
712+
stderr: '',
713+
exitCode: 0
714+
})
715+
.mockResolvedValueOnce({
716+
stdout: 'ghi789',
717+
stderr: '',
718+
exitCode: 0
719+
})
720+
const result = await getPreviousGitTag({
721+
cwd: '.',
722+
tagsPattern: '*',
723+
tagsIgnorePattern: 'v0.*.*'
724+
})
725+
expect(result).toEqual({tag: 'v1.0.0', sha: 'ghi789'})
726+
})
727+
728+
// Function executes silently when debug mode is not active
729+
it('should execute silently when debug mode is not active', async () => {
730+
jest.spyOn(core, 'isDebug').mockReturnValue(false)
731+
const spy = jest
732+
.spyOn(exec, 'getExecOutput')
733+
.mockResolvedValueOnce({
734+
stdout: 'v1.0.1\nv1.0.0',
735+
stderr: '',
736+
exitCode: 0
737+
})
738+
.mockResolvedValueOnce({
739+
stdout: 'jkl012',
740+
stderr: '',
741+
exitCode: 0
742+
})
743+
await getPreviousGitTag({
744+
cwd: '.',
745+
tagsPattern: '*',
746+
tagsIgnorePattern: ''
747+
})
748+
expect(spy).toHaveBeenCalledWith('git', ['tag', '--sort=-creatordate'], {
749+
cwd: '.',
750+
silent: true
751+
})
752+
})
753+
754+
// No tags are available in the repository
755+
it('should return empty values when no tags are available in the repository', async () => {
756+
jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({
757+
stdout: '',
758+
stderr: '',
759+
exitCode: 0
760+
})
761+
const result = await getPreviousGitTag({
762+
cwd: '.',
763+
tagsPattern: '*',
764+
tagsIgnorePattern: ''
765+
})
766+
expect(result).toEqual({tag: '', sha: ''})
767+
})
768+
769+
// Only one tag is available, making it impossible to find a previous tag
770+
it('should return empty values when only one tag is available', async () => {
771+
jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({
772+
stdout: 'v1.0.1',
773+
stderr: '',
774+
exitCode: 0
775+
})
776+
const result = await getPreviousGitTag({
777+
cwd: '.',
778+
tagsPattern: '*',
779+
tagsIgnorePattern: ''
780+
})
781+
expect(result).toEqual({tag: '', sha: ''})
782+
})
783+
784+
// Provided 'tagsPattern' matches no tags
785+
it('should return empty values when provided tagsPattern matches no tags', async () => {
786+
jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({
787+
stdout: 'v1.0.1\nv1.0.0',
788+
stderr: '',
789+
exitCode: 0
790+
})
791+
const result = await getPreviousGitTag({
792+
cwd: '.',
793+
tagsPattern: 'nonexistent*',
794+
tagsIgnorePattern: ''
795+
})
796+
expect(result).toEqual({tag: '', sha: ''})
797+
})
798+
799+
// Provided 'tagsIgnorePattern' excludes all tags
800+
it('should return empty values when provided tagsIgnorePattern excludes all tags', async () => {
801+
jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({
802+
stdout: 'v1.0.1\nv1.0.0',
803+
stderr: '',
804+
exitCode: 0
805+
})
806+
const result = await getPreviousGitTag({
807+
cwd: '.',
808+
tagsPattern: '*',
809+
tagsIgnorePattern: 'v*'
810+
})
811+
expect(result).toEqual({tag: '', sha: ''})
812+
})
813+
814+
// Git commands fail and throw errors
815+
it('should throw an error when git commands fail', async () => {
816+
jest
817+
.spyOn(exec, 'getExecOutput')
818+
.mockRejectedValue(new Error('git command failed'))
819+
await expect(
820+
getPreviousGitTag({cwd: '.', tagsPattern: '*', tagsIgnorePattern: ''})
821+
).rejects.toThrow('git command failed')
822+
})
823+
824+
// Debug mode logs additional information
825+
it('should log additional information when debug mode is active', async () => {
826+
jest.spyOn(core, 'isDebug').mockReturnValue(true)
827+
const spy = jest
828+
.spyOn(exec, 'getExecOutput')
829+
.mockResolvedValueOnce({
830+
stdout: 'v1.0.1\nv1.0.0',
831+
stderr: '',
832+
exitCode: 0
833+
})
834+
.mockResolvedValueOnce({
835+
stdout: 'mno345',
836+
stderr: '',
837+
exitCode: 0
838+
})
839+
await getPreviousGitTag({
840+
cwd: '.',
841+
tagsPattern: '*',
842+
tagsIgnorePattern: ''
843+
})
844+
expect(spy).toHaveBeenCalledWith('git', ['tag', '--sort=-creatordate'], {
845+
cwd: '.',
846+
silent: false
847+
})
848+
})
849+
})
657850
})

src/commitSha.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,11 @@ export const getSHAForNonPullRequestEvent = async ({
240240
}
241241
} else if (isTag) {
242242
core.debug('Getting previous SHA for tag...')
243-
const {sha, tag} = await getPreviousGitTag({cwd: workingDirectory})
243+
const {sha, tag} = await getPreviousGitTag({
244+
cwd: workingDirectory,
245+
tagsPattern: inputs.tagsPattern,
246+
tagsIgnorePattern: inputs.tagsIgnorePattern
247+
})
244248
previousSha = sha
245249
targetBranch = tag
246250
} else {

src/constant.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,7 @@ export const DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS: Partial<Inputs> = {
2323
dirNamesDeletedFilesIncludeOnlyDeletedDirs: false,
2424
excludeSubmodules: false,
2525
fetchMissingHistoryMaxRetries: 10,
26-
usePosixPathSeparator: false
26+
usePosixPathSeparator: false,
27+
tagsPattern: '*',
28+
tagsIgnorePattern: ''
2729
}

0 commit comments

Comments
 (0)