Replace string with CommandCacheKey for better type safety

This commit is contained in:
Mario Campos
2026-06-19 14:47:05 -05:00
parent 420c97eadd
commit dd7ff30205
4 changed files with 40 additions and 24 deletions

View File

@@ -174,7 +174,7 @@ test.serial(
"cacheCommandOutput persists the output to both the memo and the file",
async (t) => {
await withCacheDir((cacheFilePath) => {
cacheCommandOutput("some-command", "/path/to/codeql", {
cacheCommandOutput(CommandCacheKey.Version, "/path/to/codeql", {
hello: "world",
});
@@ -182,16 +182,17 @@ test.serial(
const onDisk = JSON.parse(
fs.readFileSync(cacheFilePath, "utf8"),
) as Record<string, unknown>;
t.deepEqual(onDisk["some-command"], {
t.deepEqual(onDisk[CommandCacheKey.Version], {
cmd: "/path/to/codeql",
output: { hello: "world" },
});
// Tier 1: the value is served from the memo even after the file is gone.
fs.rmSync(cacheFilePath);
t.deepEqual(getCachedCommandOutput("some-command", "/path/to/codeql"), {
hello: "world",
});
t.deepEqual(
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
{ hello: "world" },
);
});
},
);
@@ -200,15 +201,18 @@ test.serial(
"getCachedCommandOutput prefers the in-memory memo over the file",
async (t) => {
await withCacheDir((cacheFilePath) => {
cacheCommandOutput("some-command", "/path/to/codeql", { value: 1 });
cacheCommandOutput(CommandCacheKey.Version, "/path/to/codeql", {
value: 1,
});
// Overwrite the file with a different value; the memo (tier 1) should win.
writeCacheFile(cacheFilePath, {
"some-command": { cmd: "/path/to/codeql", output: { value: 2 } },
});
t.deepEqual(getCachedCommandOutput("some-command", "/path/to/codeql"), {
value: 1,
[CommandCacheKey.Version]: { cmd: "/path/to/codeql", output: { value: 2 } },
});
t.deepEqual(
getCachedCommandOutput(CommandCacheKey.Version, "/path/to/codeql"),
{ value: 1 },
);
});
},
);
@@ -217,9 +221,13 @@ test.serial(
"cacheCommandOutput throws if called twice for the same key",
async (t) => {
await withCacheDir(() => {
cacheCommandOutput("some-command", "/path/to/codeql", { value: 1 });
cacheCommandOutput(CommandCacheKey.Version, "/path/to/codeql", {
value: 1,
});
t.throws(() =>
cacheCommandOutput("some-command", "/path/to/codeql", { value: 2 }),
cacheCommandOutput(CommandCacheKey.Version, "/path/to/codeql", {
value: 2,
}),
);
});
},

View File

@@ -10,11 +10,15 @@ import * as json from "./json";
*/
const COMMAND_CACHE_FILENAME = "codeql-action-command-cache.json";
/** The keys for cached CLI commands. */
export enum CommandCacheKey {
Version = "version",
ResolveLanguages = "resolveLanguages",
}
/** 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];
/** A single cached command output together with the CLI path it came from. */
interface CacheEntry {
@@ -32,7 +36,7 @@ interface CacheEntry {
* whenever a value is read from the file (tier 2) or computed via the CLI
* (tier 3).
*/
const inMemoryCache = new Map<string, CacheEntry>();
const inMemoryCache = new Map<CommandCacheKey, CacheEntry>();
function getCommandCacheFilePath(): string {
return path.join(getTemporaryDirectory(), COMMAND_CACHE_FILENAME);
@@ -81,7 +85,7 @@ function writeCommandCacheFile(data: Record<string, CacheEntry>): void {
* served from the memo rather than recomputed.
*/
export function cacheCommandOutput(
key: string,
key: CommandCacheKey,
cmd: string,
output: unknown,
): void {
@@ -110,7 +114,7 @@ export function cacheCommandOutput(
* CLI).
*/
export function getCachedCommandOutput<T>(
key: string,
key: CommandCacheKey,
cmd?: string,
validate?: (output: unknown) => output is T,
): T | undefined {

View File

@@ -548,7 +548,7 @@ export async function getCodeQLForTesting(
* @param validate Optional type guard for values loaded from the temporary file.
*/
async function getCachedOrRun<T>(
key: string,
key: CommandCacheKey,
cmd: string,
run: () => Promise<T>,
validate?: (output: unknown) => output is T,