From 7747b12ae8625d37ceae02420f956504b2078ac6 Mon Sep 17 00:00:00 2001 From: ericLemanissier Date: Wed, 16 Oct 2024 15:04:14 +0200 Subject: [PATCH 1/4] do not attempt to delete existing cache --- src/classes/state/state-cache-storage.ts | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/classes/state/state-cache-storage.ts b/src/classes/state/state-cache-storage.ts index b30b503b6..13880f6c1 100644 --- a/src/classes/state/state-cache-storage.ts +++ b/src/classes/state/state-cache-storage.ts @@ -44,26 +44,6 @@ const checkIfCacheExists = async (cacheKey: string): Promise => { } return false; }; -const resetCacheWithOctokit = async (cacheKey: string): Promise => { - const client = getOctokitClient(); - core.debug(`remove cache "${cacheKey}"`); - try { - // TODO: replace with client.rest. - await client.request( - `DELETE /repos/${context.repo.owner}/${context.repo.repo}/actions/caches?key=${cacheKey}` - ); - } catch (error) { - if (error.status) { - core.warning( - `Error delete ${cacheKey}: [${error.status}] ${ - error.message || 'Unknown reason' - }` - ); - } else { - throw error; - } - } -}; export class StateCacheStorage implements IStateStorage { async save(serializedState: string): Promise { const tmpDir = mkTempDir(); @@ -71,10 +51,6 @@ export class StateCacheStorage implements IStateStorage { fs.writeFileSync(filePath, serializedState); try { - const cacheExists = await checkIfCacheExists(CACHE_KEY); - if (cacheExists) { - await resetCacheWithOctokit(CACHE_KEY); - } const fileSize = fs.statSync(filePath).size; if (fileSize === 0) { From 8bf2567410a02aa765c88cc64c9516b110727f4a Mon Sep 17 00:00:00 2001 From: ericLemanissier Date: Wed, 16 Oct 2024 15:32:50 +0200 Subject: [PATCH 2/4] do not check if cache exists during restore It introduces a TOCTOU issue, and is not needed because `restoreCache` returns `undefined` if the cache does not exist https://github.com/actions/toolkit/tree/main/packages/cache --- src/classes/state/state-cache-storage.ts | 25 +----------------------- 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/classes/state/state-cache-storage.ts b/src/classes/state/state-cache-storage.ts index 13880f6c1..9fb12331e 100644 --- a/src/classes/state/state-cache-storage.ts +++ b/src/classes/state/state-cache-storage.ts @@ -3,8 +3,6 @@ import fs from 'fs'; import path from 'path'; import os from 'os'; import * as core from '@actions/core'; -import {context, getOctokit} from '@actions/github'; -import {retry as octokitRetry} from '@octokit/plugin-retry'; import * as cache from '@actions/cache'; const CACHE_KEY = '_state'; @@ -25,25 +23,6 @@ const unlinkSafely = (filePath: string) => { } }; -const getOctokitClient = () => { - const token = core.getInput('repo-token'); - return getOctokit(token, undefined, octokitRetry); -}; - -const checkIfCacheExists = async (cacheKey: string): Promise => { - const client = getOctokitClient(); - try { - const issueResult = await client.request( - `/repos/${context.repo.owner}/${context.repo.repo}/actions/caches` - ); - const caches: Array<{key?: string}> = - issueResult.data['actions_caches'] || []; - return Boolean(caches.find(cache => cache['key'] === cacheKey)); - } catch (error) { - core.debug(`Error checking if cache exist: ${error.message}`); - } - return false; -}; export class StateCacheStorage implements IStateStorage { async save(serializedState: string): Promise { const tmpDir = mkTempDir(); @@ -75,7 +54,7 @@ export class StateCacheStorage implements IStateStorage { const filePath = path.join(tmpDir, STATE_FILE); unlinkSafely(filePath); try { - const cacheExists = await checkIfCacheExists(CACHE_KEY); + const cacheExists = await cache.restoreCache([path.dirname(filePath)], CACHE_KEY); if (!cacheExists) { core.info( 'The saved state was not found, the process starts from the first issue.' @@ -83,8 +62,6 @@ export class StateCacheStorage implements IStateStorage { return ''; } - await cache.restoreCache([path.dirname(filePath)], CACHE_KEY); - if (!fs.existsSync(filePath)) { core.warning( 'Unknown error when unpacking the cache, the process starts from the first issue.' From ea2b2f2934a942aaa9bfbfe9518ff8757f56e6e4 Mon Sep 17 00:00:00 2001 From: ericLemanissier Date: Thu, 17 Oct 2024 08:24:01 +0000 Subject: [PATCH 3/4] update dist --- dist/index.js | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/dist/index.js b/dist/index.js index 6fe079ac0..55efbfb88 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1592,8 +1592,6 @@ const fs_1 = __importDefault(__nccwpck_require__(7147)); const path_1 = __importDefault(__nccwpck_require__(1017)); const os_1 = __importDefault(__nccwpck_require__(2037)); const core = __importStar(__nccwpck_require__(2186)); -const github_1 = __nccwpck_require__(5438); -const plugin_retry_1 = __nccwpck_require__(6298); const cache = __importStar(__nccwpck_require__(7799)); const CACHE_KEY = '_state'; const STATE_FILE = 'state.txt'; @@ -1611,38 +1609,6 @@ const unlinkSafely = (filePath) => { /* ignore */ } }; -const getOctokitClient = () => { - const token = core.getInput('repo-token'); - return (0, github_1.getOctokit)(token, undefined, plugin_retry_1.retry); -}; -const checkIfCacheExists = (cacheKey) => __awaiter(void 0, void 0, void 0, function* () { - const client = getOctokitClient(); - try { - const issueResult = yield client.request(`/repos/${github_1.context.repo.owner}/${github_1.context.repo.repo}/actions/caches`); - const caches = issueResult.data['actions_caches'] || []; - return Boolean(caches.find(cache => cache['key'] === cacheKey)); - } - catch (error) { - core.debug(`Error checking if cache exist: ${error.message}`); - } - return false; -}); -const resetCacheWithOctokit = (cacheKey) => __awaiter(void 0, void 0, void 0, function* () { - const client = getOctokitClient(); - core.debug(`remove cache "${cacheKey}"`); - try { - // TODO: replace with client.rest. - yield client.request(`DELETE /repos/${github_1.context.repo.owner}/${github_1.context.repo.repo}/actions/caches?key=${cacheKey}`); - } - catch (error) { - if (error.status) { - core.warning(`Error delete ${cacheKey}: [${error.status}] ${error.message || 'Unknown reason'}`); - } - else { - throw error; - } - } -}); class StateCacheStorage { save(serializedState) { return __awaiter(this, void 0, void 0, function* () { @@ -1650,10 +1616,6 @@ class StateCacheStorage { const filePath = path_1.default.join(tmpDir, STATE_FILE); fs_1.default.writeFileSync(filePath, serializedState); try { - const cacheExists = yield checkIfCacheExists(CACHE_KEY); - if (cacheExists) { - yield resetCacheWithOctokit(CACHE_KEY); - } const fileSize = fs_1.default.statSync(filePath).size; if (fileSize === 0) { core.info(`the state will be removed`); @@ -1675,12 +1637,11 @@ class StateCacheStorage { const filePath = path_1.default.join(tmpDir, STATE_FILE); unlinkSafely(filePath); try { - const cacheExists = yield checkIfCacheExists(CACHE_KEY); + const cacheExists = yield cache.restoreCache([path_1.default.dirname(filePath)], CACHE_KEY); if (!cacheExists) { core.info('The saved state was not found, the process starts from the first issue.'); return ''; } - yield cache.restoreCache([path_1.default.dirname(filePath)], CACHE_KEY); if (!fs_1.default.existsSync(filePath)) { core.warning('Unknown error when unpacking the cache, the process starts from the first issue.'); return ''; From 8a1b2ac37c7f08c2fe861b11966db83580569302 Mon Sep 17 00:00:00 2001 From: ericLemanissier Date: Thu, 17 Oct 2024 08:33:12 +0000 Subject: [PATCH 4/4] run prettier --- src/classes/state/state-cache-storage.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/classes/state/state-cache-storage.ts b/src/classes/state/state-cache-storage.ts index 9fb12331e..b891b4e75 100644 --- a/src/classes/state/state-cache-storage.ts +++ b/src/classes/state/state-cache-storage.ts @@ -54,7 +54,10 @@ export class StateCacheStorage implements IStateStorage { const filePath = path.join(tmpDir, STATE_FILE); unlinkSafely(filePath); try { - const cacheExists = await cache.restoreCache([path.dirname(filePath)], CACHE_KEY); + const cacheExists = await cache.restoreCache( + [path.dirname(filePath)], + CACHE_KEY + ); if (!cacheExists) { core.info( 'The saved state was not found, the process starts from the first issue.'