Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Display the CLI's no code found error for CodeQL 2.12.4+
  • Loading branch information
henrymercer committed Jul 20, 2023
commit 76b2afaa4a6ae85e24a64e70957bb553ef3a02b3
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