Switch CommandCacheKey back to an enum

The code reads better/simpler as an `enum`.
This commit is contained in:
Mario Campos
2026-06-30 16:06:13 -05:00
parent 0d698171d3
commit da149812f1
5 changed files with 91 additions and 101 deletions

107
lib/entry-points.js generated
View File

@@ -149863,7 +149863,7 @@ var path15 = __toESM(require("path"));
var core10 = __toESM(require_core());
var toolrunner3 = __toESM(require_toolrunner());
// src/cache.ts
// src/cli/output-cache.ts
var fs6 = __toESM(require("fs"));
var path6 = __toESM(require("path"));
@@ -149908,11 +149908,28 @@ function formatDuration(durationMs) {
return `${minutes}m${seconds}s`;
}
// src/cache.ts
// src/cli/output-cache.ts
var COMMAND_CACHE_FILENAME = "codeql-action-command-cache.json";
var CommandCacheKey = {
Version: "version",
ResolveLanguages: "resolveLanguages"
function isVersionInfo(x) {
return isObject(x) && validateSchema(
{
version: string,
features: optional(object),
overlayVersion: optional(number)
},
x
);
}
function isResolveLanguagesOutput(x) {
return isObject(x) && isObject(x.extractors) && Object.values(x.extractors).every(
(extractorList) => isArray(extractorList) && extractorList.every(
(extractor) => isObject(extractor) && isString(extractor.extractor_root)
)
) && (x.aliases === void 0 || isObject(x.aliases) && Object.values(x.aliases).every((alias) => isString(alias)));
}
var commandCacheValidators = {
["version" /* Version */]: isVersionInfo,
["resolve languages" /* ResolveLanguages */]: isResolveLanguagesOutput
};
var inMemoryCache = /* @__PURE__ */ new Map();
var logger = getActionsLogger();
@@ -149948,18 +149965,20 @@ function cacheCommandOutput(key, cmd, output) {
const entry = { cmd, output };
inMemoryCache.set(key, entry);
}
function getCachedCommandOutput(key, cmd, validate) {
function getCachedCommandOutput(key, cmd) {
const memoized = inMemoryCache.get(key);
if (memoized !== void 0) {
return memoized.output;
}
const entry = readCommandCacheFile()[key];
if (!isObject(entry) || !isString(entry.cmd) || cmd !== void 0 && entry.cmd !== cmd || validate !== void 0 && !validate(entry.output)) {
if (!isObject(entry) || !isString(entry.cmd) || cmd !== void 0 && entry.cmd !== cmd || !commandCacheValidators[key](entry.output)) {
logger.warning("Received invalid data from the command-cache file.");
return void 0;
}
cacheCommandOutput(key, entry.cmd, entry.output);
return entry.output;
const cachedEntry = entry;
const output = cachedEntry.output;
cacheCommandOutput(key, cachedEntry.cmd, output);
return output;
}
// src/cli-errors.ts
@@ -153676,23 +153695,6 @@ async function getCombinedTracerConfig(codeql, config) {
}
// src/codeql.ts
function isVersionInfo(x) {
return isObject(x) && validateSchema(
{
version: string,
features: optional(object),
overlayVersion: optional(number)
},
x
);
}
function isResolveLanguagesOutput(x) {
return isObject(x) && isObject(x.extractors) && Object.values(x.extractors).every(
(extractorList) => isArray(extractorList) && extractorList.every(
(extractor) => isObject(extractor) && isString(extractor.extractor_root)
)
) && (x.aliases === void 0 || isObject(x.aliases) && Object.values(x.aliases).every((alias) => isString(alias)));
}
var cachedCodeQL = void 0;
var CODEQL_MINIMUM_VERSION = "2.19.4";
var CODEQL_NEXT_MINIMUM_VERSION = "2.19.4";
@@ -153755,8 +153757,8 @@ async function getCodeQL(cmd) {
}
return cachedCodeQL;
}
async function getCachedOrRun(key, cmd, run9, validate) {
let result = getCachedCommandOutput(key, cmd, validate);
async function getCachedOrRun(key, cmd, run9) {
let result = getCachedCommandOutput(key, cmd);
if (result === void 0) {
result = await run9();
cacheCommandOutput(key, cmd, result);
@@ -153770,12 +153772,11 @@ async function getCodeQLForCmd(cmd, checkVersion) {
},
async getVersion() {
return getCachedOrRun(
CommandCacheKey.Version,
"version" /* Version */,
cmd,
() => runCliJson(cmd, ["version", "--format=json"], {
noStreamStdout: true
}),
isVersionInfo
})
);
},
async printVersion() {
@@ -153931,28 +153932,23 @@ async function getCodeQLForCmd(cmd, checkVersion) {
await runCli(cmd, args);
},
async resolveLanguages() {
return getCachedOrRun(
CommandCacheKey.ResolveLanguages,
cmd,
async () => {
const isFilterToLanguagesWithQueriesSupported = await this.supportsFeature(
"builtinExtractorsSpecifyDefaultQueries" /* BuiltinExtractorsSpecifyDefaultQueries */
);
return runCliJson(cmd, [
"resolve",
"languages",
"--format=betterjson",
"--extractor-options-verbosity=4",
"--extractor-include-aliases",
// TODO: Unconditionally include `--filter-to-languages-with-queries`
// once CODEQL_MINIMUM_VERSION is at least v2.23.0
// — the first version to support this flag.
...isFilterToLanguagesWithQueriesSupported ? ["--filter-to-languages-with-queries"] : [],
...getExtraOptionsFromEnv(["resolve", "languages"])
]);
},
isResolveLanguagesOutput
);
return getCachedOrRun("resolve languages" /* ResolveLanguages */, cmd, async () => {
const isFilterToLanguagesWithQueriesSupported = await this.supportsFeature(
"builtinExtractorsSpecifyDefaultQueries" /* BuiltinExtractorsSpecifyDefaultQueries */
);
return runCliJson(cmd, [
"resolve",
"languages",
"--format=betterjson",
"--extractor-options-verbosity=4",
"--extractor-include-aliases",
// TODO: Unconditionally include `--filter-to-languages-with-queries`
// once CODEQL_MINIMUM_VERSION is at least v2.23.0
// — the first version to support this flag.
...isFilterToLanguagesWithQueriesSupported ? ["--filter-to-languages-with-queries"] : [],
...getExtraOptionsFromEnv(["resolve", "languages"])
]);
});
},
async resolveBuildEnvironment(workingDir, language) {
const codeqlArgs = [
@@ -155213,9 +155209,8 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi
}
const runnerOs = getRequiredEnvParam("RUNNER_OS");
const codeQlCliVersion = getCachedCommandOutput(
CommandCacheKey.Version,
void 0,
isVersionInfo
"version" /* Version */,
void 0
);
const actionRef = process.env["GITHUB_ACTION_REF"] || "";
const testingEnvironment = getTestingEnvironment();

View File

@@ -8,6 +8,7 @@ import { setupTests } from "../testing-utils";
import {
cacheCommandOutput,
CommandCacheKey,
getCachedCommandOutput,
resetCachedCommandOutputs,
type VersionInfo,
@@ -51,16 +52,13 @@ test.serial(
async (t) => {
await withCacheDir((cacheFilePath) => {
writeCacheFile(cacheFilePath, {
version: {
[CommandCacheKey.Version]: {
cmd: "/path/to/codeql",
output: { version: "2.20.0" },
},
});
t.deepEqual(
getCachedCommandOutput(
"version",
"/path/to/codeql",
),
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
{ version: "2.20.0" },
);
});
@@ -72,16 +70,13 @@ test.serial(
async (t) => {
await withCacheDir((cacheFilePath) => {
writeCacheFile(cacheFilePath, {
version: {
[CommandCacheKey.Version]: {
cmd: "/path/to/other-codeql",
output: { version: "2.20.0" },
},
});
t.is(
getCachedCommandOutput(
"version",
"/path/to/codeql",
),
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
undefined,
);
});
@@ -94,10 +89,7 @@ test.serial(
await withCacheDir((cacheFilePath) => {
fs.writeFileSync(cacheFilePath, "not valid json");
t.is(
getCachedCommandOutput(
"version",
"/path/to/codeql",
),
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
undefined,
);
});
@@ -109,10 +101,7 @@ test.serial(
async (t) => {
await withCacheDir(() => {
t.is(
getCachedCommandOutput(
"version",
"/path/to/codeql",
),
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
undefined,
);
});
@@ -131,13 +120,10 @@ test.serial(
]) {
resetCachedCommandOutputs();
writeCacheFile(cacheFilePath, {
version: { cmd: "/path/to/codeql", output },
[CommandCacheKey.Version]: { cmd: "/path/to/codeql", output },
});
t.is(
getCachedCommandOutput(
"version",
"/path/to/codeql",
),
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
undefined,
JSON.stringify(output),
);
@@ -151,13 +137,10 @@ test.serial(
async (t) => {
await withCacheDir((cacheFilePath) => {
writeCacheFile(cacheFilePath, {
version: { output: { version: "2.20.0" } },
[CommandCacheKey.Version]: { output: { version: "2.20.0" } },
});
t.is(
getCachedCommandOutput(
"version",
"/path/to/codeql",
),
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
undefined,
);
});
@@ -167,10 +150,13 @@ test.serial(
test.serial("cacheCommandOutput persists the output to the memo", async (t) => {
await withCacheDir(() => {
const output: VersionInfo = { version: "2.20.0" };
cacheCommandOutput("version", "/path/to/codeql", output);
cacheCommandOutput(CommandCacheKey.Version, "/path/to/codeql", output);
// Tier 1: the value is immediately available from the memo.
t.deepEqual(getCachedCommandOutput("version", "/path/to/codeql"), output);
t.deepEqual(
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
output,
);
});
});
@@ -179,16 +165,19 @@ test.serial(
async (t) => {
await withCacheDir((cacheFilePath) => {
const output: VersionInfo = { version: "2.20.0", overlayVersion: 1 };
cacheCommandOutput("version", "/path/to/codeql", output);
cacheCommandOutput(CommandCacheKey.Version, "/path/to/codeql", output);
// Overwrite the file with a different value; the memo (tier 1) should win.
writeCacheFile(cacheFilePath, {
version: {
[CommandCacheKey.Version]: {
cmd: "/path/to/codeql",
output: { version: "2.21.0" },
},
});
t.deepEqual(getCachedCommandOutput("version", "/path/to/codeql"), output);
t.deepEqual(
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
output,
);
});
},
);

View File

@@ -12,7 +12,10 @@ import { getActionsLogger } from "../logging";
const COMMAND_CACHE_FILENAME = "codeql-action-command-cache.json";
/** A key used to identify cached command output. */
export type CommandCacheKey = "version" | "resolve languages";
export enum CommandCacheKey {
Version = "version",
ResolveLanguages = "resolve languages",
}
export interface VersionInfo {
version: string;
@@ -78,8 +81,8 @@ export function isResolveLanguagesOutput(
}
export type CommandCacheKeyOutputMap = {
version: VersionInfo;
"resolve languages": ResolveLanguagesOutput;
[CommandCacheKey.Version]: VersionInfo;
[CommandCacheKey.ResolveLanguages]: ResolveLanguagesOutput;
};
const commandCacheValidators: {
@@ -87,8 +90,8 @@ const commandCacheValidators: {
output: unknown,
) => output is CommandCacheKeyOutputMap[K];
} = {
version: isVersionInfo,
"resolve languages": isResolveLanguagesOutput,
[CommandCacheKey.Version]: isVersionInfo,
[CommandCacheKey.ResolveLanguages]: isResolveLanguagesOutput,
};
interface StoredCommandCacheEntry {
@@ -174,8 +177,8 @@ export function cacheCommandOutput<K extends CommandCacheKey>(
*
* Resolves tier 1 (in-memory memo) first, then tier 2 (temporary file). A value
* loaded from the file is ignored unless its `cmd` matches the optional `cmd`
* argument, and it satisfies the optional `validate` type guard; valid values
* are memoized into tier 1 before being returned.
* argument and its output satisfies the internal validator for `key`; valid
* values are memoized into tier 1 before being returned.
*
* A return value of `undefined` signals the caller to fall back to tier 3 (the
* CLI).

View File

@@ -14,9 +14,9 @@ import {
import * as api from "./api-client";
import {
cacheCommandOutput,
CommandCacheKey,
getCachedCommandOutput,
type CommandCacheKeyOutputMap,
type CommandCacheKey,
type ResolveLanguagesOutput,
type VersionInfo,
} from "./cli/output-cache";
@@ -515,7 +515,7 @@ async function getCodeQLForCmd(
return cmd;
},
async getVersion() {
return getCachedOrRun("version", cmd, () =>
return getCachedOrRun(CommandCacheKey.Version, cmd, () =>
runCliJson<VersionInfo>(cmd, ["version", "--format=json"], {
noStreamStdout: true,
}),
@@ -718,7 +718,7 @@ async function getCodeQLForCmd(
await runCli(cmd, args);
},
async resolveLanguages() {
return getCachedOrRun("resolve languages", cmd, async () => {
return getCachedOrRun(CommandCacheKey.ResolveLanguages, cmd, async () => {
const isFilterToLanguagesWithQueriesSupported =
await this.supportsFeature(
ToolsFeature.BuiltinExtractorsSpecifyDefaultQueries,

View File

@@ -12,7 +12,7 @@ import {
isSelfHostedRunner,
} from "./actions-util";
import { getAnalysisKey, getApiClient } from "./api-client";
import { getCachedCommandOutput } from "./cli/output-cache";
import { CommandCacheKey, getCachedCommandOutput } from "./cli/output-cache";
import { parseRegistriesWithoutCredentials, type Config } from "./config-utils";
import { DependencyCacheRestoreStatusReport } from "./dependency-caching";
import { DocUrl } from "./doc-url";
@@ -283,7 +283,10 @@ export async function createStatusReportBase(
core.exportVariable(EnvVar.WORKFLOW_STARTED_AT, workflowStartedAt);
}
const runnerOs = getRequiredEnvParam("RUNNER_OS");
const codeQlCliVersion = getCachedCommandOutput("version", undefined);
const codeQlCliVersion = getCachedCommandOutput(
CommandCacheKey.Version,
undefined,
);
const actionRef = process.env["GITHUB_ACTION_REF"] || "";
const testingEnvironment = getTestingEnvironment();
// re-export the testing environment variable so that it is available to subsequent steps,