Skip to content

Commit

Permalink
Store diagnostics in memory until the database is available
Browse files Browse the repository at this point in the history
  • Loading branch information
mbg committed Apr 11, 2024
1 parent 73ba197 commit cc356e1
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 35 deletions.
54 changes: 41 additions & 13 deletions lib/diagnostics.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/diagnostics.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions lib/init-action.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/init-action.js.map

Large diffs are not rendered by default.

86 changes: 67 additions & 19 deletions src/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ export interface DiagnosticMessage {
attributes?: { [key: string]: any };
}

/** Represents a diagnostic message that has not yet been written to the database. */
interface UnwrittenDiagnostic {
/** The diagnostic message that has not yet been written. */
diagnostic: DiagnosticMessage;
/** The language the diagnostic is for. */
language: Language;
}

/** A list of diagnostics which have not yet been written to disk. */
let unwrittenDiagnostics: UnwrittenDiagnostic[] = [];

/**
* Constructs a new diagnostic message with the specified id and name, as well as optional additional data.
*
Expand All @@ -76,9 +87,11 @@ export function makeDiagnostic(
}

/**
* Writes the given diagnostic to the database.
* Adds the given diagnostic to the database. If the database does not yet exist,
* the diagnostic will be written to it once it has been created.
*
* @param config The configuration that tells us where to store the diagnostic.
* @param language The language which the diagnostic is for.
* @param diagnostic The diagnostic message to add to the database.
*/
export function addDiagnostic(
Expand All @@ -88,30 +101,65 @@ export function addDiagnostic(
) {
const logger = getActionsLogger();
const databasePath = getCodeQLDatabasePath(config, language);

// Check that the database exists before writing to it. If the database does not yet exist,
// store the diagnostic in memory and write it later.
if (existsSync(databasePath)) {
writeDiagnostic(config, language, diagnostic);
} else {
logger.info(
`Writing a diagnostic for ${language}, but the database at ${databasePath} does not exist yet.`,
);

unwrittenDiagnostics.push({ diagnostic, language });
}
}

/**
* Writes the given diagnostic to the database.
*
* @param config The configuration that tells us where to store the diagnostic.
* @param language The language which the diagnostic is for.
* @param diagnostic The diagnostic message to add to the database.
*/
function writeDiagnostic(
config: Config,
language: Language,
diagnostic: DiagnosticMessage,
) {
const logger = getActionsLogger();
const diagnosticsPath = path.resolve(
databasePath,
getCodeQLDatabasePath(config, language),
"diagnostic",
"codeql-action",
);

// Check that the database exists before writing to it.
if (existsSync(databasePath)) {
try {
// Create the directory if it doesn't exist yet.
mkdirSync(diagnosticsPath, { recursive: true });

const jsonPath = path.resolve(
diagnosticsPath,
`codeql-action-${diagnostic.timestamp}.json`,
);
try {
// Create the directory if it doesn't exist yet.
mkdirSync(diagnosticsPath, { recursive: true });

writeFileSync(jsonPath, JSON.stringify(diagnostic));
} catch (err) {
logger.warning(`Unable to write diagnostic message to database: ${err}`);
}
} else {
logger.info(
`Writing a diagnostic for ${language}, but the database at ${databasePath} does not exist yet.`,
const jsonPath = path.resolve(
diagnosticsPath,
`codeql-action-${diagnostic.timestamp}.json`,
);

writeFileSync(jsonPath, JSON.stringify(diagnostic));
} catch (err) {
logger.warning(`Unable to write diagnostic message to database: ${err}`);
}
}

/** Writes all unwritten diagnostics to disk. */
export function flushDiagnostics(config: Config) {
const logger = getActionsLogger();
logger.info(
`Writing ${unwrittenDiagnostics.length} diagnostic(s) to database.`,
);

for (const unwritten of unwrittenDiagnostics) {
writeDiagnostic(config, unwritten.language, unwritten.diagnostic);
}

// Reset the unwritten diagnostics array.
unwrittenDiagnostics = [];
}
6 changes: 5 additions & 1 deletion src/init-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { getGitHubVersion } from "./api-client";
import { CodeQL } from "./codeql";
import * as configUtils from "./config-utils";
import { addDiagnostic, makeDiagnostic } from "./diagnostics";
import { addDiagnostic, flushDiagnostics, makeDiagnostic } from "./diagnostics";
import { EnvVar } from "./environment";
import { Feature, Features } from "./feature-flags";
import { checkInstallPython311, initCodeQL, initConfig, runInit } from "./init";
Expand Down Expand Up @@ -522,6 +522,10 @@ async function run() {
}
}

// Write diagnostics to the database that we previously stored in memory because the database
// did not exist until now.
flushDiagnostics(config);

core.setOutput("codeql-path", config.codeQLCmd);
} catch (unwrappedError) {
const error = wrapError(unwrappedError);
Expand Down

0 comments on commit cc356e1

Please sign in to comment.