-
Notifications
You must be signed in to change notification settings - Fork 451
Expand file tree
/
Copy pathindex.ts
More file actions
117 lines (97 loc) · 3.16 KB
/
index.ts
File metadata and controls
117 lines (97 loc) · 3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import * as fs from "fs";
import { Logger } from "../logging";
import * as sarif from "sarif";
export type * from "sarif";
// `automationId` is non-standard.
export type RunKey = sarif.ToolComponent & {
automationId: string | undefined;
};
/**
* An error that occurred due to an invalid SARIF upload request.
*/
export class InvalidSarifUploadError extends Error {}
/**
* Get the array of all the tool names contained in the given sarif contents.
*
* Returns an array of unique string tool names.
*/
export function getToolNames(sarifFile: sarif.Log): string[] {
const toolNames = {};
for (const run of sarifFile.runs || []) {
const tool = run.tool || {};
const driver = tool.driver || {};
if (typeof driver.name === "string" && driver.name.length > 0) {
toolNames[driver.name] = true;
}
}
return Object.keys(toolNames);
}
export function readSarifFile(sarifFilePath: string): sarif.Log {
return JSON.parse(fs.readFileSync(sarifFilePath, "utf8")) as sarif.Log;
}
// Takes a list of paths to sarif files and combines them together,
// returning the contents of the combined sarif file.
export function combineSarifFiles(
sarifFiles: string[],
logger: Logger,
): sarif.Log {
logger.info(`Loading SARIF file(s)`);
const combinedSarif: sarif.Log = {
version: "2.1.0",
runs: [],
};
for (const sarifFile of sarifFiles) {
logger.debug(`Loading SARIF file: ${sarifFile}`);
const sarifObject = readSarifFile(sarifFile);
// Check SARIF version
if (combinedSarif.version === null) {
combinedSarif.version = sarifObject.version;
} else if (combinedSarif.version !== sarifObject.version) {
throw new InvalidSarifUploadError(
`Different SARIF versions encountered: ${combinedSarif.version} and ${sarifObject.version}`,
);
}
combinedSarif.runs.push(...sarifObject.runs);
}
return combinedSarif;
}
/**
* Checks whether all the runs in the given SARIF files were produced by CodeQL.
* @param sarifObjects The list of SARIF objects to check.
*/
export function areAllRunsProducedByCodeQL(sarifObjects: sarif.Log[]): boolean {
return sarifObjects.every((sarifObject) => {
return sarifObject.runs?.every(
(run) => run.tool?.driver?.name === "CodeQL",
);
});
}
function createRunKey(run: sarif.Run): RunKey {
return {
name: run.tool?.driver?.name,
fullName: run.tool?.driver?.fullName,
version: run.tool?.driver?.version,
semanticVersion: run.tool?.driver?.semanticVersion,
guid: run.tool?.driver?.guid,
automationId: run.automationDetails?.id,
};
}
/**
* Checks whether all runs in the given SARIF files are unique (based on the
* criteria used by Code Scanning to determine analysis categories).
* @param sarifObjects The list of SARIF objects to check.
*/
export function areAllRunsUnique(sarifObjects: sarif.Log[]): boolean {
const keys = new Set<string>();
for (const sarifObject of sarifObjects) {
for (const run of sarifObject.runs) {
const key = JSON.stringify(createRunKey(run));
// If the key already exists, the runs are not unique.
if (keys.has(key)) {
return false;
}
keys.add(key);
}
}
return true;
}