Skip to content

Commit dae1626

Browse files
committed
Filter alerts by pr-diff-range JSON file
1 parent 77bc2a5 commit dae1626

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

src/diff-filtering-utils.ts

+15
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,18 @@ export function writeDiffRangesJsonFile(
2525
`Wrote pr-diff-range JSON file to ${jsonFilePath}:\n${jsonContents}`,
2626
);
2727
}
28+
29+
export function readDiffRangesJsonFile(
30+
logger: Logger,
31+
): DiffThunkRange[] | undefined {
32+
const jsonFilePath = getDiffRangesJsonFilePath();
33+
if (!fs.existsSync(jsonFilePath)) {
34+
logger.debug(`Diff ranges JSON file does not exist at ${jsonFilePath}`);
35+
return undefined;
36+
}
37+
const jsonContents = fs.readFileSync(jsonFilePath, "utf8");
38+
logger.debug(
39+
`Read pr-diff-range JSON file from ${jsonFilePath}:\n${jsonContents}`,
40+
);
41+
return JSON.parse(jsonContents) as DiffThunkRange[];
42+
}

src/upload-lib.ts

+49
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import * as api from "./api-client";
1414
import { getGitHubVersion, wrapApiConfigurationError } from "./api-client";
1515
import { CodeQL, getCodeQL } from "./codeql";
1616
import { getConfig } from "./config-utils";
17+
import { readDiffRangesJsonFile } from "./diff-filtering-utils";
1718
import { EnvVar } from "./environment";
1819
import { FeatureEnablement } from "./feature-flags";
1920
import * as fingerprints from "./fingerprints";
@@ -578,6 +579,7 @@ export async function uploadFiles(
578579
features,
579580
logger,
580581
);
582+
sarif = filterAlertsByDiffRange(logger, sarif);
581583
sarif = await fingerprints.addFingerprints(sarif, checkoutPath, logger);
582584

583585
const analysisKey = await api.getAnalysisKey();
@@ -848,3 +850,50 @@ export class InvalidSarifUploadError extends Error {
848850
super(message);
849851
}
850852
}
853+
854+
function filterAlertsByDiffRange(logger: Logger, sarif: SarifFile): SarifFile {
855+
const diffRanges = readDiffRangesJsonFile(logger);
856+
if (!diffRanges?.length) {
857+
return sarif;
858+
}
859+
860+
const checkoutPath = actionsUtil.getRequiredInput("checkout_path");
861+
862+
for (const run of sarif.runs) {
863+
if (run.results) {
864+
run.results = run.results.filter((result) => {
865+
const locations = [
866+
...(result.locations || []).map((loc) => loc.physicalLocation),
867+
...(result.relatedLocations || []).map((loc) => loc.physicalLocation),
868+
];
869+
870+
return locations.some((physicalLocation) => {
871+
const locationUri = physicalLocation?.artifactLocation?.uri;
872+
const locationStartLine = physicalLocation?.region?.startLine;
873+
if (!locationUri || locationStartLine === undefined) {
874+
return false;
875+
}
876+
// CodeQL always uses forward slashes as the path separator, so on Windows we
877+
// need to replace any backslashes with forward slashes.
878+
const locationPath = path
879+
.join(checkoutPath, locationUri)
880+
.replaceAll(path.sep, "/");
881+
// Alert filtering here replicates the same behavior as the restrictAlertsTo
882+
// extensible predicate in CodeQL. See the restrictAlertsTo documentation
883+
// https://codeql.github.com/codeql-standard-libraries/csharp/codeql/util/AlertFiltering.qll/predicate.AlertFiltering$restrictAlertsTo.3.html
884+
// for more details, such as why the filtering applies only to the first line
885+
// of an alert location.
886+
return diffRanges.some(
887+
(range) =>
888+
range.path === locationPath &&
889+
((range.startLine <= locationStartLine &&
890+
range.endLine >= locationStartLine) ||
891+
(range.startLine === 0 && range.endLine === 0)),
892+
);
893+
});
894+
});
895+
}
896+
}
897+
898+
return sarif;
899+
}

src/util.ts

+10
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,16 @@ export interface SarifResult {
9696
};
9797
};
9898
}>;
99+
relatedLocations?: Array<{
100+
physicalLocation: {
101+
artifactLocation: {
102+
uri: string;
103+
};
104+
region?: {
105+
startLine?: number;
106+
};
107+
};
108+
}>;
99109
partialFingerprints: {
100110
primaryLocationLineHash?: string;
101111
};

0 commit comments

Comments
 (0)