Skip to content

Commit 76b2afa

Browse files
committed
Display the CLI's no code found error for CodeQL 2.12.4+
1 parent ce84bed commit 76b2afa

12 files changed

+141
-59
lines changed

lib/codeql.js

Lines changed: 32 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/codeql.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/codeql.test.js

Lines changed: 26 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/codeql.test.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/error-matcher.js

Lines changed: 0 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/error-matcher.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/error-matcher.test.js

Lines changed: 0 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/error-matcher.test.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/codeql.test.ts

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as fs from "fs";
22
import path from "path";
33

4+
import { ExecOptions } from "@actions/exec";
45
import * as toolrunner from "@actions/exec/lib/toolrunner";
56
import * as toolcache from "@actions/tool-cache";
67
import * as safeWhich from "@chrisgavin/safe-which";
@@ -1133,13 +1134,45 @@ for (const {
11331134
});
11341135
}
11351136

1136-
export function stubToolRunnerConstructor(): sinon.SinonStub<
1137-
any[],
1138-
toolrunner.ToolRunner
1139-
> {
1137+
test("database finalize recognises JavaScript no code found error on CodeQL 2.11.6", async (t) => {
1138+
stubToolRunnerConstructor(
1139+
1,
1140+
`2020-09-07T17:39:53.9050522Z [2020-09-07 17:39:53] [build] Done extracting /opt/hostedtoolcache/CodeQL/0.0.0-20200630/x64/codeql/javascript/tools/data/externs/web/ie_vml.js (3 ms)
1141+
2020-09-07T17:39:53.9051849Z [2020-09-07 17:39:53] [build-err] No JavaScript or TypeScript code found.
1142+
2020-09-07T17:39:53.9052444Z [2020-09-07 17:39:53] [build-err] No JavaScript or TypeScript code found.
1143+
2020-09-07T17:39:53.9251124Z [2020-09-07 17:39:53] [ERROR] Spawned process exited abnormally (code 255; tried to run: [/opt/hostedtoolcache/CodeQL/0.0.0-20200630/x64/codeql/javascript/tools/autobuild.sh])`
1144+
);
1145+
const codeqlObject = await codeql.getCodeQLForTesting();
1146+
sinon.stub(codeqlObject, "getVersion").resolves("2.11.6");
1147+
// safeWhich throws because of the test CodeQL object.
1148+
sinon.stub(safeWhich, "safeWhich").resolves("");
1149+
1150+
await t.throwsAsync(
1151+
async () => await codeqlObject.finalizeDatabase("", "", ""),
1152+
{
1153+
message:
1154+
"No code found during the build. Please see: " +
1155+
"https://gh.io/troubleshooting-code-scanning/no-source-code-seen-during-build",
1156+
}
1157+
);
1158+
});
1159+
1160+
export function stubToolRunnerConstructor(
1161+
exitCode: number = 0,
1162+
stderr?: string
1163+
): sinon.SinonStub<any[], toolrunner.ToolRunner> {
11401164
const runnerObjectStub = sinon.createStubInstance(toolrunner.ToolRunner);
1141-
runnerObjectStub.exec.resolves(0);
11421165
const runnerConstructorStub = sinon.stub(toolrunner, "ToolRunner");
1143-
runnerConstructorStub.returns(runnerObjectStub);
1166+
let stderrListener: ((data: Buffer) => void) | undefined = undefined;
1167+
runnerConstructorStub.callsFake((_cmd, _args, options: ExecOptions) => {
1168+
stderrListener = options.listeners?.stderr;
1169+
return runnerObjectStub;
1170+
});
1171+
runnerObjectStub.exec.callsFake(async () => {
1172+
if (stderrListener !== undefined && stderr !== undefined) {
1173+
stderrListener(Buffer.from(stderr));
1174+
}
1175+
return exitCode;
1176+
});
11441177
return runnerConstructorStub;
11451178
}

src/codeql.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ export class CommandInvocationError extends Error {
4949
constructor(
5050
cmd: string,
5151
args: string[],
52-
exitCode: number,
53-
error: string,
52+
public exitCode: number,
53+
public error: string,
5454
public output: string
5555
) {
5656
super(
@@ -307,6 +307,12 @@ export const CODEQL_VERSION_EXPORT_CODE_SCANNING_CONFIG = "2.12.3";
307307
*/
308308
export const CODEQL_VERSION_INIT_WITH_QLCONFIG = "2.12.4";
309309

310+
/**
311+
* Versions 2.12.4+ of the CodeQL CLI provide a better error message when `database finalize`
312+
* determines that no code has been found.
313+
*/
314+
export const CODEQL_VERSION_BETTER_NO_CODE_ERROR_MESSAGE = "2.12.4";
315+
310316
/**
311317
* Versions 2.13.4+ of the CodeQL CLI support the `resolve build-environment` command.
312318
*/
@@ -649,7 +655,24 @@ export async function getCodeQLForCmd(
649655
...getExtraOptionsFromEnv(["database", "finalize"]),
650656
databasePath,
651657
];
652-
await toolrunnerErrorCatcher(cmd, args, errorMatchers);
658+
try {
659+
await runTool(cmd, args);
660+
} catch (e) {
661+
if (
662+
e instanceof CommandInvocationError &&
663+
!(await util.codeQlVersionAbove(
664+
this,
665+
CODEQL_VERSION_BETTER_NO_CODE_ERROR_MESSAGE
666+
)) &&
667+
isNoCodeFoundError(e)
668+
) {
669+
throw new util.UserError(
670+
"No code found during the build. Please see: " +
671+
"https://gh.io/troubleshooting-code-scanning/no-source-code-seen-during-build"
672+
);
673+
}
674+
throw e;
675+
}
653676
},
654677
async resolveLanguages() {
655678
const codeqlArgs = [
@@ -1292,3 +1315,17 @@ export async function getTrapCachingExtractorConfigArgsForLang(
12921315
export function getGeneratedCodeScanningConfigPath(config: Config): string {
12931316
return path.resolve(config.tempDir, "user-config.yaml");
12941317
}
1318+
1319+
function isNoCodeFoundError(e: CommandInvocationError): boolean {
1320+
/**
1321+
* Earlier versions of the JavaScript extractor (pre-CodeQL 2.12.0) extract externs even if no
1322+
* source code was found. This means that we don't get the no code found error from
1323+
* `codeql database finalize`. To ensure users get a good error message, we detect this manually
1324+
* here, and upon detection override the error message.
1325+
*
1326+
* This can be removed once support for CodeQL 2.11.6 is removed.
1327+
*/
1328+
const javascriptNoCodeFoundWarning =
1329+
"No JavaScript or TypeScript code found.";
1330+
return e.exitCode === 32 || e.error.includes(javascriptNoCodeFoundWarning);
1331+
}

0 commit comments

Comments
 (0)