diff --git a/pkg/lint/service.go b/pkg/lint/service.go index 9b3e09e..4734fd6 100644 --- a/pkg/lint/service.go +++ b/pkg/lint/service.go @@ -420,6 +420,9 @@ func collectConfiguredFiles(projectPath string, paths []string, excludes []strin addFile := func(candidate string) { relativePath := relativeConfiguredPath(projectPath, candidate) + if hasHiddenDirectory(relativePath) || hasHiddenDirectory(filepath.ToSlash(filepath.Clean(candidate))) { + return + } if matchesConfiguredExclude(relativePath, excludes) || matchesConfiguredExclude(filepath.ToSlash(filepath.Clean(candidate)), excludes) { return } @@ -493,6 +496,22 @@ func matchesConfiguredExclude(candidate string, excludes []string) bool { return false } +func hasHiddenDirectory(candidate string) bool { + if candidate == "" { + return false + } + + for _, segment := range strings.Split(filepath.ToSlash(filepath.Clean(candidate)), "/") { + if segment == "" || segment == "." || segment == ".." { + continue + } + if strings.HasPrefix(segment, ".") { + return true + } + } + return false +} + func enabledToolNames(config LintConfig, languages []string, input RunInput, categories []string) []string { var names []string diff --git a/pkg/lint/service_test.go b/pkg/lint/service_test.go index 0d50bc2..fe8ea91 100644 --- a/pkg/lint/service_test.go +++ b/pkg/lint/service_test.go @@ -189,6 +189,48 @@ func Run() { assert.True(t, report.Summary.Passed) } +func TestServiceRun_Good_SkipsHiddenConfiguredFilePath(t *testing.T) { + dir := t.TempDir() + require.NoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module example.com/test\n"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(dir, "root.go"), []byte(`package sample + +type service struct{} + +func (service) Process(string) error { return nil } + +func Run() { + svc := service{} + _ = svc.Process("root") +} +`), 0o644)) + require.NoError(t, os.MkdirAll(filepath.Join(dir, ".hidden"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(dir, ".hidden", "scoped.go"), []byte(`package sample + +type service struct{} + +func (service) Process(string) error { return nil } + +func Run() { + svc := service{} + _ = svc.Process("hidden") +} +`), 0o644)) + require.NoError(t, os.MkdirAll(filepath.Join(dir, ".core"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(dir, ".core", "lint.yaml"), []byte("paths:\n - root.go\n - .hidden/scoped.go\n"), 0o644)) + + svc := &Service{adapters: []Adapter{newCatalogAdapter()}} + report, err := svc.Run(context.Background(), RunInput{ + Path: dir, + FailOn: "warning", + }) + require.NoError(t, err) + + require.Len(t, report.Findings, 1) + assert.Equal(t, "root.go", report.Findings[0].File) + assert.Equal(t, 1, report.Summary.Total) + assert.False(t, report.Summary.Passed) +} + func TestServiceRun_Good_UsesNamedSchedule(t *testing.T) { dir := t.TempDir() require.NoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module example.com/test\n"), 0o644))