-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9ab9c9c
commit 920869a
Showing
4 changed files
with
359 additions
and
197 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package ignore | ||
|
||
import ( | ||
"context" | ||
"strings" | ||
|
||
"github.com/keboola/keboola-as-code/internal/pkg/filesystem" | ||
"github.com/keboola/keboola-as-code/internal/pkg/state" | ||
"github.com/keboola/keboola-as-code/internal/pkg/utils/errors" | ||
) | ||
|
||
const KBCIgnoreFilePath = ".keboola/kbc_ignore" | ||
|
||
type File struct { | ||
rawStringPattern string | ||
state *state.Registry | ||
} | ||
|
||
func newFile(pattern string, state *state.Registry) *File { | ||
return &File{ | ||
rawStringPattern: pattern, | ||
state: state, | ||
} | ||
} | ||
|
||
func LoadFile(ctx context.Context, fs filesystem.Fs, state *state.Registry, path string) (*File, error) { | ||
if !fs.Exists(ctx, path) { | ||
return nil, errors.Errorf("ignore file \"%s\" not found", path) | ||
} | ||
|
||
content, err := fs.ReadFile(ctx, filesystem.NewFileDef(path)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
f := &File{ | ||
state: state, | ||
rawStringPattern: content.Content, | ||
} | ||
|
||
return f, nil | ||
} | ||
|
||
func (f *File) IgnoreConfigsOrRows() error { | ||
return f.applyIgnoredPatterns() | ||
} | ||
|
||
func (f *File) parseIgnoredPatterns() []string { | ||
var ignorePatterns []string | ||
lines := strings.Split(f.rawStringPattern, "\n") | ||
for _, line := range lines { | ||
trimmedLine := strings.TrimSpace(line) | ||
// Skip empty lines and comments | ||
if trimmedLine != "" && !strings.HasPrefix(trimmedLine, "#") { | ||
ignorePatterns = append(ignorePatterns, trimmedLine) | ||
} | ||
} | ||
|
||
return ignorePatterns | ||
} | ||
|
||
// applyIgnorePattern applies a single ignore pattern, marking the appropriate config or row as ignored. | ||
func (f *File) applyIgnorePattern(ignoreConfig string) error { | ||
parts := strings.Split(ignoreConfig, "/") | ||
|
||
switch len(parts) { | ||
case 2: | ||
// Ignore config by ID and name. | ||
configID, componentID := parts[1], parts[0] | ||
f.state.IgnoreConfig(configID, componentID) | ||
case 3: | ||
// Ignore specific config row. | ||
configID, rowID := parts[1], parts[2] | ||
f.state.IgnoreConfigRow(configID, rowID) | ||
default: | ||
return errors.Errorf("invalid ignore ignoreConfig format: %s", ignoreConfig) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// applyIgnoredPatterns parses the content for ignore patterns and applies them to configurations or rows. | ||
func (f *File) applyIgnoredPatterns() error { | ||
for _, pattern := range f.parseIgnoredPatterns() { | ||
if err := f.applyIgnorePattern(pattern); err != nil { | ||
continue | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
package ignore | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/keboola/keboola-as-code/internal/pkg/filesystem" | ||
"github.com/keboola/keboola-as-code/internal/pkg/filesystem/aferofs" | ||
"github.com/keboola/keboola-as-code/internal/pkg/filesystem/knownpaths" | ||
"github.com/keboola/keboola-as-code/internal/pkg/model" | ||
"github.com/keboola/keboola-as-code/internal/pkg/naming" | ||
"github.com/keboola/keboola-as-code/internal/pkg/state/registry" | ||
) | ||
|
||
func Test_loadFile(t *testing.T) { | ||
t.Parallel() | ||
ctx := context.Background() | ||
|
||
projectState := newTestRegistry(t) | ||
|
||
fs := aferofs.NewMemoryFs() | ||
require.NoError(t, fs.WriteFile(ctx, filesystem.NewRawFile(`foo/bar1`, "keboola.bar/678/34\nkeboola.foo/345"))) | ||
|
||
file, err := LoadFile(ctx, fs, projectState, "foo/bar1") | ||
require.NoError(t, err) | ||
|
||
assert.Equal(t, "keboola.bar/678/34\nkeboola.foo/345", file.rawStringPattern) | ||
|
||
assert.NoError(t, file.IgnoreConfigsOrRows()) | ||
|
||
assert.Len(t, projectState.IgnoredConfigRows(), 1) | ||
assert.Len(t, projectState.IgnoredConfigs(), 1) | ||
assert.Equal(t, projectState.IgnoredConfigRows()[0].ID.String(), "34") | ||
assert.Equal(t, projectState.IgnoredConfigs()[0].ID.String(), "345") | ||
} | ||
|
||
func Test_applyIgnoredPatterns(t *testing.T) { | ||
t.Parallel() | ||
projectState := newTestRegistry(t) | ||
|
||
type args struct { | ||
pattern string | ||
} | ||
|
||
file := &File{ | ||
state: projectState, | ||
} | ||
|
||
tests := []struct { | ||
name string | ||
args args | ||
wantErr assert.ErrorAssertionFunc | ||
}{ | ||
{ | ||
name: "empty patterns", | ||
args: args{ | ||
pattern: "", | ||
}, | ||
wantErr: assert.Error, | ||
}, | ||
{ | ||
name: "wrong pattern", | ||
args: args{ | ||
pattern: "wrong pattern", | ||
}, | ||
wantErr: assert.Error, | ||
}, | ||
{ | ||
name: "too long pattern", | ||
args: args{ | ||
pattern: "keboola.bar/687/1234/1234", | ||
}, | ||
wantErr: assert.Error, | ||
}, | ||
{ | ||
name: "short pattern", | ||
args: args{ | ||
pattern: "keboola.bar", | ||
}, | ||
wantErr: assert.Error, | ||
}, | ||
{ | ||
name: "correct pattern", | ||
args: args{ | ||
pattern: "keboola.bar/687", | ||
}, | ||
wantErr: assert.NoError, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
t.Parallel() | ||
tt.wantErr(t, file.applyIgnorePattern(tt.args.pattern), fmt.Sprintf("applyIgnoredPatterns(%v)", tt.args.pattern)) | ||
}) | ||
} | ||
} | ||
|
||
func Test_parseIgnoredPatterns(t *testing.T) { | ||
t.Parallel() | ||
|
||
projectState := newTestRegistry(t) | ||
|
||
type args struct { | ||
content string | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want []string | ||
}{ | ||
{ | ||
name: "with comments", | ||
args: args{ | ||
content: "##dataapps\nkeboola.data-apps/12345\n##dataapps2\nkeboola.data-apps/123/rowId123\n##dataaps3\nkeboola.data-apps/12", | ||
}, | ||
want: []string{ | ||
"keboola.data-apps/12345", | ||
"keboola.data-apps/123/rowId123", | ||
"keboola.data-apps/12", | ||
}, | ||
}, | ||
{ | ||
name: "with empty lines", | ||
args: args{ | ||
content: "##dataapps\n\n\n\n\n\nkeboola.data-apps/12345\n\t##dataapps2\nkeboola.data-apps/123\n##dataaps3\nkeboola.data-apps/12", | ||
}, | ||
want: []string{ | ||
"keboola.data-apps/12345", | ||
"keboola.data-apps/123", | ||
"keboola.data-apps/12", | ||
}, | ||
}, | ||
{ | ||
name: "empty file", | ||
args: args{ | ||
content: "\n", | ||
}, | ||
want: nil, | ||
}, | ||
{ | ||
name: "error", | ||
args: args{ | ||
content: "##dataapps\n\n\n\n\n\nkeboola.data-apps/12345\n\t##dataapps2\nkeboola.data-apps/123\n##dataaps3\nkeboola.data-apps/12", | ||
}, | ||
want: []string{ | ||
"keboola.data-apps/12345", | ||
"keboola.data-apps/123", | ||
"keboola.data-apps/12", | ||
}, | ||
}, | ||
{ | ||
name: "empty file", | ||
args: args{ | ||
content: "\n", | ||
}, | ||
want: nil, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
file := newFile(tt.args.content, projectState) | ||
got := file.parseIgnoredPatterns() | ||
assert.Equal(t, tt.want, got) | ||
} | ||
} | ||
|
||
func newTestRegistry(t *testing.T) *registry.Registry { | ||
t.Helper() | ||
|
||
r := registry.New(knownpaths.NewNop(context.Background()), naming.NewRegistry(), model.NewComponentsMap(nil), model.SortByPath) | ||
// Branch 1 | ||
branch1Key := model.BranchKey{ID: 123} | ||
branch1 := &model.BranchState{ | ||
BranchManifest: &model.BranchManifest{ | ||
BranchKey: branch1Key, | ||
}, | ||
Local: &model.Branch{ | ||
Name: "Main", | ||
IsDefault: true, | ||
}, | ||
} | ||
assert.NoError(t, r.Set(branch1)) | ||
|
||
// Branch 2 | ||
branch2Key := model.BranchKey{ID: 567} | ||
branch2 := &model.BranchState{ | ||
BranchManifest: &model.BranchManifest{ | ||
BranchKey: branch2Key, | ||
}, | ||
Local: &model.Branch{ | ||
Name: "Foo Bar Branch", | ||
IsDefault: false, | ||
}, | ||
} | ||
assert.NoError(t, r.Set(branch2)) | ||
|
||
// Config 1 | ||
config1Key := model.ConfigKey{BranchID: 123, ComponentID: "keboola.foo", ID: `345`} | ||
config1 := &model.ConfigState{ | ||
ConfigManifest: &model.ConfigManifest{ConfigKey: config1Key}, | ||
Local: &model.Config{ | ||
Name: "Config 1", | ||
}, | ||
} | ||
assert.NoError(t, r.Set(config1)) | ||
|
||
// Config 2 | ||
config2Key := model.ConfigKey{BranchID: 123, ComponentID: "keboola.bar", ID: `678`} | ||
config2 := &model.ConfigState{ | ||
ConfigManifest: &model.ConfigManifest{ConfigKey: config2Key}, | ||
Local: &model.Config{ | ||
Name: "Config 2", | ||
}, | ||
} | ||
assert.NoError(t, r.Set(config2)) | ||
|
||
// Config Row 1 | ||
row1Key := model.ConfigRowKey{BranchID: 123, ComponentID: "keboola.bar", ConfigID: `678`, ID: `12`} | ||
row1 := &model.ConfigRowState{ | ||
ConfigRowManifest: &model.ConfigRowManifest{ConfigRowKey: row1Key}, | ||
Local: &model.ConfigRow{ | ||
Name: "Config Row 1", | ||
}, | ||
} | ||
assert.NoError(t, r.Set(row1)) | ||
|
||
// Config Row 2 | ||
row2Key := model.ConfigRowKey{BranchID: 123, ComponentID: "keboola.bar", ConfigID: `678`, ID: `34`} | ||
row2 := &model.ConfigRowState{ | ||
ConfigRowManifest: &model.ConfigRowManifest{ConfigRowKey: row2Key}, | ||
Local: &model.ConfigRow{ | ||
Name: "Config Row 2", | ||
}, | ||
} | ||
assert.NoError(t, r.Set(row2)) | ||
|
||
return r | ||
} |
Oops, something went wrong.