From 6cdc6063c031308c200c6cc637e69b1af0ce2c40 Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Tue, 30 Jun 2026 22:55:24 -0500 Subject: [PATCH 1/4] Create wrapper `runCliJson` --- lib/entry-points.js | 72 +++++++++++++++------------------------- src/codeql.ts | 80 ++++++++++++++++++--------------------------- 2 files changed, 59 insertions(+), 93 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 93a4d0ed58..d55ecde940 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,14 @@ 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 { + throw Error(`Invalid JSON output from \`${args.join(" ")}\`: ${output}`); + } +} async function writeCodeScanningConfigFile(config, logger) { const codeScanningConfigFile = getGeneratedCodeScanningConfigPath(config); const augmentedConfig = appendExtraQueryExclusions( diff --git a/src/codeql.ts b/src/codeql.ts index 5d78337d2e..a6a52a659f 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,19 @@ async function runCli( } } +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 { + throw Error(`Invalid JSON output from \`${args.join(" ")}\`: ${output}`); + } +} + /** * Writes the code scanning configuration that is to be used by the CLI. * From 7d1c6e90aa51e277b6632cb8da85d148f1507e30 Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Tue, 30 Jun 2026 23:13:36 -0500 Subject: [PATCH 2/4] Include `codeql` path in `runCliJson` error --- lib/entry-points.js | 3 ++- src/codeql.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index d55ecde940..c43febeb1c 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -150923,7 +150923,8 @@ async function runCliJson(cmd, args = [], opts = {}) { try { return JSON.parse(output); } catch { - throw Error(`Invalid JSON output from \`${args.join(" ")}\`: ${output}`); + const command = [cmd, ...args].join(" "); + throw Error(`Invalid JSON output from \`${command}\`: ${output}`); } } async function writeCodeScanningConfigFile(config, logger) { diff --git a/src/codeql.ts b/src/codeql.ts index a6a52a659f..ba7dffb3a6 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -1140,7 +1140,8 @@ async function runCliJson( try { return JSON.parse(output) as T; } catch { - throw Error(`Invalid JSON output from \`${args.join(" ")}\`: ${output}`); + const command = [cmd, ...args].join(" "); + throw Error(`Invalid JSON output from \`${command}\`: ${output}`); } } From a8958a9883e8c21a7619ee9493b8b5022ba8b5cb Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Wed, 1 Jul 2026 11:12:08 -0500 Subject: [PATCH 3/4] Keep the JSON exception message consistent --- lib/entry-points.js | 7 ++++--- src/codeql.ts | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index c43febeb1c..2908798b2f 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -150922,9 +150922,10 @@ async function runCliJson(cmd, args = [], opts = {}) { const output = await runCli(cmd, args, opts); try { return JSON.parse(output); - } catch { - const command = [cmd, ...args].join(" "); - throw Error(`Invalid JSON output from \`${command}\`: ${output}`); + } catch (e) { + throw Error( + `Unexpected output from codeql ${args.join(" ")}: ${getErrorMessage(e)}` + ); } } async function writeCodeScanningConfigFile(config, logger) { diff --git a/src/codeql.ts b/src/codeql.ts index ba7dffb3a6..bf17dfebab 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -1139,9 +1139,10 @@ async function runCliJson( const output = await runCli(cmd, args, opts); try { return JSON.parse(output) as T; - } catch { - const command = [cmd, ...args].join(" "); - throw Error(`Invalid JSON output from \`${command}\`: ${output}`); + } catch (e) { + throw Error( + `Unexpected output from codeql ${args.join(" ")}: ${getErrorMessage(e)}`, + ); } } From d5b80463869b5d252374fd7fef10f1c3ccbebec2 Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Wed, 1 Jul 2026 11:18:02 -0500 Subject: [PATCH 4/4] Add JSDoc comment to `runCliJson` --- src/codeql.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/codeql.ts b/src/codeql.ts index bf17dfebab..bb6c0fb55b 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -1131,6 +1131,15 @@ 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[] = [],