From 2613b9ca2bc0061a584d1218ea0cbb5f9a6175fb Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 23:38:11 +0100 Subject: [PATCH] Fix `flushDiagnostics` not ensuring directories exist --- lib/entry-points.js | 13 +++++++++++-- src/diagnostics.test.ts | 3 +-- src/diagnostics.ts | 16 +++++++++++++--- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 54362e40d..7376558e1 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -173070,6 +173070,7 @@ function flushDiagnostics(action, config) { action.logger.debug( `Moving ${diagnosticsCount} diagnostic(s) to their respective databases.` ); + const failedFlushDiagnostics = []; for (const temporary of temporaryDiagnostics) { const directory = getDatabaseDiagnosticsPath( config, @@ -173077,9 +173078,17 @@ function flushDiagnostics(action, config) { ); const filename = import_path2.default.basename(temporary.path); const destination = import_path2.default.join(directory, filename); - action.fs.renameSync(temporary.path, destination); + try { + action.fs.mkdirSync(directory, { recursive: true }); + action.fs.renameSync(temporary.path, destination); + } catch (err) { + action.logger.warning( + `Failed to rename '${temporary.path}' to '${destination}': ${getErrorMessage(err)}` + ); + failedFlushDiagnostics.push(temporary); + } } - temporaryDiagnostics = []; + temporaryDiagnostics = failedFlushDiagnostics; } function makeTelemetryDiagnostic(id, name, attributes, tags) { return makeDiagnostic(id, name, { diff --git a/src/diagnostics.test.ts b/src/diagnostics.test.ts index e721dfc52..7d898defc 100644 --- a/src/diagnostics.test.ts +++ b/src/diagnostics.test.ts @@ -88,9 +88,8 @@ test("addDiagnostic writes temporary diagnostics and flushDiagnostics moves them ); }); - // addDiagnostic t.is(existsSync.callCount, 1); - t.is(mkdirSync.callCount, 1); + t.is(mkdirSync.callCount, 2); t.is(writeFileSync.callCount, 1); t.is(writeFileSync.args[0].length, 2); t.is(writeFileSync.args[0][1], JSON.stringify(diagnostic)); diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 3563e41f4..a29ef25ec 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -7,7 +7,7 @@ import type { Config } from "./config-utils"; import type { FileSystem } from "./fs"; import { Language } from "./languages"; import { getActionsLogger, type Logger } from "./logging"; -import { getCodeQLDatabasePath } from "./util"; +import { getCodeQLDatabasePath, getErrorMessage } from "./util"; /** * Known tags for diagnostics. There is currently only "internal-error", @@ -304,6 +304,7 @@ export function flushDiagnostics( `Moving ${diagnosticsCount} diagnostic(s) to their respective databases.`, ); + const failedFlushDiagnostics: TemporaryDiagnostic[] = []; for (const temporary of temporaryDiagnostics) { // If `temporary.language` is `undefined`, then we didn't have a `config` at the time that // `addNoLanguageDiagnostic` was called. In that case, we arbitrarily choose the first @@ -315,11 +316,20 @@ export function flushDiagnostics( const filename = path.basename(temporary.path); const destination = path.join(directory, filename); - action.fs.renameSync(temporary.path, destination); + try { + action.fs.mkdirSync(directory, { recursive: true }); + action.fs.renameSync(temporary.path, destination); + } catch (err) { + action.logger.warning( + `Failed to rename '${temporary.path}' to '${destination}': ${getErrorMessage(err)}`, + ); + + failedFlushDiagnostics.push(temporary); + } } // Reset the temporary diagnostics arrays. - temporaryDiagnostics = []; + temporaryDiagnostics = failedFlushDiagnostics; } /**