dd6c6c610f
CI / test (pull_request) Successful in 14s
CI / review (gpt-4.1, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 26s
CI / review (gpt-5, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 1m34s
CI / review (gpt-5, security, SECURITY_REVIEW.md, SONNET_REVIEW_TOKEN) (pull_request) Successful in 1m48s
When reviewer-name is set, prepend "# Security Review" / "# Sonnet Review" etc. as a top-level header. Makes it immediately obvious which role each review represents in the Gitea UI, especially when multiple reviews come from the same bot account.
56 lines
1.5 KiB
Go
56 lines
1.5 KiB
Go
package review
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// FormatMarkdown formats a ReviewResult into the markdown body for a Gitea review.
|
|
func FormatMarkdown(result *ReviewResult, reviewerName string) string {
|
|
var sb strings.Builder
|
|
|
|
if reviewerName != "" {
|
|
title := strings.ToUpper(reviewerName[:1]) + reviewerName[1:]
|
|
sb.WriteString(fmt.Sprintf("# %s Review\n\n", title))
|
|
}
|
|
|
|
sb.WriteString("## Summary\n\n")
|
|
sb.WriteString(result.Summary)
|
|
sb.WriteString("\n\n")
|
|
|
|
if len(result.Findings) > 0 {
|
|
sb.WriteString("## Findings\n\n")
|
|
sb.WriteString("| # | Severity | File | Line | Finding |\n")
|
|
sb.WriteString("|---|----------|------|------|--------|\n")
|
|
|
|
for i, f := range result.Findings {
|
|
sb.WriteString(fmt.Sprintf("| %d | [%s] | `%s` | %d | %s |\n",
|
|
i+1, f.Severity, f.File, f.Line, f.Finding))
|
|
}
|
|
sb.WriteString("\n")
|
|
}
|
|
|
|
sb.WriteString("## Recommendation\n\n")
|
|
sb.WriteString(fmt.Sprintf("**%s** — %s\n", result.Verdict, result.Recommendation))
|
|
|
|
if reviewerName != "" {
|
|
sb.WriteString(fmt.Sprintf("\n---\n*Review by %s*\n", reviewerName))
|
|
// Hidden sentinel for identifying this bot's reviews during cleanup
|
|
sb.WriteString(fmt.Sprintf("\n<!-- review-bot:%s -->\n", reviewerName))
|
|
}
|
|
|
|
return sb.String()
|
|
}
|
|
|
|
// GiteaEvent converts the verdict to the Gitea API event string.
|
|
func GiteaEvent(verdict string) string {
|
|
switch verdict {
|
|
case "APPROVE":
|
|
return "APPROVED"
|
|
case "REQUEST_CHANGES":
|
|
return "REQUEST_CHANGES"
|
|
default:
|
|
return "COMMENT"
|
|
}
|
|
}
|