mirror of
https://github.com/actions/checkout.git
synced 2026-06-08 16:13:50 +08:00
Compare commits
1 Commits
v6
...
67bd696108
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67bd696108 |
@@ -1,9 +1,5 @@
|
||||
# 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
|
||||
* Fix tag handling: preserve annotations and explicit fetch-tags by @ericsciple in https://github.com/actions/checkout/pull/2356
|
||||
|
||||
|
||||
@@ -1103,6 +1103,7 @@ async function setup(testName: string): Promise<void> {
|
||||
),
|
||||
tryDisableAutomaticGarbageCollection: jest.fn(),
|
||||
tryGetFetchUrl: jest.fn(),
|
||||
tryGetObjectFormat: jest.fn(async () => ({format: '', succeeded: true})),
|
||||
tryGetConfigValues: jest.fn(
|
||||
async (
|
||||
key: string,
|
||||
|
||||
@@ -378,7 +378,7 @@ describe('Test fetchDepth and fetchTags options', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('repository initialization object format', () => {
|
||||
describe('repository object format', () => {
|
||||
beforeEach(async () => {
|
||||
jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn())
|
||||
jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn())
|
||||
@@ -388,6 +388,116 @@ describe('repository initialization object format', () => {
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
||||
it('detects SHA-256 from a 64-character HEAD oid', async () => {
|
||||
mockExec.mockImplementation((path, args, options) => {
|
||||
if (args.includes('version')) {
|
||||
options.listeners.stdout(Buffer.from('git version 2.50.1'))
|
||||
}
|
||||
|
||||
if (args.includes('ls-remote')) {
|
||||
options.listeners.stdout(
|
||||
Buffer.from(
|
||||
'ref: refs/heads/main\tHEAD\n' +
|
||||
'9422233ca7ee1b17f1e905d0e141faf0c401556c41cdc6acd71c6bd685da2e92\tHEAD\n'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return 0
|
||||
})
|
||||
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
|
||||
|
||||
git = await commandManager.createCommandManager('test', false, false)
|
||||
|
||||
const objectFormat = await git.tryGetObjectFormat(
|
||||
'https://github.com/example/repo'
|
||||
)
|
||||
|
||||
expect(objectFormat).toEqual({format: 'sha256', succeeded: true})
|
||||
expect(mockExec).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
[
|
||||
'-c',
|
||||
'protocol.version=2',
|
||||
'ls-remote',
|
||||
'--quiet',
|
||||
'--exit-code',
|
||||
'--symref',
|
||||
'https://github.com/example/repo',
|
||||
'HEAD'
|
||||
],
|
||||
expect.objectContaining({
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('detects SHA-1 from a 40-character HEAD oid', async () => {
|
||||
mockExec.mockImplementation((path, args, options) => {
|
||||
if (args.includes('version')) {
|
||||
options.listeners.stdout(Buffer.from('git version 2.50.1'))
|
||||
}
|
||||
|
||||
if (args.includes('ls-remote')) {
|
||||
options.listeners.stdout(
|
||||
Buffer.from(
|
||||
'ref: refs/heads/main\tHEAD\n' +
|
||||
'c988866043f035e6a46509872215f91d879044c9\tHEAD\n'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return 0
|
||||
})
|
||||
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
|
||||
|
||||
git = await commandManager.createCommandManager('test', false, false)
|
||||
|
||||
await expect(
|
||||
git.tryGetObjectFormat('https://github.com/example/repo')
|
||||
).resolves.toEqual({format: 'sha1', succeeded: true})
|
||||
})
|
||||
|
||||
it('returns unsuccessful when HEAD does not resolve to a recognized object id', async () => {
|
||||
mockExec.mockImplementation((path, args, options) => {
|
||||
if (args.includes('version')) {
|
||||
options.listeners.stdout(Buffer.from('git version 2.50.1'))
|
||||
}
|
||||
|
||||
if (args.includes('ls-remote')) {
|
||||
options.listeners.stdout(Buffer.from('ref: refs/heads/main\tHEAD\n'))
|
||||
}
|
||||
|
||||
return 0
|
||||
})
|
||||
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
|
||||
|
||||
git = await commandManager.createCommandManager('test', false, false)
|
||||
|
||||
await expect(
|
||||
git.tryGetObjectFormat('https://github.com/example/repo')
|
||||
).resolves.toEqual({format: '', succeeded: false})
|
||||
})
|
||||
|
||||
it('returns unsuccessful when object format detection cannot reach the remote', async () => {
|
||||
mockExec.mockImplementation((path, args, options) => {
|
||||
if (args.includes('version')) {
|
||||
options.listeners.stdout(Buffer.from('git version 2.50.1'))
|
||||
return 0
|
||||
}
|
||||
|
||||
return 128
|
||||
})
|
||||
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
|
||||
|
||||
git = await commandManager.createCommandManager('test', false, false)
|
||||
|
||||
await expect(
|
||||
git.tryGetObjectFormat('https://github.com/example/repo')
|
||||
).resolves.toEqual({format: '', succeeded: false})
|
||||
})
|
||||
|
||||
it('initializes SHA-256 repositories with the matching object format', async () => {
|
||||
mockExec.mockImplementation((path, args, options) => {
|
||||
if (args.includes('version')) {
|
||||
|
||||
@@ -501,6 +501,7 @@ async function setup(testName: string): Promise<void> {
|
||||
await fs.promises.stat(path.join(repositoryPath, '.git'))
|
||||
return repositoryUrl
|
||||
}),
|
||||
tryGetObjectFormat: jest.fn(async () => ({format: '', succeeded: true})),
|
||||
tryGetConfigValues: jest.fn(),
|
||||
tryGetConfigKeys: jest.fn(),
|
||||
tryReset: jest.fn(async () => {
|
||||
|
||||
@@ -5,16 +5,29 @@ 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
|
||||
let repoGet: jest.Mock
|
||||
let branchGet: jest.Mock
|
||||
|
||||
function mockHashAlgorithmApi(hashAlgorithm: string): void {
|
||||
request = jest.fn(async () => ({
|
||||
function mockObjectFormatApi(defaultBranch: string, commitSha: string): void {
|
||||
repoGet = jest.fn(async () => ({
|
||||
data: {
|
||||
hash_algorithm: hashAlgorithm
|
||||
default_branch: defaultBranch
|
||||
}
|
||||
}))
|
||||
branchGet = jest.fn(async () => ({
|
||||
data: {
|
||||
commit: {
|
||||
sha: commitSha
|
||||
}
|
||||
}
|
||||
}))
|
||||
getOctokitSpy = jest.spyOn(github, 'getOctokit').mockReturnValue({
|
||||
request
|
||||
rest: {
|
||||
repos: {
|
||||
get: repoGet,
|
||||
getBranch: branchGet
|
||||
}
|
||||
}
|
||||
} as any)
|
||||
}
|
||||
|
||||
@@ -26,29 +39,37 @@ describe('github-api-helper object format', () => {
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
||||
it('detects SHA-256 from the repository hash algorithm endpoint', async () => {
|
||||
mockHashAlgorithmApi('sha256')
|
||||
it('detects SHA-256 from the default branch commit SHA', async () => {
|
||||
const commitSha =
|
||||
'9422233ca7ee1b17f1e905d0e141faf0c401556c41cdc6acd71c6bd685da2e92'
|
||||
mockObjectFormatApi('main', commitSha)
|
||||
|
||||
await expect(
|
||||
githubApiHelper.tryGetRepositoryObjectFormat('token', 'owner', 'repo')
|
||||
).resolves.toEqual({format: 'sha256', succeeded: true})
|
||||
).resolves.toEqual({
|
||||
defaultBranch: 'main',
|
||||
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'}
|
||||
)
|
||||
expect(repoGet).toHaveBeenCalledWith({owner: 'owner', repo: 'repo'})
|
||||
expect(branchGet).toHaveBeenCalledWith({
|
||||
owner: 'owner',
|
||||
repo: 'repo',
|
||||
branch: 'main'
|
||||
})
|
||||
})
|
||||
|
||||
it('detects SHA-1 from the repository hash algorithm endpoint', async () => {
|
||||
mockHashAlgorithmApi('sha1')
|
||||
it('detects SHA-1 from the default branch commit SHA', async () => {
|
||||
mockObjectFormatApi('main', 'c988866043f035e6a46509872215f91d879044c9')
|
||||
|
||||
await expect(
|
||||
githubApiHelper.tryGetRepositoryObjectFormat('token', 'owner', 'repo')
|
||||
).resolves.toEqual({format: 'sha1', succeeded: true})
|
||||
).resolves.toEqual({defaultBranch: 'main', format: 'sha1', succeeded: true})
|
||||
})
|
||||
|
||||
it('detects object format from an existing commit without API calls', async () => {
|
||||
@@ -62,6 +83,7 @@ describe('github-api-helper object format', () => {
|
||||
'owner',
|
||||
'repo',
|
||||
undefined,
|
||||
undefined,
|
||||
commitSha
|
||||
)
|
||||
).resolves.toEqual({format: 'sha256', succeeded: true})
|
||||
@@ -69,30 +91,74 @@ describe('github-api-helper object format', () => {
|
||||
expect(getOctokitSpy).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('returns unsuccessful when the hash algorithm endpoint value is not recognized', async () => {
|
||||
mockHashAlgorithmApi('unknown')
|
||||
it('uses a branch ref directly without looking up the default branch', async () => {
|
||||
const commitSha = 'c988866043f035e6a46509872215f91d879044c9'
|
||||
repoGet = jest.fn()
|
||||
branchGet = jest.fn(async () => ({
|
||||
data: {
|
||||
commit: {
|
||||
sha: commitSha
|
||||
}
|
||||
}
|
||||
}))
|
||||
getOctokitSpy = jest.spyOn(github, 'getOctokit').mockReturnValue({
|
||||
rest: {
|
||||
repos: {
|
||||
get: repoGet,
|
||||
getBranch: branchGet
|
||||
}
|
||||
}
|
||||
} as any)
|
||||
|
||||
await expect(
|
||||
githubApiHelper.tryGetRepositoryObjectFormat(
|
||||
'token',
|
||||
'owner',
|
||||
'repo',
|
||||
undefined,
|
||||
'refs/heads/feature'
|
||||
)
|
||||
).resolves.toEqual({format: 'sha1', succeeded: true})
|
||||
|
||||
expect(repoGet).not.toHaveBeenCalled()
|
||||
expect(branchGet).toHaveBeenCalledWith({
|
||||
owner: 'owner',
|
||||
repo: 'repo',
|
||||
branch: 'feature'
|
||||
})
|
||||
})
|
||||
|
||||
it('returns unsuccessful when the default branch commit SHA is not recognized', async () => {
|
||||
mockObjectFormatApi('main', 'not-a-sha')
|
||||
|
||||
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'
|
||||
'Unable to determine repository object format from commit SHA'
|
||||
)
|
||||
})
|
||||
|
||||
it('returns unsuccessful when the hash algorithm API lookup fails', async () => {
|
||||
request = jest.fn(async () => {
|
||||
it('returns unsuccessful when the repository API lookup fails', async () => {
|
||||
repoGet = jest.fn(async () => {
|
||||
throw new Error('not found')
|
||||
})
|
||||
branchGet = jest.fn()
|
||||
jest.spyOn(github, 'getOctokit').mockReturnValue({
|
||||
request
|
||||
rest: {
|
||||
repos: {
|
||||
get: repoGet,
|
||||
getBranch: branchGet
|
||||
}
|
||||
}
|
||||
} as any)
|
||||
|
||||
await expect(
|
||||
githubApiHelper.tryGetRepositoryObjectFormat('token', 'owner', 'repo')
|
||||
).resolves.toEqual({format: '', succeeded: false})
|
||||
expect(branchGet).not.toHaveBeenCalled()
|
||||
expect(debugSpy).toHaveBeenCalledWith(
|
||||
'Unable to determine repository object format from hash-algorithm endpoint: not found'
|
||||
'Unable to determine repository object format: not found'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
101
dist/index.js
vendored
101
dist/index.js
vendored
@@ -1061,6 +1061,45 @@ class GitCommandManager {
|
||||
return stdout;
|
||||
});
|
||||
}
|
||||
tryGetObjectFormat(repositoryUrl) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
var _a;
|
||||
try {
|
||||
const output = yield this.execGit([
|
||||
'-c',
|
||||
'protocol.version=2',
|
||||
'ls-remote',
|
||||
'--quiet',
|
||||
'--exit-code',
|
||||
'--symref',
|
||||
repositoryUrl,
|
||||
'HEAD'
|
||||
], true, true);
|
||||
if (output.exitCode !== 0) {
|
||||
core.debug(`Unable to determine repository object format: git ls-remote exited with ${output.exitCode}`);
|
||||
return { format: '', succeeded: false };
|
||||
}
|
||||
for (const line of output.stdout.trim().split('\n')) {
|
||||
const [oid, ref] = line.split('\t');
|
||||
if (ref !== 'HEAD') {
|
||||
continue;
|
||||
}
|
||||
if (/^[0-9a-fA-F]{64}$/.test(oid)) {
|
||||
return { format: 'sha256', succeeded: true };
|
||||
}
|
||||
if (/^[0-9a-fA-F]{40}$/.test(oid)) {
|
||||
return { format: 'sha1', succeeded: true };
|
||||
}
|
||||
}
|
||||
core.debug('Unable to determine repository object format from HEAD');
|
||||
return { format: '', succeeded: false };
|
||||
}
|
||||
catch (err) {
|
||||
core.debug(`Unable to determine repository object format: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}`);
|
||||
return { format: '', succeeded: false };
|
||||
}
|
||||
});
|
||||
}
|
||||
tryGetConfigValues(configKey, globalConfig, configFile) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const args = ['config'];
|
||||
@@ -1489,13 +1528,18 @@ function getSource(settings) {
|
||||
}
|
||||
// Save state for POST action
|
||||
stateHelper.setRepositoryPath(settings.repositoryPath);
|
||||
let defaultBranch = '';
|
||||
// Initialize the repository
|
||||
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);
|
||||
let objectFormatResult = yield githubApiHelper.tryGetRepositoryObjectFormat(settings.authToken, settings.repositoryOwner, settings.repositoryName, settings.githubServerUrl, settings.ref, settings.commit);
|
||||
if (!objectFormatResult.succeeded) {
|
||||
objectFormatResult = yield git.tryGetObjectFormat(repositoryUrl);
|
||||
}
|
||||
const objectFormat = objectFormatResult.succeeded
|
||||
? objectFormatResult.format
|
||||
: '';
|
||||
defaultBranch = objectFormatResult.defaultBranch || '';
|
||||
if (objectFormat === 'sha256') {
|
||||
core.info('Detected SHA-256 repository object format');
|
||||
}
|
||||
@@ -1525,6 +1569,10 @@ function getSource(settings) {
|
||||
if (settings.sshKey) {
|
||||
settings.ref = yield git.getDefaultBranch(repositoryUrl);
|
||||
}
|
||||
else if (defaultBranch) {
|
||||
core.info(`Default branch '${defaultBranch}'`);
|
||||
settings.ref = `refs/heads/${defaultBranch}`;
|
||||
}
|
||||
else {
|
||||
settings.ref = yield githubApiHelper.getDefaultBranch(settings.authToken, settings.repositoryOwner, settings.repositoryName, settings.githubServerUrl);
|
||||
}
|
||||
@@ -1926,31 +1974,60 @@ function getDefaultBranch(authToken, owner, repo, baseUrl) {
|
||||
}));
|
||||
});
|
||||
}
|
||||
function tryGetRepositoryObjectFormat(authToken, owner, repo, baseUrl, commit) {
|
||||
function tryGetRepositoryObjectFormat(authToken, owner, repo, baseUrl, ref, commit) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
var _a;
|
||||
const commitFormat = getObjectFormat(commit);
|
||||
if (commitFormat) {
|
||||
return { format: commitFormat, succeeded: true };
|
||||
}
|
||||
try {
|
||||
const commitFormat = getObjectFormat(commit);
|
||||
if (commitFormat) {
|
||||
return { format: commitFormat, succeeded: true };
|
||||
}
|
||||
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 };
|
||||
let branchName = getBranchName(ref);
|
||||
let defaultBranch = '';
|
||||
if (!branchName) {
|
||||
const repository = yield octokit.rest.repos.get({ owner, repo });
|
||||
defaultBranch = repository.data.default_branch;
|
||||
assert.ok(defaultBranch, 'default_branch cannot be empty');
|
||||
branchName = defaultBranch;
|
||||
}
|
||||
core.debug('Unable to determine repository object format from hash-algorithm endpoint');
|
||||
const branch = yield octokit.rest.repos.getBranch({
|
||||
owner,
|
||||
repo,
|
||||
branch: branchName
|
||||
});
|
||||
const branchFormat = getObjectFormat(branch.data.commit.sha);
|
||||
if (branchFormat) {
|
||||
return {
|
||||
defaultBranch: defaultBranch || undefined,
|
||||
format: branchFormat,
|
||||
succeeded: true
|
||||
};
|
||||
}
|
||||
core.debug('Unable to determine repository object format from commit SHA');
|
||||
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}`);
|
||||
core.debug(`Unable to determine repository object format: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}`);
|
||||
return { format: '', succeeded: false };
|
||||
}
|
||||
});
|
||||
}
|
||||
function getBranchName(ref) {
|
||||
if (!ref) {
|
||||
return '';
|
||||
}
|
||||
const headsPrefix = 'refs/heads/';
|
||||
if (ref.startsWith(headsPrefix)) {
|
||||
return ref.substring(headsPrefix.length);
|
||||
}
|
||||
if (!ref.startsWith('refs/') && !getObjectFormat(ref)) {
|
||||
return ref;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
function getObjectFormat(sha) {
|
||||
if (/^[0-9a-fA-F]{64}$/.test(sha || '')) {
|
||||
return 'sha256';
|
||||
|
||||
@@ -15,6 +15,11 @@ import {GitVersion} from './git-version'
|
||||
export const MinimumGitVersion = new GitVersion('2.18')
|
||||
export const MinimumGitSparseCheckoutVersion = new GitVersion('2.28')
|
||||
|
||||
export interface GitObjectFormatResult {
|
||||
format: string
|
||||
succeeded: boolean
|
||||
}
|
||||
|
||||
export interface IGitCommandManager {
|
||||
branchDelete(remote: boolean, branch: string): Promise<void>
|
||||
branchExists(remote: boolean, pattern: string): Promise<boolean>
|
||||
@@ -68,6 +73,7 @@ export interface IGitCommandManager {
|
||||
): Promise<boolean>
|
||||
tryDisableAutomaticGarbageCollection(): Promise<boolean>
|
||||
tryGetFetchUrl(): Promise<string>
|
||||
tryGetObjectFormat(repositoryUrl: string): Promise<GitObjectFormatResult>
|
||||
tryGetConfigValues(
|
||||
configKey: string,
|
||||
globalConfig?: boolean,
|
||||
@@ -542,6 +548,55 @@ class GitCommandManager {
|
||||
return stdout
|
||||
}
|
||||
|
||||
async tryGetObjectFormat(
|
||||
repositoryUrl: string
|
||||
): Promise<GitObjectFormatResult> {
|
||||
try {
|
||||
const output = await this.execGit(
|
||||
[
|
||||
'-c',
|
||||
'protocol.version=2',
|
||||
'ls-remote',
|
||||
'--quiet',
|
||||
'--exit-code',
|
||||
'--symref',
|
||||
repositoryUrl,
|
||||
'HEAD'
|
||||
],
|
||||
true,
|
||||
true
|
||||
)
|
||||
|
||||
if (output.exitCode !== 0) {
|
||||
core.debug(
|
||||
`Unable to determine repository object format: git ls-remote exited with ${output.exitCode}`
|
||||
)
|
||||
return {format: '', succeeded: false}
|
||||
}
|
||||
|
||||
for (const line of output.stdout.trim().split('\n')) {
|
||||
const [oid, ref] = line.split('\t')
|
||||
if (ref !== 'HEAD') {
|
||||
continue
|
||||
}
|
||||
if (/^[0-9a-fA-F]{64}$/.test(oid)) {
|
||||
return {format: 'sha256', succeeded: true}
|
||||
}
|
||||
if (/^[0-9a-fA-F]{40}$/.test(oid)) {
|
||||
return {format: 'sha1', succeeded: true}
|
||||
}
|
||||
}
|
||||
|
||||
core.debug('Unable to determine repository object format from HEAD')
|
||||
return {format: '', succeeded: false}
|
||||
} catch (err) {
|
||||
core.debug(
|
||||
`Unable to determine repository object format: ${(err as any)?.message ?? err}`
|
||||
)
|
||||
return {format: '', succeeded: false}
|
||||
}
|
||||
}
|
||||
|
||||
async tryGetConfigValues(
|
||||
configKey: string,
|
||||
globalConfig?: boolean,
|
||||
|
||||
@@ -105,22 +105,29 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
||||
// Save state for POST action
|
||||
stateHelper.setRepositoryPath(settings.repositoryPath)
|
||||
|
||||
let defaultBranch = ''
|
||||
|
||||
// Initialize the repository
|
||||
if (
|
||||
!fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git'))
|
||||
) {
|
||||
core.startGroup('Determining repository object format')
|
||||
const objectFormatResult =
|
||||
let objectFormatResult =
|
||||
await githubApiHelper.tryGetRepositoryObjectFormat(
|
||||
settings.authToken,
|
||||
settings.repositoryOwner,
|
||||
settings.repositoryName,
|
||||
settings.githubServerUrl,
|
||||
settings.ref,
|
||||
settings.commit
|
||||
)
|
||||
if (!objectFormatResult.succeeded) {
|
||||
objectFormatResult = await git.tryGetObjectFormat(repositoryUrl)
|
||||
}
|
||||
const objectFormat = objectFormatResult.succeeded
|
||||
? objectFormatResult.format
|
||||
: ''
|
||||
defaultBranch = objectFormatResult.defaultBranch || ''
|
||||
if (objectFormat === 'sha256') {
|
||||
core.info('Detected SHA-256 repository object format')
|
||||
}
|
||||
@@ -155,6 +162,9 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
||||
core.startGroup('Determining the default branch')
|
||||
if (settings.sshKey) {
|
||||
settings.ref = await git.getDefaultBranch(repositoryUrl)
|
||||
} else if (defaultBranch) {
|
||||
core.info(`Default branch '${defaultBranch}'`)
|
||||
settings.ref = `refs/heads/${defaultBranch}`
|
||||
} else {
|
||||
settings.ref = await githubApiHelper.getDefaultBranch(
|
||||
settings.authToken,
|
||||
|
||||
@@ -12,6 +12,7 @@ import {getServerApiUrl} from './url-helper'
|
||||
const IS_WINDOWS = process.platform === 'win32'
|
||||
|
||||
export interface RepositoryObjectFormatResult {
|
||||
defaultBranch?: string
|
||||
format: string
|
||||
succeeded: boolean
|
||||
}
|
||||
@@ -132,38 +133,69 @@ export async function tryGetRepositoryObjectFormat(
|
||||
owner: string,
|
||||
repo: string,
|
||||
baseUrl?: string,
|
||||
ref?: string,
|
||||
commit?: string
|
||||
): Promise<RepositoryObjectFormatResult> {
|
||||
const commitFormat = getObjectFormat(commit)
|
||||
if (commitFormat) {
|
||||
return {format: commitFormat, succeeded: true}
|
||||
}
|
||||
|
||||
try {
|
||||
const commitFormat = getObjectFormat(commit)
|
||||
if (commitFormat) {
|
||||
return {format: commitFormat, succeeded: true}
|
||||
}
|
||||
|
||||
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}
|
||||
|
||||
let branchName = getBranchName(ref)
|
||||
let defaultBranch = ''
|
||||
if (!branchName) {
|
||||
const repository = await octokit.rest.repos.get({owner, repo})
|
||||
defaultBranch = repository.data.default_branch
|
||||
assert.ok(defaultBranch, 'default_branch cannot be empty')
|
||||
branchName = defaultBranch
|
||||
}
|
||||
|
||||
core.debug(
|
||||
'Unable to determine repository object format from hash-algorithm endpoint'
|
||||
)
|
||||
const branch = await octokit.rest.repos.getBranch({
|
||||
owner,
|
||||
repo,
|
||||
branch: branchName
|
||||
})
|
||||
const branchFormat = getObjectFormat(branch.data.commit.sha)
|
||||
if (branchFormat) {
|
||||
return {
|
||||
defaultBranch: defaultBranch || undefined,
|
||||
format: branchFormat,
|
||||
succeeded: true
|
||||
}
|
||||
}
|
||||
|
||||
core.debug('Unable to determine repository object format from commit SHA')
|
||||
return {format: '', succeeded: false}
|
||||
} catch (err) {
|
||||
core.debug(
|
||||
`Unable to determine repository object format from hash-algorithm endpoint: ${(err as any)?.message ?? err}`
|
||||
`Unable to determine repository object format: ${(err as any)?.message ?? err}`
|
||||
)
|
||||
return {format: '', succeeded: false}
|
||||
}
|
||||
}
|
||||
|
||||
function getBranchName(ref?: string): string {
|
||||
if (!ref) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const headsPrefix = 'refs/heads/'
|
||||
if (ref.startsWith(headsPrefix)) {
|
||||
return ref.substring(headsPrefix.length)
|
||||
}
|
||||
|
||||
if (!ref.startsWith('refs/') && !getObjectFormat(ref)) {
|
||||
return ref
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
function getObjectFormat(sha?: string): string {
|
||||
if (/^[0-9a-fA-F]{64}$/.test(sha || '')) {
|
||||
return 'sha256'
|
||||
|
||||
Reference in New Issue
Block a user