Skip to content

Commit c013552

Browse files
thelastnodeclaudebluekeyes
authored
Add file filtering support to the modified_lines predicate (#1043)
Supports three filtering modes: - No files config: count all files - Only exclude: count all files except excluded ones - Include (with optional exclude): count only included files, minus excluded ones Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Billy Keyes <bkeyes@palantir.com>
1 parent 4358c7a commit c013552

File tree

3 files changed

+314
-39
lines changed

3 files changed

+314
-39
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,10 +371,22 @@ if:
371371
# "modified_lines" is satisfied if the number of lines added or deleted by
372372
# the pull request matches any of the listed conditions. Each expression is
373373
# an operator (one of '<', '>' or '='), an optional space, and a number.
374+
# Optionally, use "files" to filter which files are counted:
375+
# - If files is not specified, all files are counted
376+
# - If only files.include is specified, only matching files are counted
377+
# - If only files.exclude is specified, all files except those matching are counted
378+
# - If both are specified, files must match an include pattern and NOT match any exclude pattern
374379
modified_lines:
375380
additions: "> 100"
376381
deletions: "> 100"
377382
total: "> 200"
383+
files:
384+
include:
385+
- ".*\\.go$"
386+
- ".*\\.js$"
387+
exclude:
388+
- ".*_test\\.go$"
389+
- ".*\\.generated\\..*"
378390

379391
# DEPRECATED: Use "has_status" below instead, which is more flexible.
380392
# "has_successful_status" is satisfied if the status checks that are specified

policy/predicate/file.go

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,29 @@ func (pred *FileNotDeleted) Trigger() common.Trigger {
359359
}
360360

361361
type ModifiedLines struct {
362-
Additions ComparisonExpr `yaml:"additions,omitempty"`
363-
Deletions ComparisonExpr `yaml:"deletions,omitempty"`
364-
Total ComparisonExpr `yaml:"total,omitempty"`
362+
Additions ComparisonExpr `yaml:"additions,omitempty"`
363+
Deletions ComparisonExpr `yaml:"deletions,omitempty"`
364+
Total ComparisonExpr `yaml:"total,omitempty"`
365+
Files ModifiedLinesFileFilter `yaml:"files,omitempty"`
366+
}
367+
368+
type ModifiedLinesFileFilter struct {
369+
Include []common.Regexp `yaml:"include,omitempty"`
370+
Exclude []common.Regexp `yaml:"exclude,omitempty"`
371+
}
372+
373+
func (ff ModifiedLinesFileFilter) IsZero() bool {
374+
return len(ff.Include) == 0 && len(ff.Exclude) == 0
375+
}
376+
377+
func (ff ModifiedLinesFileFilter) MatchesFile(filename string) bool {
378+
if len(ff.Exclude) > 0 && anyMatches(ff.Exclude, filename) {
379+
return false
380+
}
381+
if len(ff.Include) > 0 && !anyMatches(ff.Include, filename) {
382+
return false
383+
}
384+
return true
365385
}
366386

367387
type CompareOp uint8
@@ -460,7 +480,8 @@ func (pred *ModifiedLines) Evaluate(ctx context.Context, prctx pull.Context) (*c
460480

461481
predicateResult := common.PredicateResult{
462482
ValuePhrase: "file modifications",
463-
ConditionPhrase: "meet the modification conditions",
483+
ConditionPhrase: "meet",
484+
ConditionsMap: make(map[string][]string),
464485
}
465486

466487
if err != nil {
@@ -469,39 +490,67 @@ func (pred *ModifiedLines) Evaluate(ctx context.Context, prctx pull.Context) (*c
469490

470491
var additions, deletions int64
471492
for _, f := range files {
493+
if !pred.Files.MatchesFile(f.Filename) {
494+
continue
495+
}
472496
additions += int64(f.Additions)
473497
deletions += int64(f.Deletions)
474498
}
475499

500+
if len(pred.Files.Include) > 0 {
501+
predicateResult.ConditionsMap["in files matching"] = getPathStrings(pred.Files.Include)
502+
}
503+
if len(pred.Files.Exclude) > 0 {
504+
predicateResult.ConditionsMap["excluding files matching"] = getPathStrings(pred.Files.Exclude)
505+
}
506+
507+
const conditionKey = "the modification conditions"
508+
476509
if !pred.Additions.IsEmpty() {
477-
predicateResult.Values = []string{fmt.Sprintf("+%d", additions)}
478-
predicateResult.ConditionValues = []string{fmt.Sprintf("added lines %s", pred.Additions.String())}
510+
value := fmt.Sprintf("+%d", additions)
511+
cond := fmt.Sprintf("added lines %s", pred.Additions.String())
512+
479513
if pred.Additions.Evaluate(additions) {
514+
predicateResult.Values = []string{value}
515+
predicateResult.ConditionsMap[conditionKey] = []string{cond}
480516
predicateResult.Satisfied = true
481517
return &predicateResult, nil
482518
}
519+
520+
predicateResult.Values = append(predicateResult.Values, value)
521+
predicateResult.ConditionsMap[conditionKey] = append(predicateResult.ConditionsMap[conditionKey], cond)
483522
}
523+
484524
if !pred.Deletions.IsEmpty() {
525+
value := fmt.Sprintf("-%d", deletions)
526+
cond := fmt.Sprintf("deleted lines %s", pred.Deletions.String())
527+
485528
if pred.Deletions.Evaluate(deletions) {
486-
predicateResult.Values = []string{fmt.Sprintf("-%d", deletions)}
487-
predicateResult.ConditionValues = []string{fmt.Sprintf("deleted lines %s", pred.Deletions.String())}
529+
predicateResult.Values = []string{value}
530+
predicateResult.ConditionsMap[conditionKey] = []string{cond}
488531
predicateResult.Satisfied = true
489532
return &predicateResult, nil
490533
}
491-
predicateResult.Values = append(predicateResult.Values, fmt.Sprintf("-%d", deletions))
492-
predicateResult.ConditionValues = append(predicateResult.ConditionValues, fmt.Sprintf("deleted lines %s", pred.Deletions.String()))
534+
535+
predicateResult.Values = append(predicateResult.Values, value)
536+
predicateResult.ConditionsMap[conditionKey] = append(predicateResult.ConditionsMap[conditionKey], cond)
493537
}
538+
494539
if !pred.Total.IsEmpty() {
540+
value := fmt.Sprintf("total %d", additions+deletions)
541+
cond := fmt.Sprintf("total modifications %s", pred.Total.String())
542+
495543
if pred.Total.Evaluate(additions + deletions) {
496-
predicateResult.Values = []string{fmt.Sprintf("total %d", additions+deletions)}
497-
predicateResult.ConditionValues = []string{fmt.Sprintf("total modifications %s", pred.Total.String())}
544+
predicateResult.Values = []string{value}
545+
predicateResult.ConditionsMap[conditionKey] = []string{cond}
498546
predicateResult.Satisfied = true
499547
return &predicateResult, nil
500548
}
501-
predicateResult.Values = append(predicateResult.Values, fmt.Sprintf("total %d", additions+deletions))
502-
predicateResult.ConditionValues = append(predicateResult.ConditionValues, fmt.Sprintf("total modifications %s", pred.Total.String()))
549+
550+
predicateResult.Values = append(predicateResult.Values, value)
551+
predicateResult.ConditionsMap[conditionKey] = append(predicateResult.ConditionsMap[conditionKey], cond)
503552
}
504-
predicateResult.Satisfied = false
553+
505554
return &predicateResult, nil
506555
}
507556

0 commit comments

Comments
 (0)