From 68a03db89927bb75b55c815d96b14d78e1846aa1 Mon Sep 17 00:00:00 2001 From: Yang Zhao Date: Fri, 23 Aug 2024 00:23:06 -0700 Subject: [PATCH] Add objectFormat setting to allow init()ing a repo with sha256 --- README.md | 14 +++++ __test__/git-auth-helper.test.ts | 3 +- __test__/git-command-manager.test.ts | 27 +++++++++ dist/index.js | 89 +++++++++++++++++----------- src/git-command-manager.ts | 10 +++- src/git-source-provider.ts | 2 +- src/git-source-settings.ts | 5 ++ src/input-helper.ts | 9 +++ 8 files changed, 120 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index e1ea03298..ec27a3365 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. + # Defualt: null + object-format: '' ``` @@ -143,6 +148,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/ - [Checkout pull request HEAD commit instead of merge commit](#Checkout-pull-request-HEAD-commit-instead-of-merge-commit) - [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) +- [Checkout SHA-256 repository](#checkout-sha-256-repository) ## Fetch only the root files @@ -288,6 +294,14 @@ jobs: ``` *NOTE:* The user email is `{user.id}+{user.login}@users.noreply.github.com`. See users API: https://api.github.com/users/github-actions%5Bbot%5D +## 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 { 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..d85ef0da7 100644 --- a/__test__/git-command-manager.test.ts +++ b/__test__/git-command-manager.test.ts @@ -375,4 +375,31 @@ describe('Test fetchDepth and fetchTags options', () => { expect.any(Object) ) }) + + it('should call execGit wiwth 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'}) + // await git.init({objectFormat: undefined}) + + expect(mockExec).toHaveBeenCalledWith( + expect.any(String), + [ + 'init', + '--object-format=sha256', + 'test' + ], + expect.any(Object) + ) + }) }) + diff --git a/dist/index.js b/dist/index.js index d86415e06..dc07d40e6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -30,9 +30,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.directoryExistsSync = directoryExistsSync; -exports.existsSync = existsSync; -exports.fileExistsSync = fileExistsSync; +exports.fileExistsSync = exports.existsSync = exports.directoryExistsSync = void 0; const fs = __importStar(__nccwpck_require__(7147)); function directoryExistsSync(path, required) { var _a; @@ -60,6 +58,7 @@ function directoryExistsSync(path, required) { } throw new Error(`Directory '${path}' does not exist`); } +exports.directoryExistsSync = directoryExistsSync; function existsSync(path) { var _a; if (!path) { @@ -76,6 +75,7 @@ function existsSync(path) { } return true; } +exports.existsSync = existsSync; function fileExistsSync(path) { var _a; if (!path) { @@ -96,6 +96,7 @@ function fileExistsSync(path) { } return false; } +exports.fileExistsSync = fileExistsSync; /***/ }), @@ -138,7 +139,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.createAuthHelper = createAuthHelper; +exports.createAuthHelper = void 0; const assert = __importStar(__nccwpck_require__(9491)); const core = __importStar(__nccwpck_require__(2186)); const exec = __importStar(__nccwpck_require__(1514)); @@ -155,6 +156,7 @@ const SSH_COMMAND_KEY = 'core.sshCommand'; function createAuthHelper(git, settings) { return new GitAuthHelper(git, settings); } +exports.createAuthHelper = createAuthHelper; class GitAuthHelper { constructor(gitCommandManager, gitSourceSettings) { this.insteadOfValues = []; @@ -473,8 +475,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.MinimumGitSparseCheckoutVersion = exports.MinimumGitVersion = void 0; -exports.createCommandManager = createCommandManager; +exports.createCommandManager = exports.MinimumGitSparseCheckoutVersion = exports.MinimumGitVersion = void 0; const core = __importStar(__nccwpck_require__(2186)); const exec = __importStar(__nccwpck_require__(1514)); const fs = __importStar(__nccwpck_require__(7147)); @@ -495,6 +496,7 @@ function createCommandManager(workingDirectory, lfs, doSparseCheckout) { return yield GitCommandManager.createCommandManager(workingDirectory, lfs, doSparseCheckout); }); } +exports.createCommandManager = createCommandManager; class GitCommandManager { // Private constructor; use createCommandManager() constructor() { @@ -709,9 +711,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() { @@ -1018,7 +1024,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.prepareExistingDirectory = prepareExistingDirectory; +exports.prepareExistingDirectory = void 0; const assert = __importStar(__nccwpck_require__(9491)); const core = __importStar(__nccwpck_require__(2186)); const fs = __importStar(__nccwpck_require__(7147)); @@ -1122,6 +1128,7 @@ function prepareExistingDirectory(git, repositoryPath, repositoryUrl, clean, ref } }); } +exports.prepareExistingDirectory = prepareExistingDirectory; /***/ }), @@ -1164,8 +1171,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getSource = getSource; -exports.cleanup = cleanup; +exports.cleanup = exports.getSource = void 0; const core = __importStar(__nccwpck_require__(2186)); const fsHelper = __importStar(__nccwpck_require__(7219)); const gitAuthHelper = __importStar(__nccwpck_require__(2565)); @@ -1236,7 +1242,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(); } @@ -1371,6 +1377,7 @@ function getSource(settings) { } }); } +exports.getSource = getSource; function cleanup(repositoryPath) { return __awaiter(this, void 0, void 0, function* () { // Repo exists? @@ -1406,6 +1413,7 @@ function cleanup(repositoryPath) { } }); } +exports.cleanup = cleanup; function getGitCommandManager(settings) { return __awaiter(this, void 0, void 0, function* () { core.info(`Working directory is '${settings.repositoryPath}'`); @@ -1544,8 +1552,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.downloadRepository = downloadRepository; -exports.getDefaultBranch = getDefaultBranch; +exports.getDefaultBranch = exports.downloadRepository = void 0; const assert = __importStar(__nccwpck_require__(9491)); const core = __importStar(__nccwpck_require__(2186)); const fs = __importStar(__nccwpck_require__(7147)); @@ -1609,6 +1616,7 @@ function downloadRepository(authToken, owner, repo, ref, commit, repositoryPath, yield io.rmRF(extractPath); }); } +exports.downloadRepository = downloadRepository; /** * Looks up the default branch name */ @@ -1647,6 +1655,7 @@ function getDefaultBranch(authToken, owner, repo, baseUrl) { })); }); } +exports.getDefaultBranch = getDefaultBranch; function downloadArchive(authToken, owner, repo, ref, commit, baseUrl) { return __awaiter(this, void 0, void 0, function* () { const octokit = github.getOctokit(authToken, { @@ -1705,7 +1714,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getInputs = getInputs; +exports.getInputs = void 0; const core = __importStar(__nccwpck_require__(2186)); const fsHelper = __importStar(__nccwpck_require__(7219)); const github = __importStar(__nccwpck_require__(5438)); @@ -1831,9 +1840,18 @@ 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; }); } +exports.getInputs = getInputs; /***/ }), @@ -1965,12 +1983,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.tagsRefSpec = void 0; -exports.getCheckoutInfo = getCheckoutInfo; -exports.getRefSpecForAllHistory = getRefSpecForAllHistory; -exports.getRefSpec = getRefSpec; -exports.testRef = testRef; -exports.checkCommitInfo = checkCommitInfo; +exports.checkCommitInfo = exports.testRef = exports.getRefSpec = exports.getRefSpecForAllHistory = exports.getCheckoutInfo = exports.tagsRefSpec = void 0; const core = __importStar(__nccwpck_require__(2186)); const github = __importStar(__nccwpck_require__(5438)); const url_helper_1 = __nccwpck_require__(9437); @@ -2024,6 +2037,7 @@ function getCheckoutInfo(git, ref, commit) { return result; }); } +exports.getCheckoutInfo = getCheckoutInfo; function getRefSpecForAllHistory(ref, commit) { const result = ['+refs/heads/*:refs/remotes/origin/*', exports.tagsRefSpec]; if (ref && ref.toUpperCase().startsWith('REFS/PULL/')) { @@ -2032,6 +2046,7 @@ function getRefSpecForAllHistory(ref, commit) { } return result; } +exports.getRefSpecForAllHistory = getRefSpecForAllHistory; function getRefSpec(ref, commit) { if (!ref && !commit) { throw new Error('Args ref and commit cannot both be empty'); @@ -2080,6 +2095,7 @@ function getRefSpec(ref, commit) { return [`+${ref}:${ref}`]; } } +exports.getRefSpec = getRefSpec; /** * Tests whether the initial fetch created the ref at the expected commit */ @@ -2123,6 +2139,7 @@ function testRef(git, ref, commit) { } }); } +exports.testRef = testRef; function checkCommitInfo(token, commitInfo, repositoryOwner, repositoryName, ref, commit, baseUrl) { return __awaiter(this, void 0, void 0, function* () { var _a; @@ -2188,6 +2205,7 @@ function checkCommitInfo(token, commitInfo, repositoryOwner, repositoryName, ref } }); } +exports.checkCommitInfo = checkCommitInfo; function fromPayload(path) { return select(github.context.payload, path); } @@ -2212,12 +2230,13 @@ function select(obj, path) { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.escape = escape; +exports.escape = void 0; function escape(value) { return value.replace(/[^a-zA-Z0-9_]/g, x => { return `\\${x}`; }); } +exports.escape = escape; /***/ }), @@ -2260,8 +2279,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.RetryHelper = void 0; -exports.execute = execute; +exports.execute = exports.RetryHelper = void 0; const core = __importStar(__nccwpck_require__(2186)); const defaultMaxAttempts = 3; const defaultMinSeconds = 10; @@ -2313,6 +2331,7 @@ function execute(action) { return yield retryHelper.execute(action); }); } +exports.execute = execute; /***/ }), @@ -2346,11 +2365,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.SshKnownHostsPath = exports.SshKeyPath = exports.PostSetSafeDirectory = exports.RepositoryPath = exports.IsPost = void 0; -exports.setRepositoryPath = setRepositoryPath; -exports.setSshKeyPath = setSshKeyPath; -exports.setSshKnownHostsPath = setSshKnownHostsPath; -exports.setSafeDirectory = setSafeDirectory; +exports.setSafeDirectory = exports.setSshKnownHostsPath = exports.setSshKeyPath = exports.setRepositoryPath = exports.SshKnownHostsPath = exports.SshKeyPath = exports.PostSetSafeDirectory = exports.RepositoryPath = exports.IsPost = void 0; const core = __importStar(__nccwpck_require__(2186)); /** * Indicates whether the POST action is running @@ -2378,24 +2393,28 @@ exports.SshKnownHostsPath = core.getState('sshKnownHostsPath'); function setRepositoryPath(repositoryPath) { core.saveState('repositoryPath', repositoryPath); } +exports.setRepositoryPath = setRepositoryPath; /** * Save the SSH key path so the POST action can retrieve the value. */ function setSshKeyPath(sshKeyPath) { core.saveState('sshKeyPath', sshKeyPath); } +exports.setSshKeyPath = setSshKeyPath; /** * Save the SSH known hosts path so the POST action can retrieve the value. */ function setSshKnownHostsPath(sshKnownHostsPath) { core.saveState('sshKnownHostsPath', sshKnownHostsPath); } +exports.setSshKnownHostsPath = setSshKnownHostsPath; /** * Save the set-safe-directory input so the POST action can retrieve the value. */ function setSafeDirectory() { core.saveState('setSafeDirectory', 'true'); } +exports.setSafeDirectory = setSafeDirectory; // Publish a variable so that when the POST action runs, it can determine it should run the cleanup logic. // This is necessary since we don't have a separate entry point. if (!exports.IsPost) { @@ -2434,10 +2453,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getFetchUrl = getFetchUrl; -exports.getServerUrl = getServerUrl; -exports.getServerApiUrl = getServerApiUrl; -exports.isGhes = isGhes; +exports.isGhes = exports.getServerApiUrl = exports.getServerUrl = exports.getFetchUrl = void 0; const assert = __importStar(__nccwpck_require__(9491)); const url_1 = __nccwpck_require__(7310); function getFetchUrl(settings) { @@ -2453,12 +2469,14 @@ function getFetchUrl(settings) { // "origin" is SCHEME://HOSTNAME[:PORT] return `${serviceUrl.origin}/${encodedOwner}/${encodedName}`; } +exports.getFetchUrl = getFetchUrl; function getServerUrl(url) { let urlValue = url && url.trim().length > 0 ? url : process.env['GITHUB_SERVER_URL'] || 'https://github.com'; return new url_1.URL(urlValue); } +exports.getServerUrl = getServerUrl; function getServerApiUrl(url) { let apiUrl = 'https://api.github.com'; if (isGhes(url)) { @@ -2467,10 +2485,12 @@ function getServerApiUrl(url) { } return apiUrl; } +exports.getServerApiUrl = getServerApiUrl; function isGhes(url) { const ghUrl = getServerUrl(url); return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM'; } +exports.isGhes = isGhes; /***/ }), @@ -2513,7 +2533,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getOrganizationId = getOrganizationId; +exports.getOrganizationId = void 0; const core = __importStar(__nccwpck_require__(2186)); const fs = __importStar(__nccwpck_require__(7147)); /** @@ -2542,6 +2562,7 @@ function getOrganizationId() { } }); } +exports.getOrganizationId = getOrganizationId; /***/ }), diff --git a/src/git-command-manager.ts b/src/git-command-manager.ts index 8e42a387f..f19952e28 100644 --- a/src/git-command-manager.ts +++ b/src/git-command-manager.ts @@ -42,7 +42,7 @@ export interface IGitCommandManager { ): Promise getDefaultBranch(repositoryUrl: string): Promise getWorkingDirectory(): string - init(): Promise + init(options?: { objectFormat?: string }): Promise isDetached(): Promise lfsFetch(ref: string): Promise lfsInstall(): Promise @@ -327,8 +327,12 @@ class GitCommandManager { return this.workingDirectory } - async init(): Promise { - await this.execGit(['init', this.workingDirectory]) + async init(options?: { objectFormat?: string }): Promise { + await this.execGit([ + 'init', + ...(options?.objectFormat ? [`--object-format=${options.objectFormat}`] : []), + this.workingDirectory + ]) } async isDetached(): Promise { diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts index 2d3513897..8ebb1c67f 100644 --- a/src/git-source-provider.ts +++ b/src/git-source-provider.ts @@ -110,7 +110,7 @@ export async function getSource(settings: IGitSourceSettings): Promise { !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 { 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 }