From 4d90d5f46cfa65d2c7416d57c1ff19d9f7efeddc Mon Sep 17 00:00:00 2001 From: Yashwanth Anantharaju Date: Tue, 14 Apr 2026 23:44:44 +0000 Subject: [PATCH 1/3] fix: expand merge commit SHA regex and add SHA-256 test cases Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- __test__/input-helper.test.ts | 9 +++++++++ __test__/ref-helper.test.ts | 8 ++++++++ dist/index.js | 4 ++-- src/input-helper.ts | 2 +- src/ref-helper.ts | 2 +- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/__test__/input-helper.test.ts b/__test__/input-helper.test.ts index 9514cb4..e0f711b 100644 --- a/__test__/input-helper.test.ts +++ b/__test__/input-helper.test.ts @@ -133,6 +133,15 @@ describe('input-helper tests', () => { expect(settings.commit).toBe('1111111111222222222233333333334444444444') }) + it('sets ref to empty when explicit sha-256', async () => { + inputs.ref = '1111111111222222222233333333334444444444555555555566666666667777' + const settings: IGitSourceSettings = await inputHelper.getInputs() + expect(settings.ref).toBeFalsy() + expect(settings.commit).toBe( + '1111111111222222222233333333334444444444555555555566666666667777' + ) + }) + it('sets sha to empty when explicit ref', async () => { inputs.ref = 'refs/heads/some-other-ref' const settings: IGitSourceSettings = await inputHelper.getInputs() diff --git a/__test__/ref-helper.test.ts b/__test__/ref-helper.test.ts index 4943abd..e4837f5 100644 --- a/__test__/ref-helper.test.ts +++ b/__test__/ref-helper.test.ts @@ -3,6 +3,8 @@ import * as refHelper from '../lib/ref-helper' import {IGitCommandManager} from '../lib/git-command-manager' const commit = '1234567890123456789012345678901234567890' +const sha256Commit = + '1234567890123456789012345678901234567890123456789012345678901234' let git: IGitCommandManager describe('ref-helper tests', () => { @@ -37,6 +39,12 @@ describe('ref-helper tests', () => { expect(checkoutInfo.startPoint).toBeFalsy() }) + it('getCheckoutInfo sha-256 only', async () => { + const checkoutInfo = await refHelper.getCheckoutInfo(git, '', sha256Commit) + expect(checkoutInfo.ref).toBe(sha256Commit) + expect(checkoutInfo.startPoint).toBeFalsy() + }) + it('getCheckoutInfo refs/heads/', async () => { const checkoutInfo = await refHelper.getCheckoutInfo( git, diff --git a/dist/index.js b/dist/index.js index fe3f317..57729b2 100644 --- a/dist/index.js +++ b/dist/index.js @@ -2021,7 +2021,7 @@ function getInputs() { } } // SHA? - else if (result.ref.match(/^[0-9a-fA-F]{40}$/)) { + else if (result.ref.match(/^(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})$/)) { result.commit = result.ref; result.ref = ''; } @@ -2444,7 +2444,7 @@ function checkCommitInfo(token, commitInfo, repositoryOwner, repositoryName, ref return; } // Extract details from message - const match = commitInfo.match(/Merge ([0-9a-f]{40}) into ([0-9a-f]{40})/); + const match = commitInfo.match(/Merge ([0-9a-f]{40}|[0-9a-f]{64}) into ([0-9a-f]{40}|[0-9a-f]{64})/); if (!match) { core.debug('Unexpected message format'); return; diff --git a/src/input-helper.ts b/src/input-helper.ts index 059232f..e0c61e2 100644 --- a/src/input-helper.ts +++ b/src/input-helper.ts @@ -71,7 +71,7 @@ export async function getInputs(): Promise { } } // SHA? - else if (result.ref.match(/^[0-9a-fA-F]{40}$/)) { + else if (result.ref.match(/^(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})$/)) { result.commit = result.ref result.ref = '' } diff --git a/src/ref-helper.ts b/src/ref-helper.ts index 5130f53..05362bd 100644 --- a/src/ref-helper.ts +++ b/src/ref-helper.ts @@ -258,7 +258,7 @@ export async function checkCommitInfo( } // Extract details from message - const match = commitInfo.match(/Merge ([0-9a-f]{40}) into ([0-9a-f]{40})/) + const match = commitInfo.match(/Merge ([0-9a-f]{40}|[0-9a-f]{64}) into ([0-9a-f]{40}|[0-9a-f]{64})/) if (!match) { core.debug('Unexpected message format') return From 4f1e7288c071659b08ec066ffe7b526a96f646bc Mon Sep 17 00:00:00 2001 From: Yashwanth Anantharaju Date: Thu, 16 Apr 2026 15:27:51 +0000 Subject: [PATCH 2/3] test: add checkCommitInfo SHA coverage Add checkCommitInfo tests for SHA-1 and SHA-256 merge messages and reject invalid 50-character hex merge heads.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- __test__/ref-helper.test.ts | 140 ++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/__test__/ref-helper.test.ts b/__test__/ref-helper.test.ts index e4837f5..b1578f2 100644 --- a/__test__/ref-helper.test.ts +++ b/__test__/ref-helper.test.ts @@ -1,4 +1,6 @@ import * as assert from 'assert' +import * as core from '@actions/core' +import * as github from '@actions/github' import * as refHelper from '../lib/ref-helper' import {IGitCommandManager} from '../lib/git-command-manager' @@ -235,4 +237,142 @@ describe('ref-helper tests', () => { '+refs/heads/my/branch:refs/remotes/origin/my/branch' ) }) + + describe('checkCommitInfo', () => { + const repositoryOwner = 'some-owner' + const repositoryName = 'some-repo' + const ref = 'refs/pull/123/merge' + const sha1Head = '1111111111222222222233333333334444444444' + const sha1Base = 'aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd' + const sha256Head = + '1111111111222222222233333333334444444444555555555566666666667777' + const sha256Base = + 'aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff0000' + let debugSpy: jest.SpyInstance + let getOctokitSpy: jest.SpyInstance + let repoGetSpy: jest.Mock + let originalEventName: string + let originalPayload: unknown + let originalRef: string + let originalSha: string + + function setPullRequestContext( + expectedHeadSha: string, + expectedBaseSha: string, + mergeCommit: string + ): void { + ;(github.context as any).eventName = 'pull_request' + github.context.ref = ref + github.context.sha = mergeCommit + ;(github.context as any).payload = { + action: 'synchronize', + after: expectedHeadSha, + number: 123, + pull_request: { + base: { + sha: expectedBaseSha + } + }, + repository: { + private: false + } + } + } + + beforeEach(() => { + originalEventName = github.context.eventName + originalPayload = github.context.payload + originalRef = github.context.ref + originalSha = github.context.sha + + jest.spyOn(github.context, 'repo', 'get').mockReturnValue({ + owner: repositoryOwner, + repo: repositoryName + }) + debugSpy = jest.spyOn(core, 'debug').mockImplementation(jest.fn()) + repoGetSpy = jest.fn(async () => ({})) + getOctokitSpy = jest.spyOn(github, 'getOctokit').mockReturnValue({ + rest: { + repos: { + get: repoGetSpy + } + } + } as any) + }) + + afterEach(() => { + ;(github.context as any).eventName = originalEventName + ;(github.context as any).payload = originalPayload + github.context.ref = originalRef + github.context.sha = originalSha + jest.restoreAllMocks() + }) + + it('returns early for SHA-1 merge commit', async () => { + setPullRequestContext(sha1Head, sha1Base, commit) + + await refHelper.checkCommitInfo( + 'token', + `Merge ${sha1Head} into ${sha1Base}`, + repositoryOwner, + repositoryName, + ref, + commit + ) + + expect(getOctokitSpy).not.toHaveBeenCalled() + expect(repoGetSpy).not.toHaveBeenCalled() + }) + + it('matches SHA-256 merge commit info', async () => { + const actualHeadSha = + '9999999999888888888877777777776666666666555555555544444444443333' + setPullRequestContext(sha256Head, sha256Base, sha256Commit) + + await refHelper.checkCommitInfo( + 'token', + `Merge ${actualHeadSha} into ${sha256Base}`, + repositoryOwner, + repositoryName, + ref, + sha256Commit + ) + + expect(getOctokitSpy).toHaveBeenCalledWith( + 'token', + expect.objectContaining({ + userAgent: expect.stringContaining( + `expected_head_sha=${sha256Head};actual_head_sha=${actualHeadSha}` + ) + }) + ) + expect(repoGetSpy).toHaveBeenCalledWith({ + owner: repositoryOwner, + repo: repositoryName + }) + expect(debugSpy).toHaveBeenCalledWith( + `Expected head sha ${sha256Head}; actual head sha ${actualHeadSha}` + ) + expect(debugSpy).not.toHaveBeenCalledWith('Unexpected message format') + }) + + it('does not match 50-char hex as a valid merge', async () => { + const invalidHeadSha = + '99999999998888888888777777777766666666665555555555' + setPullRequestContext(sha1Head, sha1Base, commit) + + await refHelper.checkCommitInfo( + 'token', + `Merge ${invalidHeadSha} into ${sha1Base}`, + repositoryOwner, + repositoryName, + ref, + commit + ) + + expect(getOctokitSpy).not.toHaveBeenCalled() + expect(repoGetSpy).not.toHaveBeenCalled() + expect(debugSpy).toHaveBeenCalledWith('Unexpected message format') + }) + }) }) From 71f7057fab274d6d2bd87f9525dce0cdc9fe895e Mon Sep 17 00:00:00 2001 From: Yashwanth Anantharaju Date: Thu, 16 Apr 2026 16:11:13 +0000 Subject: [PATCH 3/3] style: fix Prettier formatting in test and source files Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- __test__/input-helper.test.ts | 3 ++- src/ref-helper.ts | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/__test__/input-helper.test.ts b/__test__/input-helper.test.ts index e0f711b..09331eb 100644 --- a/__test__/input-helper.test.ts +++ b/__test__/input-helper.test.ts @@ -134,7 +134,8 @@ describe('input-helper tests', () => { }) it('sets ref to empty when explicit sha-256', async () => { - inputs.ref = '1111111111222222222233333333334444444444555555555566666666667777' + inputs.ref = + '1111111111222222222233333333334444444444555555555566666666667777' const settings: IGitSourceSettings = await inputHelper.getInputs() expect(settings.ref).toBeFalsy() expect(settings.commit).toBe( diff --git a/src/ref-helper.ts b/src/ref-helper.ts index 05362bd..71e8b22 100644 --- a/src/ref-helper.ts +++ b/src/ref-helper.ts @@ -258,7 +258,9 @@ export async function checkCommitInfo( } // Extract details from message - const match = commitInfo.match(/Merge ([0-9a-f]{40}|[0-9a-f]{64}) into ([0-9a-f]{40}|[0-9a-f]{64})/) + const match = commitInfo.match( + /Merge ([0-9a-f]{40}|[0-9a-f]{64}) into ([0-9a-f]{40}|[0-9a-f]{64})/ + ) if (!match) { core.debug('Unexpected message format') return