From 03334d095e2739fa9ac4034ec16f66d5d01e9eba Mon Sep 17 00:00:00 2001 From: Tonye Jack Date: Thu, 23 May 2024 22:46:34 -0600 Subject: [PATCH] fix: bug detecting previous tag when workflow is rerun (#2107) Co-authored-by: GitHub Action --- dist/index.js | Bin 2347902 -> 2348864 bytes dist/index.js.map | Bin 2759994 -> 2761118 bytes src/__tests__/utils.test.ts | 158 +++++++----------------------------- src/commitSha.ts | 3 +- src/utils.ts | 75 +++++++++++------ 5 files changed, 83 insertions(+), 153 deletions(-) diff --git a/dist/index.js b/dist/index.js index 21bd141c94002d84df029d3de47cd864cd8f8170..c2194f805f18d72698d3e75ee36e1ea6f2293a8a 100644 GIT binary patch delta 1226 zcmZ9KPiPZS5XO16N&lJJv`N+2nyIaBf@x9_JVYxfQuQE4s-Q^G*W@+3lJ3Ucw^nRK z(SwR$krhWpQ4qWcQo+*JqSS*R2;x-`JbCFsJn2bsHrbTah2LZ6?VFwVeKUWbO|iun zQ*3(sjPvVNyYumLz}f#b;Ec4lUCqqQW@gyKxN!_++M*`?)m!xR}Vr7(3X zS+p%RM#Zgzwfpg%<*QsQui6;ID$<?<+A;u}`)oM;a_ zhaNX=t-32Fz7 zoF3v@fwrXqc_G1V5>R8SBC8epCReD&cMn(x{ygaO$hsxRRpS}5sL#c%9Ckx}HdDiMH&z8f3U6}e!E&8??Y{cYxU*nOo zQX2efYuva}`@b?PhXl54shG5Tu)$pfkBwpcc$Xo_>1VOvLeK1qiwK2&Dk6<+(9JfqLF?!@5srVw6sdi~Ca z=|F>*>tw!1@XI{w#_I=~0xdPE*TM^os3TSp^@NY`6AeTo(L^*8EyQXfK(rETh&Ccf nv=bdfhzJv%#9CqWzUT|`MR%@W~Rkn9!caa%GqJzi$Omoy+k|nW% zZF7?5@>EZyBJ8tAyq@@`HGXcrk;QJh#JBRV5dJsCxx8JLWJUO`@Hf-ymt>6)7tm{O zZgyvo2>W=CaxC2=VgBdt16fivdZGwtqFhyX%$`>Bz0^K?y(WHVma5vJT-DOddqFbX z(4_T4^v0HBLp>_u*kCTHDdKT#P(~57sv^;vnVB8FCP8sXKYj9D^$h|x7=cl+g9FB3 v9Gu_+4klm{+%N?m@WM2hS$>#-0L(%VLJ)>In1=`~KoltOu-NV!OS{2uso~H? diff --git a/dist/index.js.map b/dist/index.js.map index 12f2ca9954fd2a30c2e823b27bbde6c1ab85c006..94fdbe19c0890c3b97a9a5ad3bfa1dd7bb7f6cf9 100644 GIT binary patch delta 1371 zcmZvbO=ufe5XVt$?Xx9IaV$HLtlAzYk#=PyIsFW^>_B5{?ZX@rC z-M4nZ4h`wSmlWzAIwuzbIpowPf#NiWrln9qNufRWlAL>J0`0xCS_w-b3%})k%*=c9 zpLq`--U)s4%bn0&K8k-_?;YqZy*GavcSpneZnFs8m&qBwgm+=tiSQkZhq;a1haXHOz&JoS;%i~s0K zbZ6+ivOjd56x`wH*ze6r;;p-UsTxfOm{NHhUXd@-OGKy zGfCuESppx-E3sk@whnImD(7y&1_#&#UfE>I_!hXbW_xnxC50|{vf)Ymd5mdOhP|og zK`pq=f1#Z%H)-A#cLn)|I)XZ|IOe6+kH3G+0RMgxIT94{+S^KGs;$4+1b?V?S0*^O zC>?WM!xw)=lK80H7s2s!N&?G0!x2Lo0;=2LJr=en)F07lnA;I8{hOof2pe7`*8lnb<;5AZ&?uCEeP}12ei`=Z!y0k&3F7j&+ zlz%(z){!_+QARQS4jaPqSw+E{%Pc;z1yryZP)Q`$;Qj!vwHmT&TP{9dVpAzUmgY~T zZ%uk|u-E({-g+D!E?uHg(>>ojdWmGQ^cCvfmT}Q-)J>_W+iI>A+RxHl18ow^6;|wl z?QOhJVJBi;J%PK=)dYT+Nha{_<755!_S_2Bi)0;S+>v7EKB-Il^e^F~f8$5-yJVJO!Bk?b<&Ch+-o+mtDDh~AAHKdH zPT=YPlp{O0FEXN!=qDmXlo%jlM4UKG3=+QW5Ro8;i4o!`ag0b3DPojJ6R#0t#5gfQ a05M4%Cr%J2i42h?R6^UoeKGg-um1xUThIys delta 575 zcmZ|KOG_J36bEo7nmN%JH5y}^n0Uv=JZumuv=Hr-W+7M=DK$cfwm9M#Bk9CWCf&H` zqLl1PMabE;bY(WRg)Rba3w{AVh`3R7<$uNpZhGOzz1({q_k91?lnxJ@(jP6f_wuq+ zdiwW6=#8+CE_17u{pmWEKF8F0OqIX|ZO{(xR!o)WdieCWd$@iuFSicnDMNg=NF%)P zl{~zfqqv-~v|=L7KXMdoC^W>;C5pSsI?v{5>{)3;B=KH-tyz|C8Y!`}Vu+h%-wRdP z+xSMQjCVU!s4oQjkK7Ty$djLU*QlRomM9wjf4Jhr4r|h92kzKlDLA1i;P>!XP|=hY*4=3_%20+OxsLTdl$3Skb=8~^|S 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 ({