@@ -14,6 +14,7 @@ import * as api from "./api-client";
1414import { getGitHubVersion , wrapApiConfigurationError } from "./api-client" ;
1515import { CodeQL , getCodeQL } from "./codeql" ;
1616import { getConfig } from "./config-utils" ;
17+ import { readDiffRangesJsonFile } from "./diff-filtering-utils" ;
1718import { EnvVar } from "./environment" ;
1819import { FeatureEnablement } from "./feature-flags" ;
1920import * 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+ }
0 commit comments