diff --git a/lib/entry-points.js b/lib/entry-points.js index 93a4d0ed58..2908798b2f 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -150466,16 +150466,13 @@ async function getCodeQLForCmd(cmd, checkVersion) { async getVersion() { let result = getCachedCodeQlVersion(cmd); if (result === void 0) { - const output = await runCli(cmd, ["version", "--format=json"], { - noStreamStdout: true - }); - try { - result = JSON.parse(output); - } catch { - throw Error( - `Invalid JSON output from \`version --format=json\`: ${output}` - ); - } + result = await runCliJson( + cmd, + ["version", "--format=json"], + { + noStreamStdout: true + } + ); cacheCodeQlVersion(cmd, result); } return result; @@ -150635,23 +150632,18 @@ async function getCodeQLForCmd(cmd, checkVersion) { async resolveLanguages({ filterToLanguagesWithQueries } = { filterToLanguagesWithQueries: false }) { - const codeqlArgs = [ + return runCliJson(cmd, [ "resolve", "languages", "--format=betterjson", "--extractor-options-verbosity=4", "--extractor-include-aliases", + // TODO: Unconditionally include `--filter-to-languages-with-queries` + // once CODEQL_MINIMUM_VERSION is at least v2.23.0 + // — the first version to support this flag. ...filterToLanguagesWithQueries ? ["--filter-to-languages-with-queries"] : [], ...getExtraOptionsFromEnv(["resolve", "languages"]) - ]; - const output = await runCli(cmd, codeqlArgs); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve languages with --format=betterjson: ${e}` - ); - } + ]); }, async resolveBuildEnvironment(workingDir, language) { const codeqlArgs = [ @@ -150664,15 +150656,7 @@ async function getCodeQLForCmd(cmd, checkVersion) { if (workingDir !== void 0) { codeqlArgs.push("--working-dir", workingDir); } - const output = await runCli(cmd, codeqlArgs); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve build-environment: ${e} in -${output}` - ); - } + return await runCliJson(cmd, codeqlArgs); }, async databaseRunQueries(databasePath, flags, queries = []) { const codeqlArgs = [ @@ -150838,14 +150822,9 @@ ${output}` ...getExtraOptionsFromEnv(["resolve", "queries"]), ...queries ]; - const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve queries --format=startingpacks: ${e}` - ); - } + return await runCliJson(cmd, codeqlArgs, { + noStreamStdout: true + }); }, async resolveDatabase(databasePath) { const codeqlArgs = [ @@ -150855,14 +150834,9 @@ ${output}` "--format=json", ...getExtraOptionsFromEnv(["resolve", "database"]) ]; - const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve database --format=json: ${e}` - ); - } + return await runCliJson(cmd, codeqlArgs, { + noStreamStdout: true + }); }, async mergeResults(sarifFiles, outputFile, { mergeRunsFromEqualCategory = false @@ -150944,6 +150918,16 @@ async function runCli(cmd, args = [], opts = {}) { throw e; } } +async function runCliJson(cmd, args = [], opts = {}) { + const output = await runCli(cmd, args, opts); + try { + return JSON.parse(output); + } catch (e) { + throw Error( + `Unexpected output from codeql ${args.join(" ")}: ${getErrorMessage(e)}` + ); + } +} async function writeCodeScanningConfigFile(config, logger) { const codeScanningConfigFile = getGeneratedCodeScanningConfigPath(config); const augmentedConfig = appendExtraQueryExclusions( diff --git a/src/codeql.ts b/src/codeql.ts index 5d78337d2e..bb6c0fb55b 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -514,16 +514,13 @@ async function getCodeQLForCmd( async getVersion() { let result = util.getCachedCodeQlVersion(cmd); if (result === undefined) { - const output = await runCli(cmd, ["version", "--format=json"], { - noStreamStdout: true, - }); - try { - result = JSON.parse(output) as VersionInfo; - } catch { - throw Error( - `Invalid JSON output from \`version --format=json\`: ${output}`, - ); - } + result = await runCliJson( + cmd, + ["version", "--format=json"], + { + noStreamStdout: true, + }, + ); util.cacheCodeQlVersion(cmd, result); } return result; @@ -731,26 +728,20 @@ async function getCodeQLForCmd( filterToLanguagesWithQueries: boolean; } = { filterToLanguagesWithQueries: false }, ) { - const codeqlArgs = [ + return runCliJson(cmd, [ "resolve", "languages", "--format=betterjson", "--extractor-options-verbosity=4", "--extractor-include-aliases", + // TODO: Unconditionally include `--filter-to-languages-with-queries` + // once CODEQL_MINIMUM_VERSION is at least v2.23.0 + // — the first version to support this flag. ...(filterToLanguagesWithQueries ? ["--filter-to-languages-with-queries"] : []), ...getExtraOptionsFromEnv(["resolve", "languages"]), - ]; - const output = await runCli(cmd, codeqlArgs); - - try { - return JSON.parse(output) as ResolveLanguagesOutput; - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve languages with --format=betterjson: ${e}`, - ); - } + ]); }, async resolveBuildEnvironment( workingDir: string | undefined, @@ -766,15 +757,7 @@ async function getCodeQLForCmd( if (workingDir !== undefined) { codeqlArgs.push("--working-dir", workingDir); } - const output = await runCli(cmd, codeqlArgs); - - try { - return JSON.parse(output) as ResolveBuildEnvironmentOutput; - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve build-environment: ${e} in\n${output}`, - ); - } + return await runCliJson(cmd, codeqlArgs); }, async databaseRunQueries( databasePath: string, @@ -976,15 +959,9 @@ async function getCodeQLForCmd( ...getExtraOptionsFromEnv(["resolve", "queries"]), ...queries, ]; - const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); - - try { - return JSON.parse(output) as string[]; - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve queries --format=startingpacks: ${e}`, - ); - } + return await runCliJson(cmd, codeqlArgs, { + noStreamStdout: true, + }); }, async resolveDatabase( databasePath: string, @@ -996,15 +973,9 @@ async function getCodeQLForCmd( "--format=json", ...getExtraOptionsFromEnv(["resolve", "database"]), ]; - const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); - - try { - return JSON.parse(output) as ResolveDatabaseOutput; - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve database --format=json: ${e}`, - ); - } + return await runCliJson(cmd, codeqlArgs, { + noStreamStdout: true, + }); }, async mergeResults( sarifFiles: string[], @@ -1160,6 +1131,30 @@ async function runCli( } } +/** + * Wraps the command executor {@link runCli} and tries to parse the output as JSON. + * @param cmd The command to run. + * @param args The arguments to pass to the command. + * @param opts The options for running the command. + * @param opts.stdin Optional string to pass to the command's standard input. + * @param opts.noStreamStdout Optional boolean to indicate whether to stream the command's standard output. + * @returns The parsed JSON output from the command. + */ +async function runCliJson( + cmd: string, + args: string[] = [], + opts: { stdin?: string; noStreamStdout?: boolean } = {}, +): Promise { + const output = await runCli(cmd, args, opts); + try { + return JSON.parse(output) as T; + } catch (e) { + throw Error( + `Unexpected output from codeql ${args.join(" ")}: ${getErrorMessage(e)}`, + ); + } +} + /** * Writes the code scanning configuration that is to be used by the CLI. *