Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add ignore path to autodiscover using glob #5267

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ require (
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/bmatcuk/doublestar/v4 v4.8.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cloudflare/circl v1.3.9 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bmatcuk/doublestar/v4 v4.8.0 h1:DSXtrypQddoug1459viM9X9D3dp1Z7993fw36I2kNcQ=
github.com/bmatcuk/doublestar/v4 v4.8.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/bradleyfalzon/ghinstallation/v2 v2.13.0 h1:5FhjW93/YLQJDmPdeyMPw7IjAPzqsr+0jHPfrPz0sZI=
github.com/bradleyfalzon/ghinstallation/v2 v2.13.0/go.mod h1:EJ6fgedVEHa2kUyBTTvslJCXJafS/mhJNNKEOCspZXQ=
github.com/briandowns/spinner v1.23.1 h1:t5fDPmScwUjozhDj4FA46p5acZWIPXYE30qW2Ptu650=
Expand Down
11 changes: 11 additions & 0 deletions runatlantis.io/docs/repo-level-atlantis-yaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ version: 3
automerge: true
autodiscover:
mode: auto
ignore_paths:
- some/path
delete_source_branch_on_merge: true
parallel_plan: true
parallel_apply: true
Expand Down Expand Up @@ -405,6 +407,15 @@ the manual configuration will take precedence.
Use this feature when some projects require specific configuration in a repo with many projects yet
it's still desirable for Atlantis to plan/apply for projects not enumerated in the config.

```yaml
autodiscover:
mode: "enabled"
ignore_paths:
- dir/*
```

Autodiscover can also be configured to skip over directories that match a path glob (as defined [here](https://pkg.go.dev/github.com/bmatcuk/doublestar/v4))

### Custom Backend Config

See [Custom Workflow Use Cases: Custom Backend Config](custom-workflows.md#custom-backend-config)
Expand Down
3 changes: 3 additions & 0 deletions runatlantis.io/docs/server-side-repo-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ repos:
# autodiscover defines how atlantis should automatically discover projects in this repository.
autodiscover:
mode: auto
# Optionally ignore some paths for autodiscovery by a glob path
ignore_paths:
- foo/*

# id can also be an exact match.
- id: github.com/myorg/specific-repo
Expand Down
35 changes: 33 additions & 2 deletions server/core/config/raw/autodiscover.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package raw

import (
"fmt"
"strings"

"github.com/bmatcuk/doublestar/v4"
validation "github.com/go-ozzo/ozzo-validation"
"github.com/pkg/errors"
"github.com/runatlantis/atlantis/server/core/config/valid"
)

var DefaultAutoDiscoverMode = valid.AutoDiscoverAutoMode

type AutoDiscover struct {
Mode *valid.AutoDiscoverMode `yaml:"mode,omitempty"`
Mode *valid.AutoDiscoverMode `yaml:"mode,omitempty"`
IgnorePaths []string `yaml:"ignore_paths,omitempty"`
}

func (a AutoDiscover) ToValid() *valid.AutoDiscover {
Expand All @@ -20,19 +26,44 @@ func (a AutoDiscover) ToValid() *valid.AutoDiscover {
v.Mode = DefaultAutoDiscoverMode
}

v.IgnorePaths = a.IgnorePaths

return &v
}

func (a AutoDiscover) Validate() error {

ignoreValid := func(value interface{}) error {
strSlice := value.([]string)
if strSlice == nil {
return nil
}
for _, ignore := range strSlice {
// A beginning slash isn't necessary since they are specifying a relative path, not an absolute one.
// Rejecting `/...` also allows us to potentially use `/.*/` as regexes in the future
if strings.HasPrefix(ignore, "/") {
return errors.New("pattern must not begin with a slash '/'")
}

if !doublestar.ValidatePattern(ignore) {
return fmt.Errorf("invalid pattern: %s", ignore)
}

}
return nil
}

res := validation.ValidateStruct(&a,
// If a.Mode is nil, this should still pass validation.
validation.Field(&a.Mode, validation.In(valid.AutoDiscoverAutoMode, valid.AutoDiscoverDisabledMode, valid.AutoDiscoverEnabledMode)),
validation.Field(&a.IgnorePaths, validation.By(ignoreValid)),
)
return res
}

func DefaultAutoDiscover() *valid.AutoDiscover {
return &valid.AutoDiscover{
Mode: DefaultAutoDiscoverMode,
Mode: DefaultAutoDiscoverMode,
IgnorePaths: nil,
}
}
80 changes: 77 additions & 3 deletions server/core/config/raw/autodiscover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@ func TestAutoDiscover_UnmarshalYAML(t *testing.T) {
description: "omit unset fields",
input: "",
exp: raw.AutoDiscover{
Mode: nil,
Mode: nil,
IgnorePaths: nil,
},
},
{
description: "all fields set",
input: `
mode: enabled
ignore_paths:
- foobar
`,
exp: raw.AutoDiscover{
Mode: &autoDiscoverEnabled,
Mode: &autoDiscoverEnabled,
IgnorePaths: []string{"foobar"},
},
},
}
Expand Down Expand Up @@ -86,6 +90,67 @@ func TestAutoDiscover_Validate(t *testing.T) {
},
errContains: String("valid value"),
},
{
description: "ignore set with leading slash",
input: raw.AutoDiscover{
Mode: &autoDiscoverAuto,
IgnorePaths: []string{
"/foo",
},
},
errContains: String("pattern must not begin with a slash '/'"),
},
{
description: `ignore set to broken pattern \`,
input: raw.AutoDiscover{
Mode: &autoDiscoverAuto,
IgnorePaths: []string{
`\`,
},
},
errContains: String(`invalid pattern: \`),
},
{
description: "ignore set to broken pattern [",
input: raw.AutoDiscover{
Mode: &autoDiscoverAuto,
IgnorePaths: []string{
"[",
},
},
errContains: String("invalid pattern: ["),
},
{
description: "ignore set to valid pattern",
input: raw.AutoDiscover{
Mode: &autoDiscoverAuto,
IgnorePaths: []string{
"foo*",
},
},
errContains: nil,
},
{
description: "ignore set to long pattern",
input: raw.AutoDiscover{
Mode: &autoDiscoverAuto,
IgnorePaths: []string{
"foo/**/bar/baz/??",
},
},
errContains: nil,
},
{
description: "ignore set to one valid and one invalid pattern",
input: raw.AutoDiscover{
Mode: &autoDiscoverAuto,
IgnorePaths: []string{
"foo",
"foo[",
},
},
errContains: String("invalid pattern: foo["),
},
}
for _, c := range cases {
t.Run(c.description, func(t *testing.T) {
Expand All @@ -109,16 +174,25 @@ func TestAutoDiscover_ToValid(t *testing.T) {
description: "nothing set",
input: raw.AutoDiscover{},
exp: &valid.AutoDiscover{
Mode: valid.AutoDiscoverAutoMode,
Mode: valid.AutoDiscoverAutoMode,
IgnorePaths: nil,
},
},
{
description: "value set",
input: raw.AutoDiscover{
Mode: &autoDiscoverEnabled,
IgnorePaths: []string{
"foo",
"bar/*",
},
},
exp: &valid.AutoDiscover{
Mode: valid.AutoDiscoverEnabledMode,
IgnorePaths: []string{
"foo",
"bar/*",
},
},
},
}
Expand Down
9 changes: 7 additions & 2 deletions server/core/config/raw/repo_cfg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ version: 3
automerge: true
autodiscover:
mode: enabled
ignore_paths:
- foo/*
parallel_apply: true
parallel_plan: false
repo_locks:
Expand Down Expand Up @@ -157,8 +159,11 @@ allowed_regexp_prefixes:
- dev/
- staging/`,
exp: raw.RepoCfg{
Version: Int(3),
AutoDiscover: &raw.AutoDiscover{Mode: &autoDiscoverEnabled},
Version: Int(3),
AutoDiscover: &raw.AutoDiscover{
Mode: &autoDiscoverEnabled,
IgnorePaths: []string{"foo/*"},
},
Automerge: Bool(true),
ParallelApply: Bool(true),
ParallelPlan: Bool(false),
Expand Down
3 changes: 2 additions & 1 deletion server/core/config/valid/autodiscover.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ const (
)

type AutoDiscover struct {
Mode AutoDiscoverMode
Mode AutoDiscoverMode
IgnorePaths []string
}
20 changes: 20 additions & 0 deletions server/core/config/valid/repo_cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"regexp"
"strings"

"github.com/bmatcuk/doublestar/v4"
version "github.com/hashicorp/go-version"
"github.com/pkg/errors"
)

// RepoCfg is the atlantis.yaml config after it's been parsed and validated.
Expand Down Expand Up @@ -111,6 +113,24 @@ func (r RepoCfg) AutoDiscoverEnabled(defaultAutoDiscoverMode AutoDiscoverMode) b
return autoDiscoverMode == AutoDiscoverEnabledMode
}

func (r RepoCfg) IsPathIgnoredForAutoDiscover(path string) (bool, error) {
if r.AutoDiscover == nil || r.AutoDiscover.IgnorePaths == nil {
return false, nil
}
for i := 0; i < len(r.AutoDiscover.IgnorePaths); i++ {
matches, err := doublestar.Match(r.AutoDiscover.IgnorePaths[i], path)
if err != nil {
// Per documentation https://pkg.go.dev/github.com/bmatcuk/doublestar, this only
// occurs if the pattern itself is invalid, and we already checked this when parsing raw config
return false, errors.Wrap(err, "unexpectedly found invalid ignore pattern (this is a bug, should have been validated at startup)")
}
if matches {
return true, nil
}
}
return false, nil
}

// validateWorkspaceAllowed returns an error if repoCfg defines projects in
// repoRelDir but none of them use workspace. We want this to be an error
// because if users have gone to the trouble of defining projects in repoRelDir
Expand Down
Loading
Loading