From b79966a8eed1b74372dee8aeba5d983c4e29f2d2 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 11:32:04 +0100 Subject: [PATCH] Clean up path functions in `diagnostics.ts` and add some tests --- lib/entry-points.js | 34 ++++++++++----- src/diagnostics.test.ts | 54 +++++++++++++++++++++++ src/diagnostics.ts | 68 +++++++++++++++++++---------- src/init-action-post-helper.test.ts | 4 +- src/init-action-post-helper.ts | 4 +- 5 files changed, 126 insertions(+), 38 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index de7255217..c04fd4a7e 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -172991,6 +172991,11 @@ var semver4 = __toESM(require_semver2()); // src/diagnostics.ts var fs7 = __toESM(require("fs")); var import_path2 = __toESM(require("path")); +var TEMP_DIAGNOSTIC_DIR_NAME = "codeql-action-temp-diagnostics"; +var CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS = [ + "diagnostic", + "codeql-action" +]; var temporaryDiagnostics = []; var diagnosticCounter = 0; function makeDiagnostic(id, name, data = void 0) { @@ -173000,15 +173005,25 @@ function makeDiagnostic(id, name, data = void 0) { source: { ...data?.source, id, name } }; } -function getTempDiagnosticPath(tmpDir, language) { - const root = import_path2.default.join(tmpDir, "codeql-action-temp-diagnostics"); - return getDiagnosticsPath(root, language); +function getLanguageDiagnosticsPath(basePath, language) { + return import_path2.default.resolve( + basePath, + language, + ...CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS + ); } -function getDiagnosticsPath(basePath, language) { +function getTempDiagnosticsRoot(tmpDir) { + return import_path2.default.resolve(tmpDir, TEMP_DIAGNOSTIC_DIR_NAME); +} +function getTempLanguageDiagnosticsPath(tmpDir, language) { + const root = getTempDiagnosticsRoot(tmpDir); if (language !== void 0) { - return import_path2.default.resolve(basePath, language, "diagnostic", "codeql-action"); + return getLanguageDiagnosticsPath(root, language); } - return import_path2.default.resolve(basePath, "diagnostic", "codeql-action"); + return import_path2.default.resolve(root, ...CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS); +} +function getDatabaseDiagnosticsPath(config, language) { + return getLanguageDiagnosticsPath(config.dbLocation, language); } function addDiagnostic(config, language, diagnostic, logger2 = getActionsLogger()) { const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; @@ -173043,7 +173058,7 @@ function addNoLanguageDiagnostic(config, diagnostic, logger2 = getActionsLogger( } } function writeTemporaryDiagnosticFile(logger2, tempDir, language, diagnostic) { - const tempDiagnosticsPath = getTempDiagnosticPath(tempDir, language); + const tempDiagnosticsPath = getTempLanguageDiagnosticsPath(tempDir, language); try { const diagnosticPath = writeDiagnosticFile(tempDiagnosticsPath, diagnostic); temporaryDiagnostics.push({ path: diagnosticPath, language }); @@ -173069,9 +173084,6 @@ function writeDiagnosticFile(diagnosticsPath, diagnostic) { fs7.writeFileSync(jsonPath, JSON.stringify(diagnostic)); return jsonPath; } -function getDatabaseDiagnosticsPath(config, language) { - return getDiagnosticsPath(config.dbLocation, language); -} function writeDiagnostic(action, config, language, diagnostic) { const diagnosticsPath = getDatabaseDiagnosticsPath(config, language); try { @@ -187059,7 +187071,7 @@ async function generateFailedSarif(logger2, features, config, category, checkout codeql ); if (databasePath === void 0 || !exportDiagnosticsEnabled) { - let diagnosticDir = getTempDiagnosticPath( + let diagnosticDir = getTempDiagnosticsRoot( config.tempDir ); if (!exportDiagnosticsEnabled || !fs31.existsSync(diagnosticDir)) { diff --git a/src/diagnostics.test.ts b/src/diagnostics.test.ts index 2ba98da60..0d9af674d 100644 --- a/src/diagnostics.test.ts +++ b/src/diagnostics.test.ts @@ -27,6 +27,60 @@ test("makeDiagnostic - adds expected properties", (t) => { t.is(diagnostic.source.name, name); }); +test("getLanguageDiagnosticsPath gets language-specific path", async (t) => + withTmpDir(async (tmpDir) => { + for (const language of Object.values(BuiltInLanguage)) { + t.is( + diagnostics.getLanguageDiagnosticsPath(tmpDir, language), + path.resolve( + tmpDir, + language, + ...diagnostics.CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS, + ), + ); + } + })); + +test("getTempLanguageDiagnosticsPath returns path without language", async (t) => + withTmpDir(async (tmpDir) => { + t.is( + diagnostics.getTempLanguageDiagnosticsPath(tmpDir), + path.resolve( + tmpDir, + diagnostics.TEMP_DIAGNOSTIC_DIR_NAME, + ...diagnostics.CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS, + ), + ); + })); + +test("getTempLanguageDiagnosticsPath returns language-specific path if a language is provided", async (t) => + withTmpDir(async (tmpDir) => { + t.is( + diagnostics.getTempLanguageDiagnosticsPath(tmpDir, BuiltInLanguage.swift), + path.resolve( + tmpDir, + diagnostics.TEMP_DIAGNOSTIC_DIR_NAME, + BuiltInLanguage.swift, + ...diagnostics.CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS, + ), + ); + })); + +test("getDatabaseDiagnosticsPath returns language-specific path if a language is provided", async (t) => + withTmpDir(async (tmpDir) => { + t.is( + diagnostics.getDatabaseDiagnosticsPath( + createTestConfig({ dbLocation: tmpDir }), + BuiltInLanguage.swift, + ), + path.resolve( + tmpDir, + BuiltInLanguage.swift, + ...diagnostics.CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS, + ), + ); + })); + /** * Diagnostic files that are written to disk don't have deterministic names. * This function recursively finds all `.json` files at {@link rootPath}, diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 2c5fe909d..5e5bf2156 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -12,6 +12,14 @@ import { isErrnoException, } from "./util"; +/** The name of the directory we use to temporarily store diagnostics. */ +export const TEMP_DIAGNOSTIC_DIR_NAME = "codeql-action-temp-diagnostics"; + +export const CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS = [ + "diagnostic", + "codeql-action", +]; + /** * Known tags for diagnostics. There is currently only "internal-error", * but others may be added in the future. @@ -129,26 +137,48 @@ export function makeDiagnostic( } /** - * Gets a path relative to {@link tmpDir} where diagnostics for {@link language} - * can temporarily be stored at before the database is initialised. If {@link language} - * is `undefined`, then the common base path for all languages relative to {@link tmpDir} - * is returned. + * Gets a path relative to {@link basePath} where diagnostics for to {@link language} should be stored at. */ -export function getTempDiagnosticPath(tmpDir: string, language?: Language) { - const root = path.join(tmpDir, "codeql-action-temp-diagnostics"); - return getDiagnosticsPath(root, language); +export function getLanguageDiagnosticsPath( + basePath: string, + language: Language, +) { + return path.resolve( + basePath, + language, + ...CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS, + ); } /** - * Gets a path relative to {@link basePath} where diagnostics for {@link language} - * should be stored at. If {@link language} is `undefined`, then {@link basePath} - * is returned instead. + * Gets a path relative to {@link tmpDir} where diagnostics should temporarily be stored + * until they can be moved to the database. */ -export function getDiagnosticsPath(basePath: string, language?: Language) { +export function getTempDiagnosticsRoot(tmpDir: string): string { + return path.resolve(tmpDir, TEMP_DIAGNOSTIC_DIR_NAME); +} + +/** + * Gets a path relative to {@link tmpDir} where diagnostics for {@link language} + * can temporarily be stored at before the database is initialised. If {@link language} + * is `undefined`, then a non-language-specific path is returned. + */ +export function getTempLanguageDiagnosticsPath( + tmpDir: string, + language?: Language, +) { + const root = getTempDiagnosticsRoot(tmpDir); + if (language !== undefined) { - return path.resolve(basePath, language, "diagnostic", "codeql-action"); + return getLanguageDiagnosticsPath(root, language); } - return path.resolve(basePath, "diagnostic", "codeql-action"); + + return path.resolve(root, ...CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS); +} + +/** Gets the path where diagnostics for {@link language} should be stored in the database. */ +export function getDatabaseDiagnosticsPath(config: Config, language: Language) { + return getLanguageDiagnosticsPath(config.dbLocation, language); } /** @@ -222,7 +252,7 @@ function writeTemporaryDiagnosticFile( language: Language | undefined, diagnostic: DiagnosticMessage, ) { - const tempDiagnosticsPath = getTempDiagnosticPath(tempDir, language); + const tempDiagnosticsPath = getTempLanguageDiagnosticsPath(tempDir, language); try { // Write the diagnostic to a temporary location. @@ -266,14 +296,6 @@ function writeDiagnosticFile( return jsonPath; } -/** Gets the path where diagnostics for {@link language} should be stored in the database. */ -export function getDatabaseDiagnosticsPath( - config: Config, - language: Language | undefined, -) { - return getDiagnosticsPath(config.dbLocation, language); -} - /** * Writes the given diagnostic to the database. * @@ -284,7 +306,7 @@ export function getDatabaseDiagnosticsPath( function writeDiagnostic( action: ActionState<["Logger"]>, config: Config, - language: Language | undefined, + language: Language, diagnostic: DiagnosticMessage, ) { const diagnosticsPath = getDatabaseDiagnosticsPath(config, language); diff --git a/src/init-action-post-helper.test.ts b/src/init-action-post-helper.test.ts index 0458dbf52..01dfbe0ce 100644 --- a/src/init-action-post-helper.test.ts +++ b/src/init-action-post-helper.test.ts @@ -11,7 +11,7 @@ import * as apiClient from "./api-client"; import * as codeql from "./codeql"; import * as configUtils from "./config-utils"; import * as debugArtifacts from "./debug-artifacts"; -import { getTempDiagnosticPath } from "./diagnostics"; +import { getTempDiagnosticsRoot } from "./diagnostics"; import { EnvVar } from "./environment"; import { Feature } from "./feature-flags"; import * as initActionPostHelper from "./init-action-post-helper"; @@ -43,7 +43,7 @@ test.serial("generateFailedSarif picks up unwritten diagnostics", async (t) => util.withTmpDir(async (tmpDir) => { const logger = new RecordingLogger(); - const tempDiagDir = getTempDiagnosticPath(tmpDir); + const tempDiagDir = getTempDiagnosticsRoot(tmpDir); fs.mkdirSync(tempDiagDir, { recursive: true }); const codeqlObject = await codeql.getCodeQLForTesting(); diff --git a/src/init-action-post-helper.ts b/src/init-action-post-helper.ts index b86ed9dbb..060592cac 100644 --- a/src/init-action-post-helper.ts +++ b/src/init-action-post-helper.ts @@ -24,7 +24,7 @@ import { type UploadDebugArtifactsConfig, } from "./debug-artifacts"; import * as dependencyCaching from "./dependency-caching"; -import { getTempDiagnosticPath } from "./diagnostics"; +import { getTempDiagnosticsRoot } from "./diagnostics"; import { EnvVar, ReadOnlyEnv } from "./environment"; import { Feature, FeatureEnablement } from "./feature-flags"; import { Logger } from "./logging"; @@ -215,7 +215,7 @@ export async function generateFailedSarif( // path that doesn't exist, so we are just being extra defensive here. // We also don't pass the path to the CLI if `exportDiagnosticsEnabled` is not enabled, to preserve // its intended behaviour of controlling whether diagnostics are included in the SARIF or not. - let diagnosticDir: string | undefined = getTempDiagnosticPath( + let diagnosticDir: string | undefined = getTempDiagnosticsRoot( config.tempDir, );