Clean up path functions in diagnostics.ts and add some tests

This commit is contained in:
Michael B. Gale
2026-10-22 11:32:04 +01:00
parent 308d941317
commit b79966a8ee
5 changed files with 126 additions and 38 deletions

34
lib/entry-points.js generated
View File

@@ -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)) {

View File

@@ -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},

View File

@@ -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);

View File

@@ -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();

View File

@@ -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,
);