From 569cc3c7d1f9c02339b26ee84980c2ee9baa138f Mon Sep 17 00:00:00 2001 From: Aaron George Date: Thu, 16 Sep 2021 15:49:11 +0100 Subject: [PATCH 1/6] Add support for regex path based selection --- README.md | 3 ++- check.go | 24 ++++++++++++++++++++++++ check_test.go | 39 +++++++++++++++++++++++++++++++++++++++ models.go | 1 + 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d46077ff..a04d0973 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ Make sure to check out [#migrating](#migrating) to learn more. | `access_token` | Yes | | A Github Access Token with repository access (required for setting status on commits). N.B. If you want github-pr-resource to work with a private repository. Set `repo:full` permissions on the access token you create on GitHub. If it is a public repository, `repo:status` is enough. | | `v3_endpoint` | No | `https://api.github.com` | Endpoint to use for the V3 Github API (Restful). | | `v4_endpoint` | No | `https://api.github.com/graphql` | Endpoint to use for the V4 Github API (Graphql). | -| `paths` | No | `["terraform/*/*.tf"]` | Only produce new versions if the PR includes changes to files that match one or more glob patterns or prefixes. | +| `paths` | No | `["terraform/*/*.tf"]` | Only produce new versions if the PR includes changes to files that match one or more patterns (following the syntax of [filepath.Match](https://pkg.go.dev/path/filepath#Match) or prefixes. | +| `path_regexps` | No | `["^terraform/.*\.tf$"]` | Only produce new versions if the PR includes changes to files that match one or more regexps (following the syntax of [re2](https://github.com/google/re2/wiki/Syntax). | | `ignore_paths` | No | `[".ci/"]` | Inverse of the above. Pattern syntax is documented in [filepath.Match](https://golang.org/pkg/path/filepath/#Match), or a path prefix can be specified (e.g. `.ci/` will match everything in the `.ci` directory). | | `disable_ci_skip` | No | `true` | Disable ability to skip builds with `[ci skip]` and `[skip ci]` in commit message or pull request title. | | `skip_ssl_verification` | No | `true` | Disable SSL/TLS certificate validation on git and API clients. Use with care! | diff --git a/check.go b/check.go index 64df9e24..827fe3de 100644 --- a/check.go +++ b/check.go @@ -108,6 +108,18 @@ Loop: } } + // Skip version if no files match the specified paths. + if len(request.Source.PathRegexps) > 0 { + var wanted []string + for _, pattern := range request.Source.PathRegexps { + w := FilterPathRegexp(files, pattern) + wanted = append(wanted, w...) + } + if len(wanted) == 0 { + continue Loop + } + } + // Skip version if all files are ignored. if len(request.Source.IgnorePaths) > 0 { wanted := files @@ -174,6 +186,18 @@ func FilterPath(files []string, pattern string) ([]string, error) { return out, nil } +// FilterPathRegexp ... +func FilterPathRegexp(files []string, pattern string) []string { + var out []string + re := regexp.MustCompile(pattern) + for _, file := range files { + if re.MatchString(file) { + out = append(out, file) + } + } + return out +} + // IsInsidePath checks whether the child path is inside the parent path. // // /foo/bar is inside /foo, but /foobar is not inside /foo. diff --git a/check_test.go b/check_test.go index 8c422914..684779b0 100644 --- a/check_test.go +++ b/check_test.go @@ -416,6 +416,45 @@ func TestFilterPath(t *testing.T) { } } +func TestFilterPathRegexp(t *testing.T) { + cases := []struct { + description string + pattern string + files []string + want []string + }{ + { + description: "returns all matching files", + pattern: ".*", + files: []string{ + "file1.txt", + "test/file2.txt", + }, + want: []string{ + "file1.txt", + "test/file2.txt", + }, + }, + { + description: "returns all matching files", + pattern: "[a-z]+$", + files: []string{ + "file1", + "file", + }, + want: []string{ + "file", + }, + }, + } + for _, tc := range cases { + t.Run(tc.description, func(t *testing.T) { + got := resource.FilterPathRegexp(tc.files, tc.pattern) + assert.Equal(t, tc.want, got) + }) + } +} + func TestFilterIgnorePath(t *testing.T) { cases := []struct { description string diff --git a/models.go b/models.go index 9e4e7b1c..f956b80c 100644 --- a/models.go +++ b/models.go @@ -16,6 +16,7 @@ type Source struct { V3Endpoint string `json:"v3_endpoint"` V4Endpoint string `json:"v4_endpoint"` Paths []string `json:"paths"` + PathRegexps []string `json:"path_regexps"` IgnorePaths []string `json:"ignore_paths"` DisableCISkip bool `json:"disable_ci_skip"` DisableGitLFS bool `json:"disable_git_lfs"` From 7b294a98daf65d3411ce114891e941149375fb76 Mon Sep 17 00:00:00 2001 From: Aaron George Date: Thu, 16 Sep 2021 15:59:42 +0100 Subject: [PATCH 2/6] Add e2e test --- e2e/e2e_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 523838c2..f526e37b 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -90,6 +90,19 @@ func TestCheckE2E(t *testing.T) { }, }, + { + description: "check will only return versions that match the specified path regexps", + source: resource.Source{ + Repository: "itsdalmo/test-repository", + AccessToken: os.Getenv("GITHUB_ACCESS_TOKEN"), + Paths: []string{".*.md"}, + }, + version: resource.Version{}, + expected: resource.CheckResponse{ + resource.Version{PR: targetPullRequestID, Commit: targetCommitID, CommittedDate: targetDateTime}, + }, + }, + { description: "check will skip versions which only match the ignore paths", source: resource.Source{ From f36c1a21184ccc7273d972ac8b12248498923435 Mon Sep 17 00:00:00 2001 From: Aaron George Date: Mon, 20 Sep 2021 10:22:49 +0100 Subject: [PATCH 3/6] Tests --- e2e/e2e_test.go | 15 ++++++++++++++- go.sum | 5 +++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index f526e37b..e537f62b 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -95,7 +95,20 @@ func TestCheckE2E(t *testing.T) { source: resource.Source{ Repository: "itsdalmo/test-repository", AccessToken: os.Getenv("GITHUB_ACCESS_TOKEN"), - Paths: []string{".*.md"}, + PathRegexps: []string{".*.md"}, + }, + version: resource.Version{}, + expected: resource.CheckResponse{ + resource.Version{PR: targetPullRequestID, Commit: targetCommitID, CommittedDate: targetDateTime}, + }, + }, + + { + description: "check will only return versions that match the specified path regexps", + source: resource.Source{ + Repository: "itsdalmo/test-repository", + AccessToken: os.Getenv("GITHUB_ACCESS_TOKEN"), + PathRegexps: []string{"^."}, }, version: resource.Version{}, expected: resource.CheckResponse{ diff --git a/go.sum b/go.sum index 82ec24e7..45de6c16 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -26,6 +27,7 @@ github.com/joefitzgerald/rainbow-reporter v0.1.0 h1:AuMG652zjdzI0YCCnXAqATtRBpGX github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -47,9 +49,11 @@ github.com/shurcooL/githubv4 v0.0.0-20200414012201-bbc966b061dd h1:EwtC+kDj8s9OK github.com/shurcooL/githubv4 v0.0.0-20200414012201-bbc966b061dd/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo= github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f h1:tygelZueB1EtXkPI6mQ4o9DQ0+FKW41hTbunoXZCTqk= github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/yuin/goldmark v1.1.27 h1:nqDD4MMMQA0lmWq03Z2/myGPYLQoXtmi0rGVs95ntbo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -80,6 +84,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 9c9e3f152c93dda274f53d7c76f8aa9d3c3bc703 Mon Sep 17 00:00:00 2001 From: Aaron George Date: Mon, 20 Sep 2021 12:34:24 +0100 Subject: [PATCH 4/6] Try and fix --- check.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/check.go b/check.go index 827fe3de..a802acbb 100644 --- a/check.go +++ b/check.go @@ -2,6 +2,7 @@ package resource import ( "fmt" + "os" "path/filepath" "regexp" "sort" @@ -86,7 +87,7 @@ Loop: // Fetch files once if paths/ignore_paths are specified. var files []string - if len(request.Source.Paths) > 0 || len(request.Source.IgnorePaths) > 0 { + if len(request.Source.Paths) > 0 || len(request.Source.IgnorePaths) > 0 || len(request.Source.PathRegexps) > 0 { files, err = manager.ListModifiedFiles(p.Number) if err != nil { return nil, fmt.Errorf("failed to list modified files: %s", err) @@ -190,6 +191,7 @@ func FilterPath(files []string, pattern string) ([]string, error) { func FilterPathRegexp(files []string, pattern string) []string { var out []string re := regexp.MustCompile(pattern) + fmt.Fprintf(os.Stderr, "Checking %v against %v\n", pattern, files) for _, file := range files { if re.MatchString(file) { out = append(out, file) From ead63306035d2e1fef626d27a42509d4b1cb1bae Mon Sep 17 00:00:00 2001 From: Aaron George Date: Mon, 20 Sep 2021 12:44:55 +0100 Subject: [PATCH 5/6] Remove temporary logging --- check.go | 1 - 1 file changed, 1 deletion(-) diff --git a/check.go b/check.go index a802acbb..3610966a 100644 --- a/check.go +++ b/check.go @@ -191,7 +191,6 @@ func FilterPath(files []string, pattern string) ([]string, error) { func FilterPathRegexp(files []string, pattern string) []string { var out []string re := regexp.MustCompile(pattern) - fmt.Fprintf(os.Stderr, "Checking %v against %v\n", pattern, files) for _, file := range files { if re.MatchString(file) { out = append(out, file) From e5eb57bab8cb463e4e7643cd3992664b01f5fdbc Mon Sep 17 00:00:00 2001 From: Aaron George Date: Tue, 21 Sep 2021 12:32:56 +0100 Subject: [PATCH 6/6] Remove unused os import --- check.go | 1 - 1 file changed, 1 deletion(-) diff --git a/check.go b/check.go index 3610966a..474cf4a6 100644 --- a/check.go +++ b/check.go @@ -2,7 +2,6 @@ package resource import ( "fmt" - "os" "path/filepath" "regexp" "sort"