From 0381dc470140eaebc6fd87fc4aedc4dd2f39f997 Mon Sep 17 00:00:00 2001 From: Galo Navarro Date: Thu, 28 Dec 2023 20:41:50 +0100 Subject: [PATCH] Size: support regex exclusions (#131) Signed-off-by: Galo Navarro --- README.md | 23 +++++++++++----- cmd/action_test.go | 7 +++++ pkg/condition_size.go | 18 ++++++++----- pkg/labeler_test.go | 37 +++++++++++++++++++++++++- test_data/config_v1_composite_size.yml | 4 +++ 5 files changed, 75 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index ae1d312..47b863b 100644 --- a/README.md +++ b/README.md @@ -400,10 +400,11 @@ files: - ".*\\/subfolder\\/.*\\.md" ``` -> **NOTICE** the double backslash (`\\`) in the example above. This GitHub Action is coded in Go (Golang), which means -> you need to pay special attention to regular expressions (Regex). Special characters need to be escaped with double -> backslashes. This is because the backslash in Go strings is an escape character and therefore must be escaped itself -> to appear as a literal in the regex. +> **NOTICE** the double backslash (`\\`) in the example above. This GitHub +Action is coded in Go (Golang), which means you need to pay special attention to +regular expressions (Regex). Special characters need to be escaped with double +backslashes. This is because the backslash in Go strings is an escape character +and therefore must be escaped itself to appear as a literal in the regex. ### Mergeable status (PRs only) @@ -457,17 +458,25 @@ reported by the [GitHub API](https://developer.github.com/v3/pulls). You can exclude some files so that their changes are not taken into account for the overall count. This can be useful for `yarn.lock`, -`go.sum` and such. Use `exclude-files`: +`go.sum` and such. Use `exclude-files`, which supports both an explicit +file or a Regex expression: ```yaml - label: "L" size: - exclude-files: ["yarn.lock"] + exclude-files: ["yarn.lock", "\\/root\\/.+\\/test.md"] above: 100 ``` This condition will apply the `L` label if the diff is above 100 lines, -but NOT taking into account changes in `yarn.lock`. +but NOT taking into account changes in `yarn.lock`, or any `test.md` +file that is in a subdirectory of `root`. + +**NOTICE** the double backslash (`\\`) in the example above. This GitHub +Action is coded in Go (Golang), which means you need to pay special attention to +regular expressions (Regex). Special characters need to be escaped with double +backslashes. This is because the backslash in Go strings is an escape character +and therefore must be escaped itself to appear as a literal in the regex. **NOTICE** the old format for specifying size properties (`size-above` and `size-below`) has been deprecated. The action will continue diff --git a/cmd/action_test.go b/cmd/action_test.go index 5ba13ce..be7f3e7 100644 --- a/cmd/action_test.go +++ b/cmd/action_test.go @@ -225,6 +225,13 @@ func TestGetLabelerConfigV1WithCompositeSize(t *testing.T) { Below: "100", }, }, + { + Label: "L", + Size: &labeler.SizeConfig{ + ExcludeFiles: []string{"test.yaml", "\\/dir\\/test.+.yaml"}, + Above: "100", + }, + }, }, } diff --git a/pkg/condition_size.go b/pkg/condition_size.go index 847de88..2cd654a 100644 --- a/pkg/condition_size.go +++ b/pkg/condition_size.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "math" + "regexp" "strconv" "strings" @@ -68,9 +69,9 @@ func isOldConfig(matcher LabelMatcher) bool { return matcher.SizeAbove != "" || matcher.SizeBelow != "" } -func (l *Labeler) getModifiedLinesCount(pr *gh.PullRequest, excludedFiles []string) (int64, error) { +func (l *Labeler) getModifiedLinesCount(pr *gh.PullRequest, exclusions []string) (int64, error) { - if len(excludedFiles) == 0 { + if len(exclusions) == 0 { // no exclusions so we can just rely on GH's summary which is // more lightweight return int64(math.Abs(float64(pr.GetAdditions() + pr.GetDeletions()))), nil @@ -97,9 +98,11 @@ func (l *Labeler) getModifiedLinesCount(pr *gh.PullRequest, excludedFiles []stri // We're in a file's block path := strings.TrimPrefix(line, "---") path = strings.TrimPrefix(path, "+++") + path = strings.TrimPrefix(path, "a/") + path = strings.TrimPrefix(path, "b/") path = strings.TrimSpace(path) // Check if the file path matches any of the excluded files - countFile = !isFileExcluded(path, excludedFiles) + countFile = !isFileExcluded(path, exclusions) if countFile { log.Printf("Counting changes in file %s", path) } else { @@ -118,9 +121,12 @@ func (l *Labeler) getModifiedLinesCount(pr *gh.PullRequest, excludedFiles []stri return count, nil } -func isFileExcluded(path string, excludedFiles []string) bool { - for _, excludedFile := range excludedFiles { - if strings.HasSuffix(path, excludedFile) { +func isFileExcluded(path string, exclusions []string) bool { + for _, exclusion := range exclusions { + exclusionRegex, err := regexp.Compile(exclusion) + if err != nil { + log.Printf("Error compiling file exclusion regex %s: %s", exclusion, err) + } else if exclusionRegex.MatchString(path) { return true } } diff --git a/pkg/labeler_test.go b/pkg/labeler_test.go index 5a6aea7..a9d3b5c 100644 --- a/pkg/labeler_test.go +++ b/pkg/labeler_test.go @@ -334,7 +334,42 @@ func TestHandleEvent(t *testing.T) { { Label: "L", Size: &SizeConfig{ - ExcludeFiles: []string{"README.md", "new_file", "dependabot.yml", "root/sub/test.md"}, + ExcludeFiles: []string{ + "R.+.md", // captures README.md + "new_file", + "dependabot.yml", + "\\/root\\/.+\\/test.md", // captures root/sub/test.md + }, + // our test file has a diff in four files, + // including added/removed which have a + // slightly trickier diff. Adding any of + // these will get us above 2 lines and fail + // the test. + Below: "2", + }, + }, + }, + }, + initialLabels: []string{}, + expectedLabels: []string{"L"}, + }, + { + event: "pull_request", + payloads: []string{"big_pr"}, + name: "Test the size_above rule applying file dodgy exclusions", + config: LabelerConfigV1{ + Version: 1, + Labels: []LabelMatcher{ + { + Label: "L", + Size: &SizeConfig{ + ExcludeFiles: []string{ + "R.+.md", // captures README.md + "new_file", + "dependabot.yml", + "root/**/test", // dodgy regex should NOT break the evaluation + "\\/root\\/.+\\/test.md", // captures root/sub/test.md + }, // our test file has a diff in four files, // including added/removed which have a // slightly trickier diff. Adding any of diff --git a/test_data/config_v1_composite_size.yml b/test_data/config_v1_composite_size.yml index 3acf8f1..f0d1bbb 100644 --- a/test_data/config_v1_composite_size.yml +++ b/test_data/config_v1_composite_size.yml @@ -8,3 +8,7 @@ labels: exclude-files: ["test.yaml"] above: 9 below: 100 + - label: L + size: + exclude-files: ["test.yaml", "\\/dir\\/test.+.yaml"] + above: 100