From 71945eb54d5bfb261e9c4a61850b25b2e4ce84ce Mon Sep 17 00:00:00 2001 From: Lukasz Mierzwa Date: Thu, 8 Jun 2023 11:15:33 +0100 Subject: [PATCH] Add exclude option to ci block Fixes #609. --- cmd/pint/ci.go | 9 ++++- cmd/pint/tests/0139_ci_exclude.txt | 46 +++++++++++++++++++++ cmd/pint/tests/0140_ci_include_exclude.txt | 47 ++++++++++++++++++++++ docs/changelog.md | 4 ++ docs/configuration.md | 4 ++ internal/config/ci.go | 8 ++++ internal/config/ci_test.go | 14 +++++++ internal/discovery/git_blame.go | 12 +++++- internal/discovery/git_blame_test.go | 10 +++++ internal/discovery/git_branch.go | 12 +++++- internal/discovery/git_branch_test.go | 40 ++++++++++-------- 11 files changed, 185 insertions(+), 21 deletions(-) create mode 100644 cmd/pint/tests/0139_ci_exclude.txt create mode 100644 cmd/pint/tests/0140_ci_include_exclude.txt diff --git a/cmd/pint/ci.go b/cmd/pint/ci.go index 2c62707f..ef080a7b 100644 --- a/cmd/pint/ci.go +++ b/cmd/pint/ci.go @@ -68,6 +68,11 @@ func actionCI(c *cli.Context) error { includeRe = append(includeRe, regexp.MustCompile("^"+pattern+"$")) } + excludeRe := []*regexp.Regexp{} + for _, pattern := range meta.cfg.CI.Exclude { + excludeRe = append(excludeRe, regexp.MustCompile("^"+pattern+"$")) + } + meta.cfg.CI = detectCI(meta.cfg.CI) baseBranch := meta.cfg.CI.BaseBranch if c.String(baseBranchFlag) != "" { @@ -85,10 +90,10 @@ func actionCI(c *cli.Context) error { var entries []discovery.Entry if c.Bool(devFlag) { - finder := discovery.NewGitBranchFinder(git.RunGit, includeRe, baseBranch, meta.cfg.CI.MaxCommits, meta.cfg.Parser.CompileRelaxed()) + finder := discovery.NewGitBranchFinder(git.RunGit, includeRe, excludeRe, baseBranch, meta.cfg.CI.MaxCommits, meta.cfg.Parser.CompileRelaxed()) entries, err = finder.Find() } else { - finder := discovery.NewGitBlameFinder(git.RunGit, includeRe, baseBranch, meta.cfg.CI.MaxCommits, meta.cfg.Parser.CompileRelaxed()) + finder := discovery.NewGitBlameFinder(git.RunGit, includeRe, excludeRe, baseBranch, meta.cfg.CI.MaxCommits, meta.cfg.Parser.CompileRelaxed()) entries, err = finder.Find() } if err != nil { diff --git a/cmd/pint/tests/0139_ci_exclude.txt b/cmd/pint/tests/0139_ci_exclude.txt new file mode 100644 index 00000000..e10fe6ce --- /dev/null +++ b/cmd/pint/tests/0139_ci_exclude.txt @@ -0,0 +1,46 @@ +mkdir testrepo +cd testrepo +exec git init --initial-branch=main . + +cp ../src/.pint.hcl . +env GIT_AUTHOR_NAME=pint +env GIT_AUTHOR_EMAIL=pint@example.com +env GIT_COMMITTER_NAME=pint +env GIT_COMMITTER_EMAIL=pint@example.com +exec git add . +exec git commit -am 'import rules and config' + +exec git checkout -b v1 +cp ../src/a.yml a.yml +exec git add a.yml +exec git commit -am 'v1' + +exec git checkout -b v2 +cp ../src/b.yml b.yml +exec git add b.yml +exec git commit -am 'v2' + +pint.ok -l debug --no-color ci +! stdout . +stderr 'level=debug msg="Got branch information" base=main current=v2' +stderr 'level=debug msg="Found commit to scan" commit=.*' +stderr 'level=debug msg="Found commit to scan" commit=.*' +stderr 'level=debug msg="Git file change" change=A commit=.* path=a.yml' +stderr 'level=debug msg="Git file change" change=A commit=.* path=b.yml' +stderr 'level=debug msg="Skipping file due to include/exclude rules" path=a.yml' +stderr 'level=debug msg="Skipping file due to include/exclude rules" path=b.yml' + +-- src/a.yml -- +- record: rule1 + expr: sum(foo) bi() +-- src/b.yml -- +- record: rule1 + expr: sum(foo) bi() +-- src/.pint.hcl -- +ci { + baseBranch = "main" + exclude = [".*.yml"] +} +parser { + relaxed = [".*"] +} diff --git a/cmd/pint/tests/0140_ci_include_exclude.txt b/cmd/pint/tests/0140_ci_include_exclude.txt new file mode 100644 index 00000000..aa3a5993 --- /dev/null +++ b/cmd/pint/tests/0140_ci_include_exclude.txt @@ -0,0 +1,47 @@ +mkdir testrepo +cd testrepo +exec git init --initial-branch=main . + +cp ../src/.pint.hcl . +env GIT_AUTHOR_NAME=pint +env GIT_AUTHOR_EMAIL=pint@example.com +env GIT_COMMITTER_NAME=pint +env GIT_COMMITTER_EMAIL=pint@example.com +exec git add . +exec git commit -am 'import rules and config' + +exec git checkout -b v1 +cp ../src/a.yml a.yml +exec git add a.yml +exec git commit -am 'v1' + +exec git checkout -b v2 +cp ../src/b.yml b.yml +exec git add b.yml +exec git commit -am 'v2' + +pint.ok -l debug --no-color ci +! stdout . +stderr 'level=debug msg="Got branch information" base=main current=v2' +stderr 'level=debug msg="Found commit to scan" commit=.*' +stderr 'level=debug msg="Found commit to scan" commit=.*' +stderr 'level=debug msg="Git file change" change=A commit=.* path=a.yml' +stderr 'level=debug msg="Git file change" change=A commit=.* path=b.yml' +stderr 'level=debug msg="Skipping file due to include/exclude rules" path=a.yml' +stderr 'level=debug msg="Skipping file due to include/exclude rules" path=b.yml' + +-- src/a.yml -- +- record: rule1 + expr: sum(foo) bi() +-- src/b.yml -- +- record: rule1 + expr: sum(foo) bi() +-- src/.pint.hcl -- +ci { + baseBranch = "main" + include = [".*.yml"] + exclude = [".*.yml"] +} +parser { + relaxed = [".*"] +} diff --git a/docs/changelog.md b/docs/changelog.md index b4358a57..1caff45b 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,6 +2,10 @@ ## v0.44.0 +### Added + +- Added `exclude` option to `ci` config block - #609. + ### Fixed - Fixed `alerts/annotation` check regexp matching - #613. diff --git a/docs/configuration.md b/docs/configuration.md index 361fb966..63abd045 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -117,6 +117,7 @@ Syntax: ```js ci { include = [ "(.*)", ... ] + exclude = [ "(.*)", ... ] maxCommits = 20 baseBranch = "master" } @@ -124,6 +125,9 @@ ci { - `include` - list of file patterns to check when running checks. Only files matching those regexp rules will be checked, other modified files will be ignored. +- `exclude` - list of file patterns to ignore when running checks. + This option takes precedence over `include`, so if a file path matches both + `include` & `exclude` patterns it will be excluded. - `maxCommits` - by default pint will try to find all commits on the current branch, this requires full git history to be present, if we have a shallow clone this might fail to find only current branch commits and give us a huge list. diff --git a/internal/config/ci.go b/internal/config/ci.go index 640ebf02..12cce7b1 100644 --- a/internal/config/ci.go +++ b/internal/config/ci.go @@ -7,6 +7,7 @@ import ( type CI struct { Include []string `hcl:"include,optional" json:"include,omitempty"` + Exclude []string `hcl:"exclude,optional" json:"exclude,omitempty"` MaxCommits int `hcl:"maxCommits,optional" json:"maxCommits,omitempty"` BaseBranch string `hcl:"baseBranch,optional" json:"baseBranch,omitempty"` } @@ -22,5 +23,12 @@ func (ci CI) validate() error { return err } } + + for _, pattern := range ci.Exclude { + _, err := regexp.Compile(pattern) + if err != nil { + return err + } + } return nil } diff --git a/internal/config/ci_test.go b/internal/config/ci_test.go index 81c55b30..8ad74d51 100644 --- a/internal/config/ci_test.go +++ b/internal/config/ci_test.go @@ -22,6 +22,13 @@ func TestCISettings(t *testing.T) { Include: []string{"foo/.+"}, }, }, + { + conf: CI{ + MaxCommits: 1, + BaseBranch: "main", + Exclude: []string{"foo/.+"}, + }, + }, { conf: CI{ MaxCommits: -5, @@ -41,6 +48,13 @@ func TestCISettings(t *testing.T) { }, err: errors.New("error parsing regexp: invalid nested repetition operator: `++`"), }, + { + conf: CI{ + MaxCommits: 20, + Exclude: []string{".+++"}, + }, + err: errors.New("error parsing regexp: invalid nested repetition operator: `++`"), + }, } for _, tc := range testCases { diff --git a/internal/discovery/git_blame.go b/internal/discovery/git_blame.go index fd5deeab..ffe563e6 100644 --- a/internal/discovery/git_blame.go +++ b/internal/discovery/git_blame.go @@ -14,6 +14,7 @@ import ( func NewGitBlameFinder( gitCmd git.CommandRunner, include []*regexp.Regexp, + exclude []*regexp.Regexp, baseBranch string, maxCommits int, relaxed []*regexp.Regexp, @@ -21,6 +22,7 @@ func NewGitBlameFinder( return GitBlameFinder{ gitCmd: gitCmd, include: include, + exclude: exclude, baseBranch: baseBranch, maxCommits: maxCommits, relaxed: relaxed, @@ -30,6 +32,7 @@ func NewGitBlameFinder( type GitBlameFinder struct { gitCmd git.CommandRunner include []*regexp.Regexp + exclude []*regexp.Regexp baseBranch string maxCommits int relaxed []*regexp.Regexp @@ -166,15 +169,22 @@ func (f GitBlameFinder) Find() (entries []Entry, err error) { } func (f GitBlameFinder) isPathAllowed(path string) bool { - if len(f.include) == 0 { + if len(f.include) == 0 && len(f.exclude) == 0 { return true } + for _, pattern := range f.exclude { + if pattern.MatchString(path) { + return false + } + } + for _, pattern := range f.include { if pattern.MatchString(path) { return true } } + return false } diff --git a/internal/discovery/git_blame_test.go b/internal/discovery/git_blame_test.go index cdee715b..01cee3da 100644 --- a/internal/discovery/git_blame_test.go +++ b/internal/discovery/git_blame_test.go @@ -86,6 +86,7 @@ func TestGitBlameFinder(t *testing.T) { return nil, fmt.Errorf("mock error") }, nil, + nil, "main", 0, nil, @@ -104,6 +105,7 @@ func TestGitBlameFinder(t *testing.T) { } }, nil, + nil, "main", 0, nil, @@ -128,6 +130,7 @@ func TestGitBlameFinder(t *testing.T) { } }, nil, + nil, "main", 0, []*regexp.Regexp{regexp.MustCompile(".*")}, @@ -154,6 +157,7 @@ func TestGitBlameFinder(t *testing.T) { } }, nil, + nil, "main", 0, []*regexp.Regexp{regexp.MustCompile(".*")}, @@ -185,6 +189,7 @@ func TestGitBlameFinder(t *testing.T) { } }, nil, + nil, "main", 0, []*regexp.Regexp{regexp.MustCompile(".*")}, @@ -218,6 +223,7 @@ func TestGitBlameFinder(t *testing.T) { } }, nil, + nil, "main", 0, []*regexp.Regexp{regexp.MustCompile(".*")}, @@ -330,6 +336,7 @@ R090 foo/c2c.yml c2c.yml regexp.MustCompile("^foo/.*"), regexp.MustCompile("^c.*.yml$"), }, + nil, "main", 0, []*regexp.Regexp{regexp.MustCompile(".*")}, @@ -382,6 +389,7 @@ R090 foo/c2c.yml c2c.yml } }, nil, + nil, "main", 0, nil, @@ -410,6 +418,7 @@ R090 foo/c2c.yml c2c.yml } }, nil, + nil, "main", 0, []*regexp.Regexp{regexp.MustCompile(".*")}, @@ -436,6 +445,7 @@ R090 foo/c2c.yml c2c.yml } }, nil, + nil, "main", 0, []*regexp.Regexp{regexp.MustCompile(".*")}, diff --git a/internal/discovery/git_branch.go b/internal/discovery/git_branch.go index a13f176e..603e68e8 100644 --- a/internal/discovery/git_branch.go +++ b/internal/discovery/git_branch.go @@ -17,6 +17,7 @@ import ( func NewGitBranchFinder( gitCmd git.CommandRunner, include []*regexp.Regexp, + exclude []*regexp.Regexp, baseBranch string, maxCommits int, relaxed []*regexp.Regexp, @@ -24,6 +25,7 @@ func NewGitBranchFinder( return GitBranchFinder{ gitCmd: gitCmd, include: include, + exclude: exclude, baseBranch: baseBranch, maxCommits: maxCommits, relaxed: relaxed, @@ -33,6 +35,7 @@ func NewGitBranchFinder( type GitBranchFinder struct { gitCmd git.CommandRunner include []*regexp.Regexp + exclude []*regexp.Regexp baseBranch string maxCommits int relaxed []*regexp.Regexp @@ -152,15 +155,22 @@ func (f GitBranchFinder) Find() (entries []Entry, err error) { } func (f GitBranchFinder) isPathAllowed(path string) bool { - if len(f.include) == 0 { + if len(f.include) == 0 && len(f.exclude) == 0 { return true } + for _, pattern := range f.exclude { + if pattern.MatchString(path) { + return false + } + } + for _, pattern := range f.include { if pattern.MatchString(path) { return true } } + return false } diff --git a/internal/discovery/git_branch_test.go b/internal/discovery/git_branch_test.go index 3c75b1fc..b4367382 100644 --- a/internal/discovery/git_branch_test.go +++ b/internal/discovery/git_branch_test.go @@ -75,6 +75,7 @@ func TestGitBranchFinder(t *testing.T) { return nil, fmt.Errorf("mock git error: %v", args) }, includeAll, + nil, "main", 50, nil, @@ -90,6 +91,7 @@ func TestGitBranchFinder(t *testing.T) { return nil, fmt.Errorf("mock git error: %v", args) }, includeAll, + nil, "master", 50, nil, @@ -110,6 +112,7 @@ func TestGitBranchFinder(t *testing.T) { } }, includeAll, + nil, "main", 3, nil, @@ -130,6 +133,7 @@ func TestGitBranchFinder(t *testing.T) { } }, includeAll, + nil, "main", 4, nil, @@ -152,6 +156,7 @@ func TestGitBranchFinder(t *testing.T) { } }, includeAll, + nil, "main", 4, nil, @@ -180,6 +185,7 @@ func TestGitBranchFinder(t *testing.T) { } }, includeAll, + nil, "main", 4, nil, @@ -197,7 +203,7 @@ func TestGitBranchFinder(t *testing.T) { commitFile(t, "rules.yml", "# v2\n", "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, nil), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, nil), entries: nil, }, { @@ -222,7 +228,7 @@ groups: expr: count(up == 1) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, nil), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, nil), entries: nil, }, { @@ -247,7 +253,7 @@ groups: expr: count(up == 1) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, nil), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, nil), entries: []discovery.Entry{ { State: discovery.Modified, @@ -274,7 +280,7 @@ groups: expr: count(up == 1) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, includeAll), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, includeAll), entries: []discovery.Entry{ { State: discovery.Modified, @@ -301,7 +307,7 @@ groups: expr: count(up == 1) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, nil, "main", 4, includeAll), + finder: discovery.NewGitBranchFinder(git.RunGit, nil, nil, "main", 4, includeAll), entries: []discovery.Entry{ { State: discovery.Modified, @@ -334,7 +340,7 @@ groups: expr: count(up == 1) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, []*regexp.Regexp{regexp.MustCompile("^foo#")}, "main", 4, nil), + finder: discovery.NewGitBranchFinder(git.RunGit, []*regexp.Regexp{regexp.MustCompile("^foo#")}, nil, "main", 4, nil), entries: nil, }, { @@ -359,7 +365,7 @@ groups: expr: count(up == 1) `, "v2\nskip this commit\n[skip ci]\n") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, nil), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, nil), entries: nil, }, { @@ -384,7 +390,7 @@ groups: expr: count(up == 1) `, "v2\nskip this commit\n[no ci]\n") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, nil), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, nil), entries: nil, }, { @@ -404,7 +410,7 @@ groups: require.NoError(t, err, "git add") gitCommit(t, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, includeAll), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, includeAll), entries: []discovery.Entry{ { State: discovery.Added, @@ -447,7 +453,7 @@ groups: expr: count(up) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, nil), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, nil), entries: []discovery.Entry{ { State: discovery.Modified, @@ -502,7 +508,7 @@ groups: for: 0s `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, includeAll), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, includeAll), entries: []discovery.Entry{ { State: discovery.Modified, @@ -531,7 +537,7 @@ groups: expr: sum(foo) by(job) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, includeAll), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, includeAll), entries: []discovery.Entry{ { State: discovery.Removed, @@ -560,7 +566,7 @@ groups: expr: sum(foo) by(job) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, includeAll), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, includeAll), entries: []discovery.Entry{ { State: discovery.Removed, @@ -593,7 +599,7 @@ groups: expr: sum(foo) by(job) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, includeAll), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, includeAll), entries: []discovery.Entry{ { State: discovery.Removed, @@ -627,7 +633,7 @@ groups: expr: count(up) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, nil), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, nil), entries: []discovery.Entry{ { State: discovery.Added, @@ -676,7 +682,7 @@ groups: expr: sum(foo) by(job) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, includeAll), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, includeAll), entries: []discovery.Entry{ { State: discovery.Added, @@ -716,7 +722,7 @@ groups: expr: sum(foo) by(job) `, "v2") }, - finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, "main", 4, includeAll), + finder: discovery.NewGitBranchFinder(git.RunGit, includeAll, nil, "main", 4, includeAll), entries: []discovery.Entry{ { State: discovery.Modified,