Compare commits

...

6 Commits

Author SHA1 Message Date
rizwangourysk 35ad319155
Merge e94b1128e6 into df4cb1c069 2026-06-08 22:46:32 +01:00
Yashwanth Anantharaju df4cb1c069
Update changelog for v6.0.3 (#2446) 2026-06-02 10:31:30 -04:00
Yashwanth Anantharaju 1cce3390c2
Fix checkout init for SHA-256 repositories (#2439)
* Fix checkout init for SHA-256 repositories

* Remove unused object format result field
2026-06-01 11:35:58 -04:00
Rizwan e94b1128e6 added some changes 2026-03-26 15:58:20 +05:30
rizwangourysk 7a020261fa added workflow 2026-03-26 15:45:27 +05:30
rizwangourysk bd5c14db95 added changes 2026-03-26 14:56:46 +05:30
9 changed files with 310 additions and 7 deletions

View File

@ -1,5 +1,9 @@
# Changelog # Changelog
## v6.0.3
* Fix checkout init for SHA-256 repositories by @yaananth in https://github.com/actions/checkout/pull/2439
* fix: expand merge commit SHA regex and add SHA-256 test cases by @yaananth in https://github.com/actions/checkout/pull/2414
## v6.0.2 ## v6.0.2
* Fix tag handling: preserve annotations and explicit fetch-tags by @ericsciple in https://github.com/actions/checkout/pull/2356 * Fix tag handling: preserve annotations and explicit fetch-tags by @ericsciple in https://github.com/actions/checkout/pull/2356

View File

@ -28,6 +28,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
### Note ### Note
Thank you for your interest in this GitHub action, however, right now we are not taking contributions. Thank you for your interest in this GitHub action, however, right now we are not taking contributions.
We continue to focus our resources on strategic areas that help our customers be successful while making developers' lives easier. While GitHub Actions remains a key part of this vision, we are allocating resources towards other areas of Actions and are not taking contributions to this repository at this time. The GitHub public roadmap is the best place to follow along for any updates on features we’re working on and what stage they’re in. We continue to focus our resources on strategic areas that help our customers be successful while making developers' lives easier. While GitHub Actions remains a key part of this vision, we are allocating resources towards other areas of Actions and are not taking contributions to this repository at this time. The GitHub public roadmap is the best place to follow along for any updates on features we’re working on and what stage they’re in.

View File

@ -378,6 +378,59 @@ describe('Test fetchDepth and fetchTags options', () => {
}) })
}) })
describe('repository initialization object format', () => {
beforeEach(async () => {
jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn())
jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn())
})
afterEach(() => {
jest.restoreAllMocks()
})
it('initializes SHA-256 repositories with the matching object format', async () => {
mockExec.mockImplementation((path, args, options) => {
if (args.includes('version')) {
options.listeners.stdout(Buffer.from('git version 2.50.1'))
}
return 0
})
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
git = await commandManager.createCommandManager('test', false, false)
await git.init('sha256')
expect(mockExec).toHaveBeenCalledWith(
expect.any(String),
['init', '--object-format=sha256', 'test'],
expect.any(Object)
)
})
it('initializes SHA-1 repositories with existing default arguments', async () => {
mockExec.mockImplementation((path, args, options) => {
if (args.includes('version')) {
options.listeners.stdout(Buffer.from('git version 2.50.1'))
}
return 0
})
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
git = await commandManager.createCommandManager('test', false, false)
await git.init('sha1')
expect(mockExec).toHaveBeenCalledWith(
expect.any(String),
['init', 'test'],
expect.any(Object)
)
})
})
describe('git user-agent with orchestration ID', () => { describe('git user-agent with orchestration ID', () => {
beforeEach(async () => { beforeEach(async () => {
jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn()) jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn())

View File

@ -0,0 +1,98 @@
import * as core from '@actions/core'
import * as github from '@actions/github'
import * as githubApiHelper from '../lib/github-api-helper'
describe('github-api-helper object format', () => {
let getOctokitSpy: jest.SpyInstance
let debugSpy: jest.SpyInstance
let request: jest.Mock
function mockHashAlgorithmApi(hashAlgorithm: string): void {
request = jest.fn(async () => ({
data: {
hash_algorithm: hashAlgorithm
}
}))
getOctokitSpy = jest.spyOn(github, 'getOctokit').mockReturnValue({
request
} as any)
}
beforeEach(() => {
debugSpy = jest.spyOn(core, 'debug').mockImplementation(jest.fn())
})
afterEach(() => {
jest.restoreAllMocks()
})
it('detects SHA-256 from the repository hash algorithm endpoint', async () => {
mockHashAlgorithmApi('sha256')
await expect(
githubApiHelper.tryGetRepositoryObjectFormat('token', 'owner', 'repo')
).resolves.toEqual({format: 'sha256', succeeded: true})
expect(getOctokitSpy).toHaveBeenCalledWith(
'token',
expect.objectContaining({baseUrl: 'https://api.github.com'})
)
expect(request).toHaveBeenCalledWith(
'GET /repos/{owner}/{repo}/hash-algorithm',
{owner: 'owner', repo: 'repo'}
)
})
it('detects SHA-1 from the repository hash algorithm endpoint', async () => {
mockHashAlgorithmApi('sha1')
await expect(
githubApiHelper.tryGetRepositoryObjectFormat('token', 'owner', 'repo')
).resolves.toEqual({format: 'sha1', succeeded: true})
})
it('detects object format from an existing commit without API calls', async () => {
const commitSha =
'9422233ca7ee1b17f1e905d0e141faf0c401556c41cdc6acd71c6bd685da2e92'
getOctokitSpy = jest.spyOn(github, 'getOctokit')
await expect(
githubApiHelper.tryGetRepositoryObjectFormat(
'token',
'owner',
'repo',
undefined,
commitSha
)
).resolves.toEqual({format: 'sha256', succeeded: true})
expect(getOctokitSpy).not.toHaveBeenCalled()
})
it('returns unsuccessful when the hash algorithm endpoint value is not recognized', async () => {
mockHashAlgorithmApi('unknown')
await expect(
githubApiHelper.tryGetRepositoryObjectFormat('token', 'owner', 'repo')
).resolves.toEqual({format: '', succeeded: false})
expect(debugSpy).toHaveBeenCalledWith(
'Unable to determine repository object format from hash-algorithm endpoint'
)
})
it('returns unsuccessful when the hash algorithm API lookup fails', async () => {
request = jest.fn(async () => {
throw new Error('not found')
})
jest.spyOn(github, 'getOctokit').mockReturnValue({
request
} as any)
await expect(
githubApiHelper.tryGetRepositoryObjectFormat('token', 'owner', 'repo')
).resolves.toEqual({format: '', succeeded: false})
expect(debugSpy).toHaveBeenCalledWith(
'Unable to determine repository object format from hash-algorithm endpoint: not found'
)
})
})

55
dist/index.js vendored
View File

@ -896,9 +896,14 @@ class GitCommandManager {
getWorkingDirectory() { getWorkingDirectory() {
return this.workingDirectory; return this.workingDirectory;
} }
init() { init(objectFormat) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
yield this.execGit(['init', this.workingDirectory]); const args = ['init'];
if (objectFormat === 'sha256') {
args.push('--object-format=sha256');
}
args.push(this.workingDirectory);
yield this.execGit(args);
}); });
} }
isDetached() { isDetached() {
@ -1486,8 +1491,17 @@ function getSource(settings) {
stateHelper.setRepositoryPath(settings.repositoryPath); stateHelper.setRepositoryPath(settings.repositoryPath);
// Initialize the repository // Initialize the repository
if (!fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git'))) { if (!fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git'))) {
core.startGroup('Determining repository object format');
const objectFormatResult = yield githubApiHelper.tryGetRepositoryObjectFormat(settings.authToken, settings.repositoryOwner, settings.repositoryName, settings.githubServerUrl, settings.commit);
const objectFormat = objectFormatResult.succeeded
? objectFormatResult.format
: '';
if (objectFormat === 'sha256') {
core.info('Detected SHA-256 repository object format');
}
core.endGroup();
core.startGroup('Initializing the repository'); core.startGroup('Initializing the repository');
yield git.init(); yield git.init(objectFormat);
yield git.remoteAdd('origin', repositoryUrl); yield git.remoteAdd('origin', repositoryUrl);
core.endGroup(); core.endGroup();
} }
@ -1810,6 +1824,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.downloadRepository = downloadRepository; exports.downloadRepository = downloadRepository;
exports.getDefaultBranch = getDefaultBranch; exports.getDefaultBranch = getDefaultBranch;
exports.tryGetRepositoryObjectFormat = tryGetRepositoryObjectFormat;
const assert = __importStar(__nccwpck_require__(9491)); const assert = __importStar(__nccwpck_require__(9491));
const core = __importStar(__nccwpck_require__(2186)); const core = __importStar(__nccwpck_require__(2186));
const fs = __importStar(__nccwpck_require__(7147)); const fs = __importStar(__nccwpck_require__(7147));
@ -1911,6 +1926,40 @@ function getDefaultBranch(authToken, owner, repo, baseUrl) {
})); }));
}); });
} }
function tryGetRepositoryObjectFormat(authToken, owner, repo, baseUrl, commit) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
const commitFormat = getObjectFormat(commit);
if (commitFormat) {
return { format: commitFormat, succeeded: true };
}
try {
const octokit = github.getOctokit(authToken, {
baseUrl: (0, url_helper_1.getServerApiUrl)(baseUrl)
});
const response = yield octokit.request('GET /repos/{owner}/{repo}/hash-algorithm', { owner, repo });
const hashAlgorithm = response.data.hash_algorithm;
if (hashAlgorithm === 'sha256' || hashAlgorithm === 'sha1') {
return { format: hashAlgorithm, succeeded: true };
}
core.debug('Unable to determine repository object format from hash-algorithm endpoint');
return { format: '', succeeded: false };
}
catch (err) {
core.debug(`Unable to determine repository object format from hash-algorithm endpoint: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}`);
return { format: '', succeeded: false };
}
});
}
function getObjectFormat(sha) {
if (/^[0-9a-fA-F]{64}$/.test(sha || '')) {
return 'sha256';
}
if (/^[0-9a-fA-F]{40}$/.test(sha || '')) {
return 'sha1';
}
return '';
}
function downloadArchive(authToken, owner, repo, ref, commit, baseUrl) { function downloadArchive(authToken, owner, repo, ref, commit, baseUrl) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const octokit = github.getOctokit(authToken, { const octokit = github.getOctokit(authToken, {

23
pr.yaml Normal file
View File

@ -0,0 +1,23 @@
---
# This workflow will execute on pull request to dev branch
name: pr-workflow
on:
pull_request:
branches:
- dev
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: get the code
uses: actions/checkout@v6
- name: compile the code
run: mvn compile
- name: test the code
run: mvn test
- name: create the package
run: mvn package

View File

@ -43,7 +43,7 @@ export interface IGitCommandManager {
getDefaultBranch(repositoryUrl: string): Promise<string> getDefaultBranch(repositoryUrl: string): Promise<string>
getSubmoduleConfigPaths(recursive: boolean): Promise<string[]> getSubmoduleConfigPaths(recursive: boolean): Promise<string[]>
getWorkingDirectory(): string getWorkingDirectory(): string
init(): Promise<void> init(objectFormat?: string): Promise<void>
isDetached(): Promise<boolean> isDetached(): Promise<boolean>
lfsFetch(ref: string): Promise<void> lfsFetch(ref: string): Promise<void>
lfsInstall(): Promise<void> lfsInstall(): Promise<void>
@ -364,8 +364,14 @@ class GitCommandManager {
return this.workingDirectory return this.workingDirectory
} }
async init(): Promise<void> { async init(objectFormat?: string): Promise<void> {
await this.execGit(['init', this.workingDirectory]) const args = ['init']
if (objectFormat === 'sha256') {
args.push('--object-format=sha256')
}
args.push(this.workingDirectory)
await this.execGit(args)
} }
async isDetached(): Promise<boolean> { async isDetached(): Promise<boolean> {

View File

@ -109,8 +109,25 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
if ( if (
!fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git')) !fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git'))
) { ) {
core.startGroup('Determining repository object format')
const objectFormatResult =
await githubApiHelper.tryGetRepositoryObjectFormat(
settings.authToken,
settings.repositoryOwner,
settings.repositoryName,
settings.githubServerUrl,
settings.commit
)
const objectFormat = objectFormatResult.succeeded
? objectFormatResult.format
: ''
if (objectFormat === 'sha256') {
core.info('Detected SHA-256 repository object format')
}
core.endGroup()
core.startGroup('Initializing the repository') core.startGroup('Initializing the repository')
await git.init() await git.init(objectFormat)
await git.remoteAdd('origin', repositoryUrl) await git.remoteAdd('origin', repositoryUrl)
core.endGroup() core.endGroup()
} }

View File

@ -11,6 +11,11 @@ import {getServerApiUrl} from './url-helper'
const IS_WINDOWS = process.platform === 'win32' const IS_WINDOWS = process.platform === 'win32'
export interface RepositoryObjectFormatResult {
format: string
succeeded: boolean
}
export async function downloadRepository( export async function downloadRepository(
authToken: string, authToken: string,
owner: string, owner: string,
@ -122,6 +127,53 @@ export async function getDefaultBranch(
}) })
} }
export async function tryGetRepositoryObjectFormat(
authToken: string,
owner: string,
repo: string,
baseUrl?: string,
commit?: string
): Promise<RepositoryObjectFormatResult> {
const commitFormat = getObjectFormat(commit)
if (commitFormat) {
return {format: commitFormat, succeeded: true}
}
try {
const octokit = github.getOctokit(authToken, {
baseUrl: getServerApiUrl(baseUrl)
})
const response = await octokit.request(
'GET /repos/{owner}/{repo}/hash-algorithm',
{owner, repo}
)
const hashAlgorithm = response.data.hash_algorithm
if (hashAlgorithm === 'sha256' || hashAlgorithm === 'sha1') {
return {format: hashAlgorithm, succeeded: true}
}
core.debug(
'Unable to determine repository object format from hash-algorithm endpoint'
)
return {format: '', succeeded: false}
} catch (err) {
core.debug(
`Unable to determine repository object format from hash-algorithm endpoint: ${(err as any)?.message ?? err}`
)
return {format: '', succeeded: false}
}
}
function getObjectFormat(sha?: string): string {
if (/^[0-9a-fA-F]{64}$/.test(sha || '')) {
return 'sha256'
}
if (/^[0-9a-fA-F]{40}$/.test(sha || '')) {
return 'sha1'
}
return ''
}
async function downloadArchive( async function downloadArchive(
authToken: string, authToken: string,
owner: string, owner: string,