feat: multi-repo patterns + directory recursion
patterns-repo now accepts a comma-separated list of repos: PATTERNS_REPO="rodin/elixir-patterns,rodin/phoenix-conventions" patterns-files accepts files AND directories: PATTERNS_FILES="README.md,docs/" When a path is a directory, all files within it are fetched recursively via the Gitea contents API. Only .md, .txt, .yml, and .yaml files are included as pattern content. New API methods: - ListContents: list files/dirs at a path via contents API - GetAllFilesInPath: recursively fetch all file contents This allows a single review action to pull idioms from multiple pattern repos (e.g. elixir-patterns + phoenix-conventions) and include entire directories of documentation as review criteria.
This commit is contained in:
+45
-15
@@ -184,31 +184,61 @@ func fetchFileContext(client *gitea.Client, owner, repo, ref string, files []git
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// fetchPatterns fetches pattern files from an external repo.
|
||||
// fetchPatterns fetches pattern files from one or more external repos.
|
||||
// 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.
|
||||
func fetchPatterns(client *gitea.Client, patternsRepo, patternsFiles string) string {
|
||||
parts := strings.SplitN(patternsRepo, "/", 2)
|
||||
if len(parts) != 2 {
|
||||
log.Printf("Warning: invalid patterns-repo format %q, expected owner/name", patternsRepo)
|
||||
return ""
|
||||
}
|
||||
owner, repo := parts[0], parts[1]
|
||||
|
||||
var sb strings.Builder
|
||||
for _, filepath := range strings.Split(patternsFiles, ",") {
|
||||
filepath = strings.TrimSpace(filepath)
|
||||
if filepath == "" {
|
||||
|
||||
repos := strings.Split(patternsRepo, ",")
|
||||
paths := strings.Split(patternsFiles, ",")
|
||||
|
||||
for _, repoRef := range repos {
|
||||
repoRef = strings.TrimSpace(repoRef)
|
||||
if repoRef == "" {
|
||||
continue
|
||||
}
|
||||
content, err := client.GetFileContent(owner, repo, filepath)
|
||||
if err != nil {
|
||||
log.Printf("Warning: could not fetch pattern file %s from %s: %v", filepath, patternsRepo, err)
|
||||
parts := strings.SplitN(repoRef, "/", 2)
|
||||
if len(parts) != 2 {
|
||||
log.Printf("Warning: invalid patterns-repo format %q, expected owner/name", repoRef)
|
||||
continue
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("### %s/%s\n\n%s\n\n", patternsRepo, filepath, content))
|
||||
owner, repo := parts[0], parts[1]
|
||||
|
||||
for _, path := range paths {
|
||||
path = strings.TrimSpace(path)
|
||||
if path == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
files, err := client.GetAllFilesInPath(owner, repo, path)
|
||||
if err != nil {
|
||||
log.Printf("Warning: could not fetch %s from %s: %v", path, repoRef, err)
|
||||
continue
|
||||
}
|
||||
|
||||
for filepath, content := range files {
|
||||
// Only include markdown and text files as patterns
|
||||
if !isPatternFile(filepath) {
|
||||
continue
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("### %s/%s\n\n%s\n\n", repoRef, filepath, content))
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// isPatternFile returns true if the file should be included as pattern content.
|
||||
func isPatternFile(path string) bool {
|
||||
lower := strings.ToLower(path)
|
||||
return strings.HasSuffix(lower, ".md") ||
|
||||
strings.HasSuffix(lower, ".txt") ||
|
||||
strings.HasSuffix(lower, ".yml") ||
|
||||
strings.HasSuffix(lower, ".yaml")
|
||||
}
|
||||
|
||||
// evaluateCIStatus checks if all CI statuses indicate success.
|
||||
func evaluateCIStatus(statuses []gitea.CommitStatus) (passed bool, details string) {
|
||||
if len(statuses) == 0 {
|
||||
|
||||
Reference in New Issue
Block a user