From fcd8d74cda72c98da18b8990874bb47f19b9634e Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Fri, 14 Aug 2026 14:41:04 -0500 Subject: [PATCH] Refactor output-caching functions to accept file path dependency This makes it easier to test. Credit to @mbg. --- lib/entry-points.js | 30 ++++++++++--------- src/cli/output-cache.test.ts | 58 ++++++++++++++++++++---------------- src/cli/output-cache.ts | 20 +++++-------- src/codeql.ts | 9 ++++-- src/status-report.ts | 10 +++++-- 5 files changed, 70 insertions(+), 57 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 277472778..ab6b83dab 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146753,7 +146753,7 @@ var cachedCodeQlVersion = void 0; function getCommandCacheFilePath(env) { return import_path.default.join(getTemporaryDirectory(env), COMMAND_CACHE_FILENAME); } -function cacheCodeQlVersion(env, cmd, version) { +function cacheCodeQlVersion(cacheFilePath, cmd, version) { if (cachedCodeQlVersion !== void 0) { throw new Error("cacheCodeQlVersion() should be called only once"); } @@ -146762,23 +146762,17 @@ function cacheCodeQlVersion(env, cmd, version) { cmd, entries: { version } }; - fs3.writeFileSync( - getCommandCacheFilePath(env), - JSON.stringify(outputCache), - "utf8" - ); + fs3.writeFileSync(cacheFilePath, JSON.stringify(outputCache), "utf8"); } -function getCachedCodeQlVersion(logger, env, cmd) { +function getCachedCodeQlVersion(logger, cacheFilePath, cmd) { if (cachedCodeQlVersion !== void 0) { return cachedCodeQlVersion; } let serialized; try { - serialized = fs3.readFileSync(getCommandCacheFilePath(env), "utf8"); + serialized = fs3.readFileSync(cacheFilePath, "utf8"); } catch (e) { - logger.debug( - `Cannot read CLI-cache file ${getCommandCacheFilePath(env)}: ${e}` - ); + logger.debug(`Cannot read CLI-cache file ${cacheFilePath}: ${e}`); return void 0; } let persisted; @@ -147342,7 +147336,10 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi core7.exportVariable("CODEQL_WORKFLOW_STARTED_AT" /* WORKFLOW_STARTED_AT */, workflowStartedAt); } const runnerOs = getRequiredEnvParam("RUNNER_OS"); - const codeQlCliVersion = getCachedCodeQlVersion(logger, getEnv()); + const codeQlCliVersion = getCachedCodeQlVersion( + logger, + getCommandCacheFilePath(getEnv()) + ); const actionRef = process.env["GITHUB_ACTION_REF"] || ""; const testingEnvironment = getTestingEnvironment(); if (testingEnvironment) { @@ -152362,7 +152359,12 @@ async function getCodeQLForCmd(logger, cmd, checkVersion) { return cmd; }, async getVersion() { - let result = getCachedCodeQlVersion(logger, getEnv(), cmd); + const cacheFilePath = getCommandCacheFilePath(getEnv()); + let result = getCachedCodeQlVersion( + logger, + cacheFilePath, + cmd + ); if (result === void 0) { result = await runCliJson( cmd, @@ -152371,7 +152373,7 @@ async function getCodeQLForCmd(logger, cmd, checkVersion) { noStreamStdout: true } ); - cacheCodeQlVersion(getEnv(), cmd, result); + cacheCodeQlVersion(cacheFilePath, cmd, result); } return result; }, diff --git a/src/cli/output-cache.test.ts b/src/cli/output-cache.test.ts index d5475f9cb..656cfd820 100644 --- a/src/cli/output-cache.test.ts +++ b/src/cli/output-cache.test.ts @@ -1,16 +1,13 @@ import * as fs from "fs"; +import path from "path"; import test from "ava"; -import { EnvVar } from "../environment"; import { getRunnerLogger } from "../logging"; -import { getTestEnv, setupTests } from "../testing-utils"; +import { setupTests } from "../testing-utils"; import * as util from "../util"; -import { - getCachedCodeQlVersion, - getCommandCacheFilePath, -} from "./output-cache"; +import { getCachedCodeQlVersion } from "./output-cache"; setupTests(test); @@ -20,19 +17,22 @@ test.serial( "getCachedCodeQlVersion reuses a version persisted by an earlier step", async (t) => { await util.withTmpDir(async (tmpDir: string) => { - const env = getTestEnv({ [EnvVar.TEMP]: tmpDir }); - const cacheFile = getCommandCacheFilePath(env); + const cacheFilePath = path.join(tmpDir, "cache.json"); + fs.writeFileSync( - cacheFile, + cacheFilePath, JSON.stringify({ cmd: "/path/to/codeql", entries: { version: { version: "2.20.0" } }, }), "utf8", ); - t.deepEqual(getCachedCodeQlVersion(logger, env, "/path/to/codeql"), { - version: "2.20.0", - }); + t.deepEqual( + getCachedCodeQlVersion(logger, cacheFilePath, "/path/to/codeql"), + { + version: "2.20.0", + }, + ); }); }, ); @@ -41,17 +41,19 @@ test.serial( "getCachedCodeQlVersion ignores a persisted version from a different CLI", async (t) => { await util.withTmpDir(async (tmpDir: string) => { - const env = getTestEnv({ [EnvVar.TEMP]: tmpDir }); - const cacheFile = getCommandCacheFilePath(env); + const cacheFilePath = path.join(tmpDir, "cache.json"); fs.writeFileSync( - cacheFile, + cacheFilePath, JSON.stringify({ cmd: "/path/to/other-codeql", entries: { version: { version: "2.20.0" } }, }), "utf8", ); - t.is(getCachedCodeQlVersion(logger, env, "/path/to/codeql"), undefined); + t.is( + getCachedCodeQlVersion(logger, cacheFilePath, "/path/to/codeql"), + undefined, + ); }); }, ); @@ -60,10 +62,12 @@ test.serial( "getCachedCodeQlVersion ignores a malformed persisted value", async (t) => { await util.withTmpDir(async (tmpDir: string) => { - const env = getTestEnv({ [EnvVar.TEMP]: tmpDir }); - const cacheFile = getCommandCacheFilePath(env); - fs.writeFileSync(cacheFile, "not valid json", "utf8"); - t.is(getCachedCodeQlVersion(logger, env, "/path/to/codeql"), undefined); + const cacheFilePath = path.join(tmpDir, "cache.json"); + fs.writeFileSync(cacheFilePath, "not valid json", "utf8"); + t.is( + getCachedCodeQlVersion(logger, cacheFilePath, "/path/to/codeql"), + undefined, + ); }); }, ); @@ -72,8 +76,7 @@ test.serial( "getCachedCodeQlVersion ignores a persisted value with the wrong structure", async (t) => { await util.withTmpDir(async (tmpDir: string) => { - const env = getTestEnv({ [EnvVar.TEMP]: tmpDir }); - const cacheFile = getCommandCacheFilePath(env); + const cacheFilePath = path.join(tmpDir, "cache.json"); const testValues = [ { cmd: "/path/to/codeql" }, { entries: { version: { version: "2.20.0" } } }, @@ -96,9 +99,9 @@ test.serial( ].map((v) => JSON.stringify(v)); for (const value of testValues) { - fs.writeFileSync(cacheFile, value, "utf8"); + fs.writeFileSync(cacheFilePath, value, "utf8"); t.is( - getCachedCodeQlVersion(logger, env, "/path/to/codeql"), + getCachedCodeQlVersion(logger, cacheFilePath, "/path/to/codeql"), undefined, value, ); @@ -109,9 +112,12 @@ test.serial( test.serial("getCachedCodeQlVersion ignores non-existent file", async (t) => { await util.withTmpDir(async (tmpDir: string) => { - const env = getTestEnv({ [EnvVar.TEMP]: tmpDir }); + const cacheFilePath = path.join(tmpDir, "cache.json"); t.notThrows(() => { - t.is(getCachedCodeQlVersion(logger, env, "/path/to/codeql"), undefined); + t.is( + getCachedCodeQlVersion(logger, cacheFilePath, "/path/to/codeql"), + undefined, + ); }); }); }); diff --git a/src/cli/output-cache.ts b/src/cli/output-cache.ts index 0ed592997..fb5deb1ad 100644 --- a/src/cli/output-cache.ts +++ b/src/cli/output-cache.ts @@ -57,12 +57,12 @@ export function getCommandCacheFilePath(env: Env): string { /** * Caches the CodeQL CLI version both in-memory and on disk. - * @param env The environment variables to use. + * @param cacheFilePath The path to the cache file. * @param cmd The path to the CodeQL CLI. * @param version The version information to cache. */ export function cacheCodeQlVersion( - env: Env, + cacheFilePath: string, cmd: string, version: VersionInfo, ): void { @@ -78,22 +78,18 @@ export function cacheCodeQlVersion( // processes, can reuse it rather than invoking `codeql version` again. We // record the CLI path so that a different step using a different CodeQL bundle // doesn't pick up a stale version. - fs.writeFileSync( - getCommandCacheFilePath(env), - JSON.stringify(outputCache), - "utf8", - ); + fs.writeFileSync(cacheFilePath, JSON.stringify(outputCache), "utf8"); } /** * Returns the cached CodeQL CLI version, if any. * @param logger The logger to use for logging messages. - * @param env The environment variables to use. + * @param cacheFilePath The path to the cache file. * @param cmd The path to the CodeQL CLI. */ export function getCachedCodeQlVersion( logger: Logger, - env: Env, + cacheFilePath: string, cmd?: string, ): undefined | VersionInfo { if (cachedCodeQlVersion !== undefined) { @@ -104,11 +100,9 @@ export function getCachedCodeQlVersion( // invokes `codeql version` instead. let serialized: string; try { - serialized = fs.readFileSync(getCommandCacheFilePath(env), "utf8"); + serialized = fs.readFileSync(cacheFilePath, "utf8"); } catch (e) { - logger.debug( - `Cannot read CLI-cache file ${getCommandCacheFilePath(env)}: ${e}`, - ); + logger.debug(`Cannot read CLI-cache file ${cacheFilePath}: ${e}`); return undefined; } let persisted: unknown; diff --git a/src/codeql.ts b/src/codeql.ts index 8f7e9e744..bfa52d52d 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -491,7 +491,12 @@ async function getCodeQLForCmd( return cmd; }, async getVersion() { - let result = outputCache.getCachedCodeQlVersion(logger, getEnv(), cmd); + const cacheFilePath = outputCache.getCommandCacheFilePath(getEnv()); + let result = outputCache.getCachedCodeQlVersion( + logger, + cacheFilePath, + cmd, + ); if (result === undefined) { result = await runCliJson( cmd, @@ -500,7 +505,7 @@ async function getCodeQLForCmd( noStreamStdout: true, }, ); - outputCache.cacheCodeQlVersion(getEnv(), cmd, result); + outputCache.cacheCodeQlVersion(cacheFilePath, cmd, result); } return result; }, diff --git a/src/status-report.ts b/src/status-report.ts index e61b04f9d..c5d15e1f1 100644 --- a/src/status-report.ts +++ b/src/status-report.ts @@ -14,7 +14,10 @@ import { isSelfHostedRunner, } from "./actions-util"; import { getAnalysisKey, getApiClient } from "./api-client"; -import { getCachedCodeQlVersion } from "./cli/output-cache"; +import { + getCachedCodeQlVersion, + getCommandCacheFilePath, +} from "./cli/output-cache"; import type { Config } from "./config/action-config"; import type { ComputedInput, InputName } from "./config/inputs"; import { parseRegistriesWithoutCredentials } from "./config/pack-registries"; @@ -376,7 +379,10 @@ export async function createStatusReportBase( core.exportVariable(EnvVar.WORKFLOW_STARTED_AT, workflowStartedAt); } const runnerOs = getRequiredEnvParam("RUNNER_OS"); - const codeQlCliVersion = getCachedCodeQlVersion(logger, getEnv()); + const codeQlCliVersion = getCachedCodeQlVersion( + logger, + getCommandCacheFilePath(getEnv()), + ); const actionRef = process.env["GITHUB_ACTION_REF"] || ""; const testingEnvironment = getTestingEnvironment(); // re-export the testing environment variable so that it is available to subsequent steps,