@@ -14,6 +14,7 @@ import * as api from "./api-client";
14
14
import { getGitHubVersion , wrapApiConfigurationError } from "./api-client" ;
15
15
import { CodeQL , getCodeQL } from "./codeql" ;
16
16
import { getConfig } from "./config-utils" ;
17
+ import { readDiffRangesJsonFile } from "./diff-filtering-utils" ;
17
18
import { EnvVar } from "./environment" ;
18
19
import { FeatureEnablement } from "./feature-flags" ;
19
20
import * as fingerprints from "./fingerprints" ;
@@ -578,6 +579,7 @@ export async function uploadFiles(
578
579
features ,
579
580
logger ,
580
581
) ;
582
+ sarif = filterAlertsByDiffRange ( logger , sarif ) ;
581
583
sarif = await fingerprints . addFingerprints ( sarif , checkoutPath , logger ) ;
582
584
583
585
const analysisKey = await api . getAnalysisKey ( ) ;
@@ -848,3 +850,50 @@ export class InvalidSarifUploadError extends Error {
848
850
super ( message ) ;
849
851
}
850
852
}
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