Skip to content

Commit fe0376e

Browse files
committed
Add getGroupedSarifFilePaths with tests
1 parent 36adfa7 commit fe0376e

File tree

7 files changed

+225
-27
lines changed

7 files changed

+225
-27
lines changed

lib/analyze-action.js

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

lib/init-action-post.js

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

lib/upload-lib.js

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

lib/upload-sarif-action.js

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

src/analyses.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,9 @@ export const CodeQuality: AnalysisConfig = {
8686
sarifPredicate: (name) => name.endsWith(CodeQuality.sarifExtension),
8787
sentinelPrefix: "CODEQL_UPLOAD_QUALITY_SARIF_",
8888
};
89+
90+
// Since we have overlapping extensions (i.e. ".sarif" includes ".quality.sarif"),
91+
// we want to scan a folder containing SARIF files in an order that finds the more
92+
// specific extensions first. This constant defines an array in the order of analyis
93+
// configurations with more specific extensions to less specific extensions.
94+
export const SarifScanOrder = [CodeQuality, CodeScanning];

src/upload-lib.test.ts

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as path from "path";
33

44
import test from "ava";
55

6-
import { CodeQuality, CodeScanning } from "./analyses";
6+
import { AnalysisKind, CodeQuality, CodeScanning } from "./analyses";
77
import { getRunnerLogger, Logger } from "./logging";
88
import { setupTests } from "./testing-utils";
99
import * as uploadLib from "./upload-lib";
@@ -127,27 +127,97 @@ test("finding SARIF files", async (t) => {
127127
fs.writeFileSync(path.join(tmpDir, "a.quality.sarif"), "");
128128
fs.writeFileSync(path.join(tmpDir, "dir1", "b.quality.sarif"), "");
129129

130+
const expectedSarifFiles = [
131+
path.join(tmpDir, "a.sarif"),
132+
path.join(tmpDir, "b.sarif"),
133+
path.join(tmpDir, "dir1", "d.sarif"),
134+
path.join(tmpDir, "dir1", "dir2", "e.sarif"),
135+
];
130136
const sarifFiles = uploadLib.findSarifFilesInDir(
131137
tmpDir,
132138
CodeScanning.sarifPredicate,
133139
);
134140

135-
t.deepEqual(sarifFiles, [
136-
path.join(tmpDir, "a.sarif"),
137-
path.join(tmpDir, "b.sarif"),
138-
path.join(tmpDir, "dir1", "d.sarif"),
139-
path.join(tmpDir, "dir1", "dir2", "e.sarif"),
140-
]);
141+
t.deepEqual(sarifFiles, expectedSarifFiles);
141142

143+
const expectedQualitySarifFiles = [
144+
path.join(tmpDir, "a.quality.sarif"),
145+
path.join(tmpDir, "dir1", "b.quality.sarif"),
146+
];
142147
const qualitySarifFiles = uploadLib.findSarifFilesInDir(
143148
tmpDir,
144149
CodeQuality.sarifPredicate,
145150
);
146151

147-
t.deepEqual(qualitySarifFiles, [
148-
path.join(tmpDir, "a.quality.sarif"),
149-
path.join(tmpDir, "dir1", "b.quality.sarif"),
150-
]);
152+
t.deepEqual(qualitySarifFiles, expectedQualitySarifFiles);
153+
154+
const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths(
155+
getRunnerLogger(true),
156+
tmpDir,
157+
);
158+
159+
t.not(groupedSarifFiles, undefined);
160+
t.not(groupedSarifFiles[AnalysisKind.CodeScanning], undefined);
161+
t.not(groupedSarifFiles[AnalysisKind.CodeQuality], undefined);
162+
t.deepEqual(
163+
groupedSarifFiles[AnalysisKind.CodeScanning],
164+
expectedSarifFiles,
165+
);
166+
t.deepEqual(
167+
groupedSarifFiles[AnalysisKind.CodeQuality],
168+
expectedQualitySarifFiles,
169+
);
170+
});
171+
});
172+
173+
test("getGroupedSarifFilePaths - Code Quality file", async (t) => {
174+
await withTmpDir(async (tmpDir) => {
175+
const sarifPath = path.join(tmpDir, "a.quality.sarif");
176+
fs.writeFileSync(sarifPath, "");
177+
178+
const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths(
179+
getRunnerLogger(true),
180+
sarifPath,
181+
);
182+
183+
t.not(groupedSarifFiles, undefined);
184+
t.is(groupedSarifFiles[AnalysisKind.CodeScanning], undefined);
185+
t.not(groupedSarifFiles[AnalysisKind.CodeQuality], undefined);
186+
t.deepEqual(groupedSarifFiles[AnalysisKind.CodeQuality], [sarifPath]);
187+
});
188+
});
189+
190+
test("getGroupedSarifFilePaths - Code Scanning file", async (t) => {
191+
await withTmpDir(async (tmpDir) => {
192+
const sarifPath = path.join(tmpDir, "a.sarif");
193+
fs.writeFileSync(sarifPath, "");
194+
195+
const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths(
196+
getRunnerLogger(true),
197+
sarifPath,
198+
);
199+
200+
t.not(groupedSarifFiles, undefined);
201+
t.not(groupedSarifFiles[AnalysisKind.CodeScanning], undefined);
202+
t.is(groupedSarifFiles[AnalysisKind.CodeQuality], undefined);
203+
t.deepEqual(groupedSarifFiles[AnalysisKind.CodeScanning], [sarifPath]);
204+
});
205+
});
206+
207+
test("getGroupedSarifFilePaths - Other file", async (t) => {
208+
await withTmpDir(async (tmpDir) => {
209+
const sarifPath = path.join(tmpDir, "a.json");
210+
fs.writeFileSync(sarifPath, "");
211+
212+
const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths(
213+
getRunnerLogger(true),
214+
sarifPath,
215+
);
216+
217+
t.not(groupedSarifFiles, undefined);
218+
t.not(groupedSarifFiles[AnalysisKind.CodeScanning], undefined);
219+
t.is(groupedSarifFiles[AnalysisKind.CodeQuality], undefined);
220+
t.deepEqual(groupedSarifFiles[AnalysisKind.CodeScanning], [sarifPath]);
151221
});
152222
});
153223

src/upload-lib.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,68 @@ export function getSarifFilePaths(
459459
return sarifFiles;
460460
}
461461

462+
/**
463+
* Finds SARIF files in `sarifPath`, and groups them by analysis kind, following `SarifScanOrder`.
464+
*
465+
* @param logger The logger to use.
466+
* @param sarifPath The path of a file or directory to recursively scan for SARIF files.
467+
* @returns The `.sarif` files found in `sarifPath`, grouped by analysis kind.
468+
*/
469+
export async function getGroupedSarifFilePaths(
470+
logger: Logger,
471+
sarifPath: string,
472+
): Promise<Partial<Record<analyses.AnalysisKind, string[]>>> {
473+
const stats = fs.statSync(sarifPath, { throwIfNoEntry: false });
474+
475+
if (stats === undefined) {
476+
// This is always a configuration error, even for first-party runs.
477+
throw new ConfigurationError(`Path does not exist: ${sarifPath}`);
478+
}
479+
480+
const results = {};
481+
482+
if (stats.isDirectory()) {
483+
let sarifFiles = findSarifFilesInDir(sarifPath, (name) =>
484+
name.endsWith(".sarif"),
485+
);
486+
logger.debug(
487+
`Found the following .sarif files in ${sarifPath}: ${sarifFiles.join(", ")}`,
488+
);
489+
490+
for (const analysisConfig of analyses.SarifScanOrder) {
491+
const files = sarifFiles.filter(analysisConfig.sarifPredicate);
492+
if (files.length > 0) {
493+
logger.debug(
494+
`The following SARIF files are for ${analysisConfig.name}: ${files.join(", ")}`,
495+
);
496+
// Looping through the array a second time is not efficient, but more readable.
497+
// Change this to one loop for both calls to `filter` if this becomes a bottleneck.
498+
sarifFiles = sarifFiles.filter(
499+
(name) => !analysisConfig.sarifPredicate(name),
500+
);
501+
results[analysisConfig.kind] = files;
502+
} else {
503+
logger.debug(`Found no SARIF files for ${analysisConfig.name}`);
504+
}
505+
}
506+
} else {
507+
for (const analysisConfig of analyses.SarifScanOrder) {
508+
if (
509+
analysisConfig.kind === analyses.AnalysisKind.CodeScanning ||
510+
analysisConfig.sarifPredicate(sarifPath)
511+
) {
512+
logger.debug(
513+
`Using '${sarifPath}' as a SARIF file for ${analysisConfig.name}.`,
514+
);
515+
results[analysisConfig.kind] = [sarifPath];
516+
break;
517+
}
518+
}
519+
}
520+
521+
return results;
522+
}
523+
462524
// Counts the number of results in the given SARIF file
463525
function countResultsInSarif(sarif: string): number {
464526
let numResults = 0;

0 commit comments

Comments
 (0)