feat. rebuild service in Go
ci / test (pull_request) Successful in 1m54s
ci / publish (pull_request) Has been skipped

Rebuild the Gitea Codex review bot from the product contract with a Go HTTP service, durable SQL queue, typed Gitea client, isolated runner, and deployment updates.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Space-Banane
2026-07-12 21:51:01 +02:00
parent fdd3819ff8
commit f19b271642
74 changed files with 2623 additions and 4819 deletions
+180
View File
@@ -0,0 +1,180 @@
package domain
import (
"context"
"errors"
"strings"
"time"
)
type JobStatus string
const (
JobQueued JobStatus = "queued"
JobRunning JobStatus = "running"
JobSucceeded JobStatus = "succeeded"
JobFailed JobStatus = "failed"
JobSkipped JobStatus = "skipped"
)
type RunStatus string
const (
RunRunning RunStatus = "running"
RunSucceeded RunStatus = "succeeded"
RunFailed RunStatus = "failed"
RunSkipped RunStatus = "skipped"
)
type ParsedCommand struct {
Name string
Alias string
Raw string
Mode string
ModeExplicit bool
Full bool
Arguments []string
}
func (c ParsedCommand) IsReview() bool { return c.Name == "review" || c.Name == "rerun" }
type RepoReviewConfig struct {
Configured bool
Enabled bool
DefaultMode string
MaxDiffBytes int
IncludeTests bool
Focus []string
Ignore []string
}
func DefaultRepoReviewConfig() RepoReviewConfig {
return RepoReviewConfig{Configured: true, Enabled: true, DefaultMode: "full", MaxDiffBytes: 200000, Focus: []string{"correctness", "security", "maintainability"}}
}
type PullRequestContext struct {
Repo string
PRNumber int
BaseRef string
BaseSHA string
HeadRef string
HeadSHA string
CloneURL string
BaseCloneURL string
HeadCloneURL string
HTMLURL string
IsFork bool
}
type Finding struct {
Severity string `json:"severity"`
File string `json:"file"`
LineStart int `json:"line_start"`
LineEnd int `json:"line_end"`
Title string `json:"title"`
Body string `json:"body"`
Suggestion *string `json:"suggestion"`
}
type Usage struct {
InputTokens int `json:"input_tokens,omitempty"`
OutputTokens int `json:"output_tokens,omitempty"`
TotalTokens int `json:"total_tokens,omitempty"`
}
type ReviewMeta struct {
Source string `json:"source,omitempty"`
Model string `json:"model,omitempty"`
Usage Usage `json:"usage,omitempty"`
}
type ReviewResult struct {
Verdict string `json:"verdict"`
Confidence float64 `json:"confidence"`
Summary string `json:"summary"`
MarkdownComment string `json:"markdown_comment"`
Findings []Finding `json:"findings"`
Meta *ReviewMeta `json:"_meta,omitempty"`
}
func (r ReviewResult) Validate() error {
if r.Verdict != "correct" && r.Verdict != "has_issues" {
return errors.New("invalid verdict")
}
if r.Confidence < 0 || r.Confidence > 1 {
return errors.New("confidence must be between 0 and 1")
}
if len(r.Summary) > 20000 || len(r.MarkdownComment) > 50000 {
return errors.New("review text is too long")
}
if len(r.Findings) > 200 {
return errors.New("too many findings")
}
for i, f := range r.Findings {
if f.Severity != "low" && f.Severity != "medium" && f.Severity != "high" && f.Severity != "critical" {
return errors.New("invalid finding severity")
}
if f.File == "" || len(f.File) > 1000 || f.LineStart < 1 || f.LineEnd < f.LineStart {
return errors.New("invalid finding location")
}
if len(f.Title) > 2000 || len(f.Body) > 20000 {
return errors.New("finding text is too long")
}
if f.Suggestion != nil && len(*f.Suggestion) > 20000 {
return errors.New("suggestion is too long")
}
_ = i
}
return nil
}
type WebhookEvent struct {
EventName string
DeliveryID string
Repo string
PRNumber int
HeadSHA string
CommentID int64
CommentBody string
Sender string
PayloadSHA256 string
}
type Job struct {
ID int64
Repo string
PRNumber int
HeadSHA string
TriggerCommentID int64
TriggerCommentBody string
Command string
CommandArgs string
RequestedBy string
Status JobStatus
LastError string
ResultJSON []byte
CreatedAt time.Time
UpdatedAt time.Time
StartedAt *time.Time
FinishedAt *time.Time
}
type ReviewRun struct {
ID int64
JobID int64
Status RunStatus
ContainerID string
ResultJSON []byte
Error string
StartedAt time.Time
FinishedAt *time.Time
}
func (j Job) AttemptNumber() int { return 1 }
// ReviewRunner isolates all process/container execution from orchestration.
type ReviewRunner interface {
Run(context.Context, PullRequestContext, ParsedCommand, RepoReviewConfig) (ReviewResult, error)
}
func NormalizeRepo(repo string) string { return strings.TrimSpace(repo) }