Reduce duplication in the logs when errors occur in CLI commands
This commit is contained in:
parent
a2dc5ffaff
commit
8295705640
9 changed files with 71 additions and 28 deletions
6
lib/analyze.js
generated
6
lib/analyze.js
generated
|
|
@ -237,12 +237,8 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
|
|||
}
|
||||
}
|
||||
catch (e) {
|
||||
logger.info(String(e));
|
||||
if (e instanceof Error) {
|
||||
logger.info(e.stack);
|
||||
}
|
||||
statusReport.analyze_failure_language = language;
|
||||
throw new CodeQLAnalysisError(statusReport, `Error running analysis for ${language}: ${e}`);
|
||||
throw new CodeQLAnalysisError(statusReport, `Error running analysis for ${language}: ${util.wrapError(e).message}`);
|
||||
}
|
||||
}
|
||||
return statusReport;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
21
lib/codeql.js
generated
21
lib/codeql.js
generated
|
|
@ -37,15 +37,25 @@ const setupCodeql = __importStar(require("./setup-codeql"));
|
|||
const util = __importStar(require("./util"));
|
||||
const util_1 = require("./util");
|
||||
class CommandInvocationError extends Error {
|
||||
constructor(cmd, args, exitCode, error, output) {
|
||||
constructor(cmd, args, exitCode, stderr, stdout) {
|
||||
const prettyCommand = [cmd, ...args]
|
||||
.map((x) => (x.includes(" ") ? `'${x}'` : x))
|
||||
.join(" ");
|
||||
const fatalErrors = extractFatalErrors(stderr);
|
||||
const lastLine = stderr.trim().split("\n").pop()?.trim();
|
||||
let error = fatalErrors
|
||||
? ` and error was: ${fatalErrors.trim()}`
|
||||
: lastLine
|
||||
? ` and last log line was: ${lastLine}`
|
||||
: "";
|
||||
if (error[error.length - 1] !== ".") {
|
||||
error += ".";
|
||||
}
|
||||
super(`Encountered a fatal error while running "${prettyCommand}". ` +
|
||||
`Exit code was ${exitCode} and error was: ${error.trim()}`);
|
||||
`Exit code was ${exitCode}${error} See the logs for more details.`);
|
||||
this.exitCode = exitCode;
|
||||
this.error = error;
|
||||
this.output = output;
|
||||
this.stderr = stderr;
|
||||
this.stdout = stdout;
|
||||
}
|
||||
}
|
||||
exports.CommandInvocationError = CommandInvocationError;
|
||||
|
|
@ -775,7 +785,6 @@ async function runTool(cmd, args = [], opts = {}) {
|
|||
...(opts.stdin ? { input: Buffer.from(opts.stdin || "") } : {}),
|
||||
}).exec();
|
||||
if (exitCode !== 0) {
|
||||
error = extractFatalErrors(error) || error;
|
||||
throw new CommandInvocationError(cmd, args, exitCode, error, output);
|
||||
}
|
||||
return output;
|
||||
|
|
@ -956,7 +965,7 @@ function isNoCodeFoundError(e) {
|
|||
* This can be removed once support for CodeQL 2.11.6 is removed.
|
||||
*/
|
||||
const javascriptNoCodeFoundWarning = "No JavaScript or TypeScript code found.";
|
||||
return e.exitCode === 32 || e.error.includes(javascriptNoCodeFoundWarning);
|
||||
return e.exitCode === 32 || e.stderr.includes(javascriptNoCodeFoundWarning);
|
||||
}
|
||||
async function isDiagnosticsExportInvalidSarifFixed(codeql) {
|
||||
return await util.codeQlVersionAbove(codeql, exports.CODEQL_VERSION_DIAGNOSTICS_EXPORT_FIXED);
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
16
lib/codeql.test.js
generated
16
lib/codeql.test.js
generated
|
|
@ -695,7 +695,7 @@ for (const { featureEnabled, codeqlVersion, flagPassed, negativeFlagPassed, } of
|
|||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
await t.throwsAsync(async () => await codeqlObject.finalizeDatabase("db", "--threads=2", "--ram=2048"), {
|
||||
message: 'Encountered a fatal error while running "codeql-for-testing database finalize --finalize-dataset --threads=2 --ram=2048 db". ' +
|
||||
`Exit code was 32 and error was: ${cliMessage}`,
|
||||
`Exit code was 32 and last log line was: ${cliMessage} See the logs for more details.`,
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("runTool summarizes several fatal errors", async (t) => {
|
||||
|
|
@ -710,7 +710,19 @@ for (const { featureEnabled, codeqlVersion, flagPassed, negativeFlagPassed, } of
|
|||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
await t.throwsAsync(async () => await codeqlObject.finalizeDatabase("db", "--threads=2", "--ram=2048"), {
|
||||
message: 'Encountered a fatal error while running "codeql-for-testing database finalize --finalize-dataset --threads=2 --ram=2048 db". ' +
|
||||
`Exit code was 32 and error was: ${datasetImportError}. Context: ${heapError}.`,
|
||||
`Exit code was 32 and error was: ${datasetImportError}. Context: ${heapError}. See the logs for more details.`,
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("runTool outputs last line of stderr if fatal error could not be found", async (t) => {
|
||||
const cliStderr = "line1\nline2\nline3\nline4\nline5";
|
||||
stubToolRunnerConstructor(32, cliStderr);
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves((0, testing_utils_1.makeVersionInfo)("2.12.4"));
|
||||
// safeWhich throws because of the test CodeQL object.
|
||||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
await t.throwsAsync(async () => await codeqlObject.finalizeDatabase("db", "--threads=2", "--ram=2048"), {
|
||||
message: 'Encountered a fatal error while running "codeql-for-testing database finalize --finalize-dataset --threads=2 --ram=2048 db". ' +
|
||||
"Exit code was 32 and last log line was: line5. See the logs for more details.",
|
||||
});
|
||||
});
|
||||
function stubToolRunnerConstructor(exitCode = 0, stderr) {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -394,14 +394,10 @@ export async function runQueries(
|
|||
await runPrintLinesOfCode(language);
|
||||
}
|
||||
} catch (e) {
|
||||
logger.info(String(e));
|
||||
if (e instanceof Error) {
|
||||
logger.info(e.stack!);
|
||||
}
|
||||
statusReport.analyze_failure_language = language;
|
||||
throw new CodeQLAnalysisError(
|
||||
statusReport,
|
||||
`Error running analysis for ${language}: ${e}`,
|
||||
`Error running analysis for ${language}: ${util.wrapError(e).message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1133,7 +1133,7 @@ test("database finalize does not override no code found error on CodeQL 2.12.4",
|
|||
{
|
||||
message:
|
||||
'Encountered a fatal error while running "codeql-for-testing database finalize --finalize-dataset --threads=2 --ram=2048 db". ' +
|
||||
`Exit code was 32 and error was: ${cliMessage}`,
|
||||
`Exit code was 32 and last log line was: ${cliMessage} See the logs for more details.`,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
@ -1158,7 +1158,26 @@ test("runTool summarizes several fatal errors", async (t) => {
|
|||
{
|
||||
message:
|
||||
'Encountered a fatal error while running "codeql-for-testing database finalize --finalize-dataset --threads=2 --ram=2048 db". ' +
|
||||
`Exit code was 32 and error was: ${datasetImportError}. Context: ${heapError}.`,
|
||||
`Exit code was 32 and error was: ${datasetImportError}. Context: ${heapError}. See the logs for more details.`,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test("runTool outputs last line of stderr if fatal error could not be found", async (t) => {
|
||||
const cliStderr = "line1\nline2\nline3\nline4\nline5";
|
||||
stubToolRunnerConstructor(32, cliStderr);
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.12.4"));
|
||||
// safeWhich throws because of the test CodeQL object.
|
||||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
|
||||
await t.throwsAsync(
|
||||
async () =>
|
||||
await codeqlObject.finalizeDatabase("db", "--threads=2", "--ram=2048"),
|
||||
{
|
||||
message:
|
||||
'Encountered a fatal error while running "codeql-for-testing database finalize --finalize-dataset --threads=2 --ram=2048 db". ' +
|
||||
"Exit code was 32 and last log line was: line5. See the logs for more details.",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -54,15 +54,27 @@ export class CommandInvocationError extends Error {
|
|||
cmd: string,
|
||||
args: string[],
|
||||
public exitCode: number,
|
||||
public error: string,
|
||||
public output: string,
|
||||
public stderr: string,
|
||||
public stdout: string,
|
||||
) {
|
||||
const prettyCommand = [cmd, ...args]
|
||||
.map((x) => (x.includes(" ") ? `'${x}'` : x))
|
||||
.join(" ");
|
||||
|
||||
const fatalErrors = extractFatalErrors(stderr);
|
||||
const lastLine = stderr.trim().split("\n").pop()?.trim();
|
||||
let error = fatalErrors
|
||||
? ` and error was: ${fatalErrors.trim()}`
|
||||
: lastLine
|
||||
? ` and last log line was: ${lastLine}`
|
||||
: "";
|
||||
if (error[error.length - 1] !== ".") {
|
||||
error += ".";
|
||||
}
|
||||
|
||||
super(
|
||||
`Encountered a fatal error while running "${prettyCommand}". ` +
|
||||
`Exit code was ${exitCode} and error was: ${error.trim()}`,
|
||||
`Exit code was ${exitCode}${error} See the logs for more details.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1238,7 +1250,6 @@ async function runTool(
|
|||
...(opts.stdin ? { input: Buffer.from(opts.stdin || "") } : {}),
|
||||
}).exec();
|
||||
if (exitCode !== 0) {
|
||||
error = extractFatalErrors(error) || error;
|
||||
throw new CommandInvocationError(cmd, args, exitCode, error, output);
|
||||
}
|
||||
return output;
|
||||
|
|
@ -1454,7 +1465,7 @@ function isNoCodeFoundError(e: CommandInvocationError): boolean {
|
|||
*/
|
||||
const javascriptNoCodeFoundWarning =
|
||||
"No JavaScript or TypeScript code found.";
|
||||
return e.exitCode === 32 || e.error.includes(javascriptNoCodeFoundWarning);
|
||||
return e.exitCode === 32 || e.stderr.includes(javascriptNoCodeFoundWarning);
|
||||
}
|
||||
|
||||
async function isDiagnosticsExportInvalidSarifFixed(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue