Refactor CommandCacheKey as a string union

This commit is contained in:
Mario Campos
2026-06-29 23:25:50 -05:00
parent 41965b0e7b
commit c2f43799c5
4 changed files with 36 additions and 35 deletions

View File

@@ -11,7 +11,6 @@ import {
cacheCommandOutput,
getCachedCommandOutput,
resetCachedCommandOutputs,
CommandCacheKey,
} from "./output-cache";
setupTests(test);
@@ -52,14 +51,14 @@ test.serial(
async (t) => {
await withCacheDir((cacheFilePath) => {
writeCacheFile(cacheFilePath, {
[CommandCacheKey.Version]: {
version: {
cmd: "/path/to/codeql",
output: { version: "2.20.0" },
},
});
t.deepEqual(
getCachedCommandOutput(
CommandCacheKey.Version,
"version",
"/path/to/codeql",
isVersionInfo,
),
@@ -74,14 +73,14 @@ test.serial(
async (t) => {
await withCacheDir((cacheFilePath) => {
writeCacheFile(cacheFilePath, {
[CommandCacheKey.Version]: {
version: {
cmd: "/path/to/other-codeql",
output: { version: "2.20.0" },
},
});
t.is(
getCachedCommandOutput(
CommandCacheKey.Version,
"version",
"/path/to/codeql",
isVersionInfo,
),
@@ -98,7 +97,7 @@ test.serial(
fs.writeFileSync(cacheFilePath, "not valid json");
t.is(
getCachedCommandOutput(
CommandCacheKey.Version,
"version",
"/path/to/codeql",
isVersionInfo,
),
@@ -114,7 +113,7 @@ test.serial(
await withCacheDir(() => {
t.is(
getCachedCommandOutput(
CommandCacheKey.Version,
"version",
"/path/to/codeql",
isVersionInfo,
),
@@ -136,11 +135,11 @@ test.serial(
]) {
resetCachedCommandOutputs();
writeCacheFile(cacheFilePath, {
[CommandCacheKey.Version]: { cmd: "/path/to/codeql", output },
version: { cmd: "/path/to/codeql", output },
});
t.is(
getCachedCommandOutput(
CommandCacheKey.Version,
"version",
"/path/to/codeql",
isVersionInfo,
),
@@ -157,11 +156,11 @@ test.serial(
async (t) => {
await withCacheDir((cacheFilePath) => {
writeCacheFile(cacheFilePath, {
[CommandCacheKey.Version]: { output: { version: "2.20.0" } },
version: { output: { version: "2.20.0" } },
});
t.is(
getCachedCommandOutput(
CommandCacheKey.Version,
"version",
"/path/to/codeql",
isVersionInfo,
),
@@ -173,13 +172,13 @@ test.serial(
test.serial("cacheCommandOutput persists the output to the memo", async (t) => {
await withCacheDir(() => {
cacheCommandOutput(CommandCacheKey.Version, "/path/to/codeql", {
cacheCommandOutput("version", "/path/to/codeql", {
hello: "world",
});
// Tier 1: the value is immediately available from the memo.
t.deepEqual(
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
getCachedCommandOutput("version", "/path/to/codeql"),
{ hello: "world" },
);
});
@@ -189,19 +188,19 @@ test.serial(
"getCachedCommandOutput prefers the in-memory memo over the file",
async (t) => {
await withCacheDir((cacheFilePath) => {
cacheCommandOutput(CommandCacheKey.Version, "/path/to/codeql", {
cacheCommandOutput("version", "/path/to/codeql", {
value: 1,
});
// Overwrite the file with a different value; the memo (tier 1) should win.
writeCacheFile(cacheFilePath, {
[CommandCacheKey.Version]: {
version: {
cmd: "/path/to/codeql",
output: { value: 2 },
},
});
t.deepEqual(
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
getCachedCommandOutput("version", "/path/to/codeql"),
{ value: 1 },
);
});

View File

@@ -11,15 +11,8 @@ import { getActionsLogger } from "../logging";
*/
const COMMAND_CACHE_FILENAME = "codeql-action-command-cache.json";
/** Named keys for the CLI command-output cache. */
export const CommandCacheKey = {
Version: "version",
ResolveLanguages: "resolveLanguages",
} as const;
/** A key used to identify cached command output. */
export type CommandCacheKey =
(typeof CommandCacheKey)[keyof typeof CommandCacheKey];
export type CommandCacheKey = "version" | "resolve languages";
/** A single cached command output together with the CLI path it came from. */
interface CommandCacheEntry {

View File

@@ -15,7 +15,7 @@ import * as api from "./api-client";
import {
cacheCommandOutput,
getCachedCommandOutput,
CommandCacheKey,
type CommandCacheKey,
} from "./cli/output-cache";
import { CliError, wrapCliConfigurationError } from "./cli-errors";
import { appendExtraQueryExclusions, type Config } from "./config-utils";
@@ -42,6 +42,11 @@ import { BuildMode, CleanupLevel, getErrorMessage } from "./util";
type Options = Array<string | number | boolean>;
type CommandCacheKeyOutputMap = {
version: VersionInfo;
"resolve languages": ResolveLanguagesOutput;
};
/**
* Extra command line options for the codeql commands.
*/
@@ -547,13 +552,17 @@ export async function getCodeQLForTesting(
* @param run Invokes the CLI to compute the output when it isn't cached.
* @param validate Optional type guard for values loaded from the temporary file.
*/
async function getCachedOrRun<T>(
key: CommandCacheKey,
async function getCachedOrRun<K extends CommandCacheKey>(
key: K,
cmd: string,
run: () => Promise<T>,
validate?: (output: unknown) => output is T,
): Promise<T> {
let result = getCachedCommandOutput<T>(key, cmd, validate);
run: () => Promise<CommandCacheKeyOutputMap[K]>,
validate?: (output: unknown) => output is CommandCacheKeyOutputMap[K],
): Promise<CommandCacheKeyOutputMap[K]> {
let result = getCachedCommandOutput<CommandCacheKeyOutputMap[K]>(
key,
cmd,
validate,
);
if (result === undefined) {
result = await run();
cacheCommandOutput(key, cmd, result);
@@ -579,7 +588,7 @@ async function getCodeQLForCmd(
},
async getVersion() {
return getCachedOrRun(
CommandCacheKey.Version,
"version",
cmd,
() =>
runCliJson<VersionInfo>(cmd, ["version", "--format=json"], {
@@ -786,7 +795,7 @@ async function getCodeQLForCmd(
},
async resolveLanguages() {
return getCachedOrRun(
CommandCacheKey.ResolveLanguages,
"resolve languages",
cmd,
async () => {
const isFilterToLanguagesWithQueriesSupported =

View File

@@ -12,7 +12,7 @@ import {
isSelfHostedRunner,
} from "./actions-util";
import { getAnalysisKey, getApiClient } from "./api-client";
import { getCachedCommandOutput, CommandCacheKey } from "./cli/output-cache";
import { getCachedCommandOutput } from "./cli/output-cache";
import { isVersionInfo } from "./codeql";
import { parseRegistriesWithoutCredentials, type Config } from "./config-utils";
import { DependencyCacheRestoreStatusReport } from "./dependency-caching";
@@ -285,7 +285,7 @@ export async function createStatusReportBase(
}
const runnerOs = getRequiredEnvParam("RUNNER_OS");
const codeQlCliVersion = getCachedCommandOutput(
CommandCacheKey.Version,
"version",
undefined,
isVersionInfo,
);