Skip to content

Commit

Permalink
Display the CLI's no code found error for CodeQL 2.12.4+
Browse files Browse the repository at this point in the history
  • Loading branch information
Henry Mercer committed Jul 20, 2023
1 parent ce84bed commit 76b2afa
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 59 deletions.
34 changes: 32 additions & 2 deletions lib/codeql.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/codeql.js.map

Large diffs are not rendered by default.

29 changes: 26 additions & 3 deletions lib/codeql.test.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/codeql.test.js.map

Large diffs are not rendered by default.

9 changes: 0 additions & 9 deletions lib/error-matcher.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/error-matcher.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 0 additions & 8 deletions lib/error-matcher.test.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/error-matcher.test.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 39 additions & 6 deletions src/codeql.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as fs from "fs";
import path from "path";

import { ExecOptions } from "@actions/exec";
import * as toolrunner from "@actions/exec/lib/toolrunner";
import * as toolcache from "@actions/tool-cache";
import * as safeWhich from "@chrisgavin/safe-which";
Expand Down Expand Up @@ -1133,13 +1134,45 @@ for (const {
});
}

export function stubToolRunnerConstructor(): sinon.SinonStub<
any[],
toolrunner.ToolRunner
> {
test("database finalize recognises JavaScript no code found error on CodeQL 2.11.6", async (t) => {
stubToolRunnerConstructor(
1,
`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)
2020-09-07T17:39:53.9051849Z [2020-09-07 17:39:53] [build-err] No JavaScript or TypeScript code found.
2020-09-07T17:39:53.9052444Z [2020-09-07 17:39:53] [build-err] No JavaScript or TypeScript code found.
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])`
);
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves("2.11.6");
// safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves("");

await t.throwsAsync(
async () => await codeqlObject.finalizeDatabase("", "", ""),
{
message:
"No code found during the build. Please see: " +
"https://gh.io/troubleshooting-code-scanning/no-source-code-seen-during-build",
}
);
});

export function stubToolRunnerConstructor(
exitCode: number = 0,
stderr?: string
): sinon.SinonStub<any[], toolrunner.ToolRunner> {
const runnerObjectStub = sinon.createStubInstance(toolrunner.ToolRunner);
runnerObjectStub.exec.resolves(0);
const runnerConstructorStub = sinon.stub(toolrunner, "ToolRunner");
runnerConstructorStub.returns(runnerObjectStub);
let stderrListener: ((data: Buffer) => void) | undefined = undefined;
runnerConstructorStub.callsFake((_cmd, _args, options: ExecOptions) => {
stderrListener = options.listeners?.stderr;
return runnerObjectStub;
});
runnerObjectStub.exec.callsFake(async () => {
if (stderrListener !== undefined && stderr !== undefined) {
stderrListener(Buffer.from(stderr));
}
return exitCode;
});
return runnerConstructorStub;
}
43 changes: 40 additions & 3 deletions src/codeql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ export class CommandInvocationError extends Error {
constructor(
cmd: string,
args: string[],
exitCode: number,
error: string,
public exitCode: number,
public error: string,
public output: string
) {
super(
Expand Down Expand Up @@ -307,6 +307,12 @@ export const CODEQL_VERSION_EXPORT_CODE_SCANNING_CONFIG = "2.12.3";
*/
export const CODEQL_VERSION_INIT_WITH_QLCONFIG = "2.12.4";

/**
* Versions 2.12.4+ of the CodeQL CLI provide a better error message when `database finalize`
* determines that no code has been found.
*/
export const CODEQL_VERSION_BETTER_NO_CODE_ERROR_MESSAGE = "2.12.4";

/**
* Versions 2.13.4+ of the CodeQL CLI support the `resolve build-environment` command.
*/
Expand Down Expand Up @@ -649,7 +655,24 @@ export async function getCodeQLForCmd(
...getExtraOptionsFromEnv(["database", "finalize"]),
databasePath,
];
await toolrunnerErrorCatcher(cmd, args, errorMatchers);
try {
await runTool(cmd, args);
} catch (e) {
if (
e instanceof CommandInvocationError &&
!(await util.codeQlVersionAbove(
this,
CODEQL_VERSION_BETTER_NO_CODE_ERROR_MESSAGE
)) &&
isNoCodeFoundError(e)
) {
throw new util.UserError(
"No code found during the build. Please see: " +
"https://gh.io/troubleshooting-code-scanning/no-source-code-seen-during-build"
);
}
throw e;
}
},
async resolveLanguages() {
const codeqlArgs = [
Expand Down Expand Up @@ -1292,3 +1315,17 @@ export async function getTrapCachingExtractorConfigArgsForLang(
export function getGeneratedCodeScanningConfigPath(config: Config): string {
return path.resolve(config.tempDir, "user-config.yaml");
}

function isNoCodeFoundError(e: CommandInvocationError): boolean {
/**
* Earlier versions of the JavaScript extractor (pre-CodeQL 2.12.0) extract externs even if no
* source code was found. This means that we don't get the no code found error from
* `codeql database finalize`. To ensure users get a good error message, we detect this manually
* here, and upon detection override the error message.
*
* 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);
}
14 changes: 0 additions & 14 deletions src/error-matcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,6 @@ import { namedMatchersForTesting } from "./error-matcher";
NB We test the regexes for all the matchers against example log output snippets.
*/

test("noSourceCodeFound matches against example javascript output", async (t) => {
t.assert(
testErrorMatcher(
"noSourceCodeFound",
`
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)
2020-09-07T17:39:53.9051849Z [2020-09-07 17:39:53] [build-err] No JavaScript or TypeScript code found.
2020-09-07T17:39:53.9052444Z [2020-09-07 17:39:53] [build-err] No JavaScript or TypeScript code found.
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])
`
)
);
});

test("fatalError matches against example log output", async (t) => {
t.assert(
testErrorMatcher(
Expand Down
10 changes: 0 additions & 10 deletions src/error-matcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,6 @@ export interface ErrorMatcher {

// exported only for testing purposes
export const namedMatchersForTesting: { [key: string]: ErrorMatcher } = {
/*
In due course it may be possible to remove the regex, if/when javascript also exits with code 32.
*/
noSourceCodeFound: {
exitCode: 32,
outputRegex: new RegExp("No JavaScript or TypeScript code found\\."),
message:
"No code found during the build. Please see:\n" +
"https://gh.io/troubleshooting-code-scanning/no-source-code-seen-during-build",
},
fatalError: {
outputRegex: new RegExp("A fatal error occurred"),
message: "A fatal error occurred.",
Expand Down

0 comments on commit 76b2afa

Please sign in to comment.