From 62f774ae3915b19760c4ade87823a22cdc6a46f9 Mon Sep 17 00:00:00 2001 From: Zydney Ambat Date: Thu, 25 Jun 2026 07:45:01 +1000 Subject: [PATCH 1/4] Add function to resolve ref to SHA --- src/git.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/git.ts b/src/git.ts index 9615f8b..3b7e2f5 100644 --- a/src/git.ts +++ b/src/git.ts @@ -198,6 +198,11 @@ export function isGitSha(ref: string): boolean { return /^[a-z0-9]{40}$/.test(ref) } +export async function resolveRefToSha(ref: string): Promise { + const output = (await getExecOutput('git', ['rev-parse', ref])).stdout.trim() + return output +} + async function hasCommit(ref: string): Promise { return (await getExecOutput('git', ['cat-file', '-e', `${ref}^{commit}`], {ignoreReturnCode: true})).exitCode === 0 } From cbd5f6aab9b25ce15505225038211eeff6533649 Mon Sep 17 00:00:00 2001 From: Zydney Ambat Date: Thu, 25 Jun 2026 07:47:14 +1000 Subject: [PATCH 2/4] Enhance base comparison with SHA resolution --- src/main.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 8adb308..3fe0a85 100644 --- a/src/main.ts +++ b/src/main.ts @@ -153,7 +153,9 @@ async function getChangedFilesFromGit(base: string, head: string, initialFetchDe } const isBaseSha = git.isGitSha(base) - const isBaseSameAsHead = base === head + const baseSha = await git.resolveRefToSha(base) + const headSha = await git.resolveRefToSha(head) + const isBaseSameAsHead = base === head || baseSha === headSha // If base is commit SHA we will do comparison against the referenced commit // Or if base references same branch it was pushed to, we will do comparison against the previously pushed commit From 2bbcf8a2987c3ffdf8848e923830b822887e90fe Mon Sep 17 00:00:00 2001 From: Zydney Ambat Date: Thu, 25 Jun 2026 07:57:24 +1000 Subject: [PATCH 3/4] Add tests for git reference resolution functions --- __tests__/git-resolve.test.ts | 95 +++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 __tests__/git-resolve.test.ts diff --git a/__tests__/git-resolve.test.ts b/__tests__/git-resolve.test.ts new file mode 100644 index 0000000..9f71dee --- /dev/null +++ b/__tests__/git-resolve.test.ts @@ -0,0 +1,95 @@ +import * as git from '../src/git' +import * as exec from '@actions/exec' + +jest.mock('@actions/exec') +const mockedGetExecOutput = jest.mocked(exec.getExecOutput) + +beforeEach(() => { + mockedGetExecOutput.mockReset() +}) + +describe('resolveRefToSha', () => { + test('resolves a branch name to its commit SHA', async () => { + mockedGetExecOutput.mockResolvedValue({ + exitCode: 0, + stdout: '8b399ed1681b9efd6b1e048ca1c5cba47edf3855\n', + stderr: '' + }) + const sha = await git.resolveRefToSha('master') + expect(sha).toBe('8b399ed1681b9efd6b1e048ca1c5cba47edf3855') + expect(mockedGetExecOutput).toHaveBeenCalledWith('git', ['rev-parse', 'master']) + }) + + test('resolves a tag to its commit SHA', async () => { + mockedGetExecOutput.mockResolvedValue({ + exitCode: 0, + stdout: '8b399ed1681b9efd6b1e048ca1c5cba47edf3855\n', + stderr: '' + }) + const sha = await git.resolveRefToSha('release-18') + expect(sha).toBe('8b399ed1681b9efd6b1e048ca1c5cba47edf3855') + expect(mockedGetExecOutput).toHaveBeenCalledWith('git', ['rev-parse', 'release-18']) + }) + + test('returns SHA as-is when given a full SHA', async () => { + const fullSha = '8b399ed1681b9efd6b1e048ca1c5cba47edf3855' + mockedGetExecOutput.mockResolvedValue({ + exitCode: 0, + stdout: `${fullSha}\n`, + stderr: '' + }) + const sha = await git.resolveRefToSha(fullSha) + expect(sha).toBe(fullSha) + }) +}) + +describe('isBaseSameAsHead with SHA comparison', () => { + test('different ref names pointing to same commit are treated as same', async () => { + const sameSha = '8b399ed1681b9efd6b1e048ca1c5cba47edf3855' + mockedGetExecOutput.mockResolvedValue({ + exitCode: 0, + stdout: `${sameSha}\n`, + stderr: '' + }) + + const base: string = 'master' + const head: string = 'release-18' + const baseSha = await git.resolveRefToSha(base) + const headSha = await git.resolveRefToSha(head) + const isBaseSameAsHead = base === head || baseSha === headSha + + expect(base === head).toBe(false) // ref names differ + expect(isBaseSameAsHead).toBe(true) // but SHAs match + }) + + test('different ref names pointing to different commits are not same', async () => { + mockedGetExecOutput + .mockResolvedValueOnce({ + exitCode: 0, + stdout: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n', + stderr: '' + }) + .mockResolvedValueOnce({ + exitCode: 0, + stdout: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n', + stderr: '' + }) + + const base: string = 'master' + const head: string = 'feature/xyz' + const baseSha = await git.resolveRefToSha(base) + const headSha = await git.resolveRefToSha(head) + const isBaseSameAsHead = base === head || baseSha === headSha + + expect(isBaseSameAsHead).toBe(false) + }) + + test('same ref names are detected without SHA resolution', async () => { + const base: string = 'master' + const head: string = 'master' + const isBaseSameAsHead = base === head + + expect(isBaseSameAsHead).toBe(true) + expect(mockedGetExecOutput).not.toHaveBeenCalled() + }) +}) From 9178dea8308e9ca736d9de4a14ded09e827a7cbb Mon Sep 17 00:00:00 2001 From: Zydney Ambat Date: Thu, 25 Jun 2026 08:17:05 +1000 Subject: [PATCH 4/4] rebuild dist/index.js with ncc --- dist/index.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 3365cd3..1f4643d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -204,7 +204,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.isGitSha = exports.getShortName = exports.getCurrentRef = exports.listAllFilesAsAdded = exports.parseGitDiffOutput = exports.getChangesSinceMergeBase = exports.getChangesOnHead = exports.getChanges = exports.getChangesInLastCommit = exports.HEAD = exports.NULL_SHA = void 0; +exports.resolveRefToSha = exports.isGitSha = exports.getShortName = exports.getCurrentRef = exports.listAllFilesAsAdded = exports.parseGitDiffOutput = exports.getChangesSinceMergeBase = exports.getChangesOnHead = exports.getChanges = exports.getChangesInLastCommit = exports.HEAD = exports.NULL_SHA = void 0; const exec_1 = __nccwpck_require__(1514); const core = __importStar(__nccwpck_require__(2186)); const file_1 = __nccwpck_require__(4014); @@ -394,6 +394,11 @@ function isGitSha(ref) { return /^[a-z0-9]{40}$/.test(ref); } exports.isGitSha = isGitSha; +async function resolveRefToSha(ref) { + const output = (await (0, exec_1.getExecOutput)('git', ['rev-parse', ref])).stdout.trim(); + return output; +} +exports.resolveRefToSha = resolveRefToSha; async function hasCommit(ref) { return (await (0, exec_1.getExecOutput)('git', ['cat-file', '-e', `${ref}^{commit}`], { ignoreReturnCode: true })).exitCode === 0; } @@ -675,7 +680,9 @@ async function getChangedFilesFromGit(base, head, initialFetchDepth) { throw new Error("This action requires 'base' input to be configured or 'repository.default_branch' to be set in the event payload"); } const isBaseSha = git.isGitSha(base); - const isBaseSameAsHead = base === head; + const baseSha = await git.resolveRefToSha(base); + const headSha = await git.resolveRefToSha(head); + const isBaseSameAsHead = base === head || baseSha === headSha; // If base is commit SHA we will do comparison against the referenced commit // Or if base references same branch it was pushed to, we will do comparison against the previously pushed commit if (isBaseSha || isBaseSameAsHead) {