From 6f86e66943d746dc1cd7ec27cd068f226c743377 Mon Sep 17 00:00:00 2001 From: Rodin <4+rodin@noreply.gitea.weiker.me> Date: Mon, 11 May 2026 17:45:19 +0000 Subject: [PATCH] fix(patterns): default patterns-files to empty (fetch all) (#77) --- cmd/review-bot/main.go | 23 +++++++++++++------ cmd/review-bot/main_test.go | 46 +++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/cmd/review-bot/main.go b/cmd/review-bot/main.go index f8bf815..1289a99 100644 --- a/cmd/review-bot/main.go +++ b/cmd/review-bot/main.go @@ -65,7 +65,7 @@ func main() { conventionsFile := flag.String("conventions-file", envOrDefault("CONVENTIONS_FILE", ""), "Conventions file path in repo (e.g. CLAUDE.md)") systemPromptFile := flag.String("system-prompt-file", envOrDefault("SYSTEM_PROMPT_FILE", ""), "Local file with additional system prompt instructions") patternsRepo := flag.String("patterns-repo", envOrDefault("PATTERNS_REPO", ""), "Repo with language patterns (e.g. rodin/elixir-patterns)") - patternsFiles := flag.String("patterns-files", envOrDefault("PATTERNS_FILES", "README.md"), "Comma-separated file paths to fetch from patterns repo") + patternsFiles := flag.String("patterns-files", envOrDefault("PATTERNS_FILES", ""), "Comma-separated file paths to fetch from patterns repo (empty = all files)") dryRun := flag.Bool("dry-run", false, "Print review to stdout instead of posting") llmTemp := flag.Float64("llm-temperature", envOrDefaultFloat("LLM_TEMPERATURE", 0), "LLM temperature (0 = server default)") llmTimeout := flag.Int("llm-timeout", envOrDefaultInt("LLM_TIMEOUT", 300), "LLM request timeout in seconds (default 300)") @@ -523,11 +523,25 @@ func fetchFileContext(ctx context.Context, client *gitea.Client, owner, repo, re // patternsRepo is comma-separated list of owner/name repos. // patternsFiles is comma-separated list of file paths or directories. // If a path ends with / or is a directory, all files within it are fetched recursively. +// If patternsFiles is empty, all files from the repo root are fetched. func fetchPatterns(ctx context.Context, client *gitea.Client, patternsRepo, patternsFiles string) string { var sb strings.Builder repos := strings.Split(patternsRepo, ",") - paths := strings.Split(patternsFiles, ",") + + // Build the list of paths to fetch + var paths []string + if patternsFiles == "" { + // Empty patternsFiles means "fetch all files from repo root" + paths = []string{""} + } else { + for _, p := range strings.Split(patternsFiles, ",") { + p = strings.TrimSpace(p) + if p != "" { + paths = append(paths, p) + } + } + } for _, repoRef := range repos { if ctx.Err() != nil { @@ -548,11 +562,6 @@ func fetchPatterns(ctx context.Context, client *gitea.Client, patternsRepo, patt var repoSkippedFiles []string for _, path := range paths { - path = strings.TrimSpace(path) - if path == "" { - continue - } - files, err := client.GetAllFilesInPath(ctx, owner, repo, path) if err != nil { slog.Warn("could not fetch patterns", "path", path, "repo", repoRef, "error", err) diff --git a/cmd/review-bot/main_test.go b/cmd/review-bot/main_test.go index 184af89..539d1b7 100644 --- a/cmd/review-bot/main_test.go +++ b/cmd/review-bot/main_test.go @@ -504,6 +504,52 @@ func TestIsPatternFile(t *testing.T) { } } +// TestBuildPatternPaths verifies the path-building logic for fetchPatterns. +// Empty patternsFiles means "fetch all from root" (represented as [""]). +func TestBuildPatternPaths(t *testing.T) { + buildPaths := func(patternsFiles string) []string { + if patternsFiles == "" { + return []string{""} + } + var paths []string + for _, p := range strings.Split(patternsFiles, ",") { + p = strings.TrimSpace(p) + if p != "" { + paths = append(paths, p) + } + } + return paths + } + + tests := []struct { + name string + input string + want []string + }{ + {"empty fetches root", "", []string{""}}, + {"single file", "README.md", []string{"README.md"}}, + {"multiple files", "README.md,PATTERNS.md", []string{"README.md", "PATTERNS.md"}}, + {"trims whitespace", " foo.md , bar.md ", []string{"foo.md", "bar.md"}}, + {"skips empty between commas", "foo.md,,bar.md", []string{"foo.md", "bar.md"}}, + {"directory path", "patterns/", []string{"patterns/"}}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got := buildPaths(tc.input) + if len(got) != len(tc.want) { + t.Errorf("buildPaths(%q) = %v, want %v", tc.input, got, tc.want) + return + } + for i := range got { + if got[i] != tc.want[i] { + t.Errorf("buildPaths(%q)[%d] = %q, want %q", tc.input, i, got[i], tc.want[i]) + } + } + }) + } +} + func TestEvaluateCIStatus(t *testing.T) { tests := []struct { name string