Allow the codeql-action to run packages

This commit adds a `packs` option to the codeql-config.yml file. Users
can specify a list of ql packs to include in the analysis.

For a single language analysis, the packs property looks like this:

```yaml
packs:
  - pack-scope/pack-name1@1.2.3
  - pack-scope/pack-name2   # no explicit version means download the latest
```

For multi-language analysis, you must key the packs block by lanaguage:

```yaml
packs:
  cpp:
    - pack-scope/pack-name1@1.2.3
    - pack-scope/pack-name2
  java:
    - pack-scope/pack-name3@1.2.3
    - pack-scope/pack-name4
```

This implementation adds a new analysis run (alongside custom and 
builtin runs). The unit tests indicate that the correct commands are
being run, but I have not actually tried this with a real CLI.

Also, convert `instanceof Array` to `Array.isArray` since that is
sightly better in some situations. See:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray#instanceof_vs_isarray
This commit is contained in:
Andrew Eisenberg 2021-06-03 09:32:44 -07:00
parent cbdf0df97b
commit 86a804f9a7
22 changed files with 940 additions and 45 deletions

View file

@ -166,6 +166,7 @@ export async function runQueries(
logger.startGroup(`Analyzing ${language}`);
const queries = config.queries[language];
const packsWithVersion = config.packs[language] || [];
if (
queries === undefined ||
(queries.builtin.length === 0 && queries.custom.length === 0)
@ -183,7 +184,7 @@ export async function runQueries(
const { sarifFile, stdout } = await runQueryGroup(
language,
"builtin",
queries["builtin"],
createQuerySuiteContents(queries["builtin"]),
sarifFolder,
undefined
);
@ -201,7 +202,7 @@ export async function runQueries(
const { sarifFile, stdout } = await runQueryGroup(
language,
`custom-${i}`,
queries["custom"][i].queries,
createQuerySuiteContents(queries["custom"][i].queries),
temporarySarifDir,
queries["custom"][i].searchPath
);
@ -209,6 +210,17 @@ export async function runQueries(
temporarySarifFiles.push(sarifFile);
}
}
if (packsWithVersion.length > 0) {
const { sarifFile, stdout } = await runQueryGroup(
language,
"packs",
createPackSuiteContents(packsWithVersion),
temporarySarifDir,
undefined
);
customAnalysisSummaries.push(stdout);
temporarySarifFiles.push(sarifFile);
}
if (temporarySarifFiles.length > 0) {
const sarifFile = path.join(sarifFolder, `${language}-custom.sarif`);
fs.writeFileSync(sarifFile, combineSarifFiles(temporarySarifFiles));
@ -256,7 +268,7 @@ export async function runQueries(
async function runQueryGroup(
language: Language,
type: string,
queries: string[],
querySuiteContents: string,
destinationFolder: string,
searchPath: string | undefined
): Promise<{ sarifFile: string; stdout: string }> {
@ -264,11 +276,10 @@ export async function runQueries(
// Pass the queries to codeql using a file instead of using the command
// line to avoid command line length restrictions, particularly on windows.
const querySuitePath = `${databasePath}-queries-${type}.qls`;
const querySuiteContents = queries
.map((q: string) => `- query: ${q}`)
.join("\n");
fs.writeFileSync(querySuitePath, querySuiteContents);
logger.debug(`Query suite file for ${language}...\n${querySuiteContents}`);
logger.debug(
`Query suite file for ${language}-${type}...\n${querySuiteContents}`
);
const sarifFile = path.join(destinationFolder, `${language}-${type}.sarif`);
@ -291,6 +302,26 @@ export async function runQueries(
}
}
function createQuerySuiteContents(queries: string[]) {
return queries.map((q: string) => `- query: ${q}`).join("\n");
}
function createPackSuiteContents(
packsWithVersion: configUtils.PackWithVersion[]
) {
return packsWithVersion.map(packWithVersionToQuerySuiteEntry).join("\n");
}
function packWithVersionToQuerySuiteEntry(
pack: configUtils.PackWithVersion
): string {
let text = `- qlpack: ${pack.packName}`;
if (pack.version) {
text += `${"\n"} version: ${pack.version}`;
}
return text;
}
export async function runAnalyze(
outputDir: string,
memoryFlag: string,