Refactor: Pull out generic tool invocation functionality

This commit is contained in:
Henry Mercer
2024-10-01 14:39:04 +01:00
parent cf5b0a9041
commit 1aa7f6f05d
15 changed files with 256 additions and 177 deletions

84
lib/codeql.js generated
View File

@@ -241,7 +241,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
async getVersion() {
let result = util.getCachedCodeQlVersion();
if (result === undefined) {
const output = await runTool(cmd, ["version", "--format=json"]);
const output = await runCli(cmd, ["version", "--format=json"]);
try {
result = JSON.parse(output);
}
@@ -253,7 +253,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
return result;
},
async printVersion() {
await runTool(cmd, ["version", "--format=json"]);
await runCli(cmd, ["version", "--format=json"]);
},
async supportsFeature(feature) {
return (0, tools_features_1.isSupportedToolsFeature)(await this.getVersion(), feature);
@@ -290,7 +290,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
const overwriteFlag = (0, tools_features_1.isSupportedToolsFeature)(await this.getVersion(), tools_features_1.ToolsFeature.ForceOverwrite)
? "--force-overwrite"
: "--overwrite";
await runTool(cmd, [
await runCli(cmd, [
"database",
"init",
overwriteFlag,
@@ -325,10 +325,10 @@ async function getCodeQLForCmd(cmd, checkVersion) {
// When `DYLD_INSERT_LIBRARIES` is set in the environment for a step,
// the Actions runtime introduces its own workaround for SIP
// (https://github.com/actions/runner/pull/416).
await runTool(autobuildCmd);
await runCli(autobuildCmd);
},
async extractScannedLanguage(config, language) {
await runTool(cmd, [
await runCli(cmd, [
"database",
"trace-command",
"--index-traceless-dbs",
@@ -343,7 +343,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
applyAutobuildAzurePipelinesTimeoutFix();
}
try {
await runTool(cmd, [
await runCli(cmd, [
"database",
"trace-command",
"--use-build-mode",
@@ -378,7 +378,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
...getExtraOptionsFromEnv(["database", "finalize"]),
databasePath,
];
await runTool(cmd, args);
await runCli(cmd, args);
},
async resolveLanguages() {
const codeqlArgs = [
@@ -387,7 +387,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
"--format=json",
...getExtraOptionsFromEnv(["resolve", "languages"]),
];
const output = await runTool(cmd, codeqlArgs);
const output = await runCli(cmd, codeqlArgs);
try {
return JSON.parse(output);
}
@@ -404,7 +404,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
...(await getLanguageAliasingArguments(this)),
...getExtraOptionsFromEnv(["resolve", "languages"]),
];
const output = await runTool(cmd, codeqlArgs);
const output = await runCli(cmd, codeqlArgs);
try {
return JSON.parse(output);
}
@@ -423,7 +423,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
if (extraSearchPath !== undefined) {
codeqlArgs.push("--additional-packs", extraSearchPath);
}
const output = await runTool(cmd, codeqlArgs);
const output = await runCli(cmd, codeqlArgs);
try {
return JSON.parse(output);
}
@@ -442,7 +442,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
if (workingDir !== undefined) {
codeqlArgs.push("--working-dir", workingDir);
}
const output = await runTool(cmd, codeqlArgs);
const output = await runCli(cmd, codeqlArgs);
try {
return JSON.parse(output);
}
@@ -466,7 +466,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
if (await util.codeQlVersionAtLeast(this, feature_flags_1.CODEQL_VERSION_FINE_GRAINED_PARALLELISM)) {
codeqlArgs.push("--intra-layer-parallelism");
}
await runTool(cmd, codeqlArgs);
await runCli(cmd, codeqlArgs);
},
async databaseInterpretResults(databasePath, querySuitePaths, sarifFile, addSnippetsFlag, threadsFlag, verbosityFlag, automationDetailsId, config, features) {
const shouldExportDiagnostics = await features.getValue(feature_flags_1.Feature.ExportDiagnosticsEnabled, this);
@@ -512,7 +512,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
}
// Capture the stdout, which contains the analysis summary. Don't stream it to the Actions
// logs to avoid printing it twice.
return await runTool(cmd, codeqlArgs, {
return await runCli(cmd, codeqlArgs, {
noStreamStdout: true,
});
},
@@ -523,7 +523,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
...getExtraOptionsFromEnv(["database", "print-baseline"]),
databasePath,
];
return await runTool(cmd, codeqlArgs);
return await runCli(cmd, codeqlArgs);
},
/**
* Download specified packs into the package cache. If the specified
@@ -551,7 +551,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
...getExtraOptionsFromEnv(["pack", "download"]),
...packs,
];
const output = await runTool(cmd, codeqlArgs);
const output = await runCli(cmd, codeqlArgs);
try {
const parsedOutput = JSON.parse(output);
if (Array.isArray(parsedOutput.packs) &&
@@ -580,7 +580,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
`${cacheCleanupFlag}=${cleanupLevel}`,
...getExtraOptionsFromEnv(["database", "cleanup"]),
];
await runTool(cmd, codeqlArgs);
await runCli(cmd, codeqlArgs);
},
async databaseBundle(databasePath, outputFilePath, databaseName) {
const args = [
@@ -662,7 +662,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
if (mergeRunsFromEqualCategory) {
args.push("--sarif-merge-runs-from-equal-category");
}
await runTool(cmd, args);
await runCli(cmd, args);
},
};
// To ensure that status reports include the CodeQL CLI version wherever
@@ -742,48 +742,16 @@ function getExtraOptions(options, paths, pathInfo) {
: getExtraOptions(options?.[paths[0]], paths?.slice(1), pathInfo.concat(paths[0]));
return all.concat(specific);
}
/*
* A constant defining the maximum number of characters we will keep from
* the programs stderr for logging. This serves two purposes:
* (1) It avoids an OOM if a program fails in a way that results it
* printing many log lines.
* (2) It avoids us hitting the limit of how much data we can send in our
* status reports on GitHub.com.
*/
const maxErrorSize = 20_000;
async function runTool(cmd, args = [], opts = {}) {
let stdout = "";
let stderr = "";
process.stdout.write(`[command]${cmd} ${args.join(" ")}\n`);
const exitCode = await new toolrunner.ToolRunner(cmd, args, {
ignoreReturnCode: true,
listeners: {
stdout: (data) => {
stdout += data.toString("utf8");
if (!opts.noStreamStdout) {
process.stdout.write(data);
}
},
stderr: (data) => {
let readStartIndex = 0;
// If the error is too large, then we only take the last 20,000 characters
if (data.length - maxErrorSize > 0) {
// Eg: if we have 20,000 the start index should be 2.
readStartIndex = data.length - maxErrorSize + 1;
}
stderr += data.toString("utf8", readStartIndex);
// Mimic the standard behavior of the toolrunner by writing stderr to stdout
process.stdout.write(data);
},
},
silent: true,
...(opts.stdin ? { input: Buffer.from(opts.stdin || "") } : {}),
}).exec();
if (exitCode !== 0) {
const e = new cli_errors_1.CommandInvocationError(cmd, args, exitCode, stderr, stdout);
throw (0, cli_errors_1.wrapCliConfigurationError)(e);
async function runCli(cmd, args = [], opts = {}) {
try {
return await (0, actions_util_1.runTool)(cmd, args, opts);
}
catch (e) {
if (e instanceof actions_util_1.CommandInvocationError) {
throw (0, cli_errors_1.wrapCliConfigurationError)(new cli_errors_1.CliError(e));
}
throw e;
}
return stdout;
}
/**
* Generates a code scanning configuration that is to be used for a scan.