diff --git a/README.md b/README.md index 64dc02581..b654dceea 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,11 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/ # running from unless specified. Example URLs are https://github.com or # https://my-ghes-server.example.com github-server-url: '' + + # Use the given object format when creating local repository. Specifically, use + # 'sha256' to checkout a SHA-256 repository. + # Default: null + object-format: '' ``` <!-- end usage --> @@ -144,6 +149,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/ - [Checkout pull request on closed event](#Checkout-pull-request-on-closed-event) - [Push a commit using the built-in token](#Push-a-commit-using-the-built-in-token) - [Push a commit to a PR using the built-in token](#Push-a-commit-to-a-PR-using-the-built-in-token) +- [Checkout SHA-256 repository](#checkout-sha-256-repository) ## Fetch only the root files @@ -323,6 +329,14 @@ permissions: contents: read ``` +## Checkout SHA-256 repository + +```yaml +- uses: actions/checkout@v4 + with: + object-format: sha256 +``` + # License The scripts and documentation in this project are released under the [MIT License](LICENSE) diff --git a/__test__/git-auth-helper.test.ts b/__test__/git-auth-helper.test.ts index 7633704cc..26f0330a9 100644 --- a/__test__/git-auth-helper.test.ts +++ b/__test__/git-auth-helper.test.ts @@ -824,7 +824,8 @@ async function setup(testName: string): Promise<void> { sshUser: '', workflowOrganizationId: 123456, setSafeDirectory: true, - githubServerUrl: githubServerUrl + githubServerUrl: githubServerUrl, + objectFormat: undefined } } diff --git a/__test__/git-command-manager.test.ts b/__test__/git-command-manager.test.ts index cea73d4dd..aaf65f8f0 100644 --- a/__test__/git-command-manager.test.ts +++ b/__test__/git-command-manager.test.ts @@ -375,4 +375,25 @@ describe('Test fetchDepth and fetchTags options', () => { expect.any(Object) ) }) + + it('should call execGit with the correct arguments when sha256 is used', async () => { + jest.spyOn(exec, 'exec').mockImplementation(mockExec) + + const workingDirectory = 'test' + const lfs = false + const doSparseCheckout = false + git = await commandManager.createCommandManager( + workingDirectory, + lfs, + doSparseCheckout + ) + + await git.init({objectFormat: 'sha256'}) + + expect(mockExec).toHaveBeenCalledWith( + expect.any(String), + ['init', '--object-format=sha256', 'test'], + expect.any(Object) + ) + }) }) diff --git a/action.yml b/action.yml index 6842eb843..0aa8f94c0 100644 --- a/action.yml +++ b/action.yml @@ -98,6 +98,11 @@ inputs: github-server-url: description: The base URL for the GitHub instance that you are trying to clone from, will use environment defaults to fetch from the same instance that the workflow is running from unless specified. Example URLs are https://github.com or https://my-ghes-server.example.com required: false + object-format: + description: > + Use the given object format when creating local repository. Specifically, use + 'sha256' to checkout a SHA-256 repository. + default: null outputs: ref: description: 'The branch, tag or SHA that was checked out' diff --git a/dist/index.js b/dist/index.js index b0db71380..31bde7b46 100644 --- a/dist/index.js +++ b/dist/index.js @@ -709,9 +709,13 @@ class GitCommandManager { getWorkingDirectory() { return this.workingDirectory; } - init() { + init(options) { return __awaiter(this, void 0, void 0, function* () { - yield this.execGit(['init', this.workingDirectory]); + yield this.execGit([ + 'init', + ...((options === null || options === void 0 ? void 0 : options.objectFormat) ? [`--object-format=${options.objectFormat}`] : []), + this.workingDirectory + ]); }); } isDetached() { @@ -1236,7 +1240,7 @@ function getSource(settings) { // Initialize the repository if (!fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git'))) { core.startGroup('Initializing the repository'); - yield git.init(); + yield git.init({ objectFormat: settings.objectFormat }); yield git.remoteAdd('origin', repositoryUrl); core.endGroup(); } @@ -1831,6 +1835,14 @@ function getInputs() { // Determine the GitHub URL that the repository is being hosted from result.githubServerUrl = core.getInput('github-server-url'); core.debug(`GitHub Host URL = ${result.githubServerUrl}`); + // Object format + const objectFormat = core.getInput('object-format'); + if (objectFormat) { + if (objectFormat != 'sha1' && objectFormat != 'sha256') { + throw Error(`Invalid object format '${objectFormat}'`); + } + result.objectFormat = objectFormat; + } return result; }); } diff --git a/src/git-command-manager.ts b/src/git-command-manager.ts index 8e42a387f..976bc2444 100644 --- a/src/git-command-manager.ts +++ b/src/git-command-manager.ts @@ -42,7 +42,7 @@ export interface IGitCommandManager { ): Promise<void> getDefaultBranch(repositoryUrl: string): Promise<string> getWorkingDirectory(): string - init(): Promise<void> + init(options?: {objectFormat?: string}): Promise<void> isDetached(): Promise<boolean> lfsFetch(ref: string): Promise<void> lfsInstall(): Promise<void> @@ -327,8 +327,14 @@ class GitCommandManager { return this.workingDirectory } - async init(): Promise<void> { - await this.execGit(['init', this.workingDirectory]) + async init(options?: {objectFormat?: string}): Promise<void> { + await this.execGit([ + 'init', + ...(options?.objectFormat + ? [`--object-format=${options.objectFormat}`] + : []), + this.workingDirectory + ]) } async isDetached(): Promise<boolean> { diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts index 2d3513897..d84d4559c 100644 --- a/src/git-source-provider.ts +++ b/src/git-source-provider.ts @@ -110,7 +110,7 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> { !fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git')) ) { core.startGroup('Initializing the repository') - await git.init() + await git.init({objectFormat: settings.objectFormat}) await git.remoteAdd('origin', repositoryUrl) core.endGroup() } diff --git a/src/git-source-settings.ts b/src/git-source-settings.ts index 4e41ac302..f6434e8ea 100644 --- a/src/git-source-settings.ts +++ b/src/git-source-settings.ts @@ -118,4 +118,9 @@ export interface IGitSourceSettings { * User override on the GitHub Server/Host URL that hosts the repository to be cloned */ githubServerUrl: string | undefined + + /** + * Object format used for the repo, if it is not default + */ + objectFormat: 'sha1' | 'sha256' | undefined } diff --git a/src/input-helper.ts b/src/input-helper.ts index 059232f5c..bb5657f50 100644 --- a/src/input-helper.ts +++ b/src/input-helper.ts @@ -161,5 +161,14 @@ export async function getInputs(): Promise<IGitSourceSettings> { result.githubServerUrl = core.getInput('github-server-url') core.debug(`GitHub Host URL = ${result.githubServerUrl}`) + // Object format + const objectFormat = core.getInput('object-format') + if (objectFormat) { + if (objectFormat != 'sha1' && objectFormat != 'sha256') { + throw Error(`Invalid object format '${objectFormat}'`) + } + result.objectFormat = objectFormat + } + return result }