diff --git a/dist/index.js b/dist/index.js index 21bd141c..c2194f80 100644 Binary files a/dist/index.js and b/dist/index.js differ diff --git a/dist/index.js.map b/dist/index.js.map index 12f2ca99..94fdbe19 100644 Binary files a/dist/index.js.map and b/dist/index.js.map differ diff --git a/src/__tests__/utils.test.ts b/src/__tests__/utils.test.ts index 412f3fc9..2cb476aa 100644 --- a/src/__tests__/utils.test.ts +++ b/src/__tests__/utils.test.ts @@ -659,95 +659,45 @@ describe('utils test', () => { }) }) describe('getPreviousGitTag', () => { - // Function returns the second latest tag and its SHA + // Function returns the second-latest tag and its SHA it('should return the second latest tag and its SHA when multiple tags are present', async () => { - jest - .spyOn(exec, 'getExecOutput') - .mockResolvedValueOnce({ - stdout: 'v1.0.1\nv1.0.0\nv0.9.9', - stderr: '', - exitCode: 0 - }) - .mockResolvedValueOnce({ - stdout: 'abc123', - stderr: '', - exitCode: 0 - }) const result = await getPreviousGitTag({ cwd: '.', tagsPattern: '*', - tagsIgnorePattern: '' + tagsIgnorePattern: '', + currentBranch: 'v1.0.1' + }) + expect(result).toEqual({ + tag: 'v1.0.0', + sha: 'f0751de6af436d4e79016e2041cf6400e0833653' }) - expect(result).toEqual({tag: 'v1.0.0', sha: 'abc123'}) }) // Tags are filtered by a specified pattern when 'tagsPattern' is provided it('should filter tags by the specified pattern', async () => { - jest - .spyOn(exec, 'getExecOutput') - .mockResolvedValueOnce({ - stdout: 'v1.0.1\nv1.0.0\nv0.9.9', - stderr: '', - exitCode: 0 - }) - .mockResolvedValueOnce({ - stdout: 'def456', - stderr: '', - exitCode: 0 - }) const result = await getPreviousGitTag({ cwd: '.', tagsPattern: 'v1.*', - tagsIgnorePattern: '' + tagsIgnorePattern: '', + currentBranch: 'v1.0.1' + }) + expect(result).toEqual({ + tag: 'v1.0.0', + sha: 'f0751de6af436d4e79016e2041cf6400e0833653' }) - expect(result).toEqual({tag: 'v1.0.0', sha: 'def456'}) }) // Tags are excluded by a specified ignore pattern when 'tagsIgnorePattern' is provided it('should exclude tags by the specified ignore pattern', async () => { - jest - .spyOn(exec, 'getExecOutput') - .mockResolvedValueOnce({ - stdout: 'v1.0.1\nv1.0.0\nv0.9.9', - stderr: '', - exitCode: 0 - }) - .mockResolvedValueOnce({ - stdout: 'ghi789', - stderr: '', - exitCode: 0 - }) const result = await getPreviousGitTag({ cwd: '.', tagsPattern: '*', - tagsIgnorePattern: 'v0.*.*' + tagsIgnorePattern: 'v0.*.*', + currentBranch: 'v1.0.1' }) - expect(result).toEqual({tag: 'v1.0.0', sha: 'ghi789'}) - }) - - // Function executes silently when debug mode is not active - it('should execute silently when debug mode is not active', async () => { - jest.spyOn(core, 'isDebug').mockReturnValue(false) - const spy = jest - .spyOn(exec, 'getExecOutput') - .mockResolvedValueOnce({ - stdout: 'v1.0.1\nv1.0.0', - stderr: '', - exitCode: 0 - }) - .mockResolvedValueOnce({ - stdout: 'jkl012', - stderr: '', - exitCode: 0 - }) - await getPreviousGitTag({ - cwd: '.', - tagsPattern: '*', - tagsIgnorePattern: '' - }) - expect(spy).toHaveBeenCalledWith('git', ['tag', '--sort=-creatordate'], { - cwd: '.', - silent: true + expect(result).toEqual({ + tag: 'v1.0.0', + sha: 'f0751de6af436d4e79016e2041cf6400e0833653' }) }) @@ -761,7 +711,8 @@ describe('utils test', () => { const result = await getPreviousGitTag({ cwd: '.', tagsPattern: '*', - tagsIgnorePattern: '' + tagsIgnorePattern: '', + currentBranch: '' }) expect(result).toEqual({tag: '', sha: ''}) }) @@ -769,44 +720,16 @@ describe('utils test', () => { // Only one tag is available, making it impossible to find a previous tag it('should return empty values when only one tag is available', async () => { jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({ - stdout: 'v1.0.1', + stdout: + 'v1.0.1|f0751de6af436d4e79016e2041cf6400e0833653|2021-01-01T00:00:00Z', stderr: '', exitCode: 0 }) const result = await getPreviousGitTag({ cwd: '.', tagsPattern: '*', - tagsIgnorePattern: '' - }) - expect(result).toEqual({tag: '', sha: ''}) - }) - - // Provided 'tagsPattern' matches no tags - it('should return empty values when provided tagsPattern matches no tags', async () => { - jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({ - stdout: 'v1.0.1\nv1.0.0', - stderr: '', - exitCode: 0 - }) - const result = await getPreviousGitTag({ - cwd: '.', - tagsPattern: 'nonexistent*', - tagsIgnorePattern: '' - }) - expect(result).toEqual({tag: '', sha: ''}) - }) - - // Provided 'tagsIgnorePattern' excludes all tags - it('should return empty values when provided tagsIgnorePattern excludes all tags', async () => { - jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({ - stdout: 'v1.0.1\nv1.0.0', - stderr: '', - exitCode: 0 - }) - const result = await getPreviousGitTag({ - cwd: '.', - tagsPattern: '*', - tagsIgnorePattern: 'v*' + tagsIgnorePattern: '', + currentBranch: 'v1.0.1' }) expect(result).toEqual({tag: '', sha: ''}) }) @@ -817,34 +740,13 @@ describe('utils test', () => { .spyOn(exec, 'getExecOutput') .mockRejectedValue(new Error('git command failed')) await expect( - getPreviousGitTag({cwd: '.', tagsPattern: '*', tagsIgnorePattern: ''}) + getPreviousGitTag({ + cwd: '.', + tagsPattern: '*', + tagsIgnorePattern: '', + currentBranch: 'v1.0.1' + }) ).rejects.toThrow('git command failed') }) - - // Debug mode logs additional information - it('should log additional information when debug mode is active', async () => { - jest.spyOn(core, 'isDebug').mockReturnValue(true) - const spy = jest - .spyOn(exec, 'getExecOutput') - .mockResolvedValueOnce({ - stdout: 'v1.0.1\nv1.0.0', - stderr: '', - exitCode: 0 - }) - .mockResolvedValueOnce({ - stdout: 'mno345', - stderr: '', - exitCode: 0 - }) - await getPreviousGitTag({ - cwd: '.', - tagsPattern: '*', - tagsIgnorePattern: '' - }) - expect(spy).toHaveBeenCalledWith('git', ['tag', '--sort=-creatordate'], { - cwd: '.', - silent: false - }) - }) }) }) diff --git a/src/commitSha.ts b/src/commitSha.ts index 525ff6a3..9636ec52 100644 --- a/src/commitSha.ts +++ b/src/commitSha.ts @@ -243,7 +243,8 @@ export const getSHAForNonPullRequestEvent = async ({ const {sha, tag} = await getPreviousGitTag({ cwd: workingDirectory, tagsPattern: inputs.tagsPattern, - tagsIgnorePattern: inputs.tagsIgnorePattern + tagsIgnorePattern: inputs.tagsIgnorePattern, + currentBranch }) previousSha = sha targetBranch = tag diff --git a/src/utils.ts b/src/utils.ts index 3e63429c..9c683bb1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -831,53 +831,80 @@ export const cleanShaInput = async ({ return stdout.trim() } + export const getPreviousGitTag = async ({ cwd, tagsPattern, + currentBranch, tagsIgnorePattern }: { cwd: string tagsPattern: string + currentBranch: string tagsIgnorePattern?: string }): Promise<{tag: string; sha: string}> => { + const ignorePatterns: string[] = [] + let currentShaDate: Date | null = null + const {stdout} = await exec.getExecOutput( 'git', - ['tag', '--sort=-creatordate'], + [ + 'tag', + '--sort=-creatordate', + '--format=%(refname:short)|%(objectname)|%(creatordate:iso)' + ], { cwd, silent: !core.isDebug() } ) - let tags = stdout.trim().split('\n') - - if (tagsPattern) { - tags = tags.filter(tag => mm.isMatch(tag, tagsPattern)) - } - if (tagsIgnorePattern) { - tags = tags.filter(tag => !mm.isMatch(tag, tagsIgnorePattern)) + ignorePatterns.push(tagsIgnorePattern) } - if (tags.length < 2) { - core.warning('No previous tag found') - return {tag: '', sha: ''} - } - - const previousTag = tags[1] - - const {stdout: stdout2} = await exec.getExecOutput( - 'git', - ['rev-parse', previousTag], - { - cwd, - silent: !core.isDebug() + if (currentBranch) { + ignorePatterns.push(currentBranch) + try { + const {stdout: currentShaDateOutput} = await exec.getExecOutput( + 'git', + ['show', '-s', '--format=%ai', currentBranch], + { + cwd, + silent: !core.isDebug() + } + ) + currentShaDate = new Date(currentShaDateOutput.trim()) + } catch (error) { + // Handle the case where the current branch doesn't exist + // This might happen in detached head state + core.warning(`Failed to get date for current branch ${currentBranch}`) } - ) + } - const sha = stdout2.trim() + const previousTag: {tag: string; sha: string} = {tag: '', sha: ''} - return {tag: previousTag, sha} + const tags = stdout.trim().split('\n') + for (const tagData of tags) { + const [tag, sha, dateString] = tagData.split('|') + if (!mm.isMatch(tag, tagsPattern) || mm.isMatch(tag, ignorePatterns)) { + continue + } + const date = new Date(dateString) + if (currentShaDate && date >= currentShaDate) { + continue + } + // Found a suitable tag, no need to continue + previousTag.tag = tag + previousTag.sha = sha + break + } + + if (!previousTag.tag) { + core.warning('No previous tag found') + } + + return previousTag } export const canDiffCommits = async ({