Files
orchestra/internal/provider/gitea_test.go
T
kami ce6f02f9e6 checkpoint: multi-repo Gitea ingestion, per-project repos, rotation anchor_sha fix
Pre-existing uncommitted work found at session start: rotation now emits
anchor_sha on TaskReleased (previously silently dropped by store.Append
validation), multi-repo Gitea provider support, per-project git worktree
roots, and associated test coverage. Committing as a checkpoint before
starting remediation work tracked in AUDIT.md.
2026-07-27 18:15:02 +04:00

137 lines
4.5 KiB
Go

package provider
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"net/http"
"net/http/httptest"
"orchestra/internal/domain"
"os"
"path/filepath"
"testing"
)
func TestGiteaSourceNameDefaultsToRepo(t *testing.T) {
if got := (Gitea{Repo: "orchestra"}).SourceName(); got != "gitea" {
t.Fatalf("expected legacy unnamespaced source, got %q", got)
}
if got := (Gitea{Repo: "orchestra", Project: "correx"}).SourceName(); got != "gitea:correx" {
t.Fatalf("expected namespaced source, got %q", got)
}
}
func TestGiteaIngestWebhookTagsProject(t *testing.T) {
g := Gitea{Owner: "kami", Repo: "correx-repo", Project: "correx", WebhookSecret: "s3cret"}
body, _ := json.Marshal(map[string]any{
"action": "opened",
"issue": map[string]any{"number": 42, "title": "fix thing", "body": "", "state": "open"},
})
mac := hmac.New(sha256.New, []byte("s3cret"))
mac.Write(body)
sig := hex.EncodeToString(mac.Sum(nil))
sk := &sink{}
if err := g.IngestWebhook(body, sig, sk); err != nil {
t.Fatalf("ingest: %v", err)
}
if len(sk.events) != 1 {
t.Fatalf("expected 1 event, got %d", len(sk.events))
}
var p struct {
Project string `json:"project"`
Source string `json:"source"`
ExternalID string `json:"external_id"`
}
if err := json.Unmarshal(sk.events[0].Payload, &p); err != nil {
t.Fatalf("unmarshal payload: %v", err)
}
if p.Project != "correx" || p.Source != "gitea:correx" || p.ExternalID != "42" {
t.Fatalf("unexpected payload: %+v", p)
}
}
func TestGiteaIngestWebhookRejectsBadSignature(t *testing.T) {
g := Gitea{Owner: "kami", Repo: "r", Project: "p", WebhookSecret: "s3cret"}
if err := g.IngestWebhook([]byte(`{"action":"opened","issue":{"number":1}}`), "wrong", &sink{}); err == nil {
t.Fatal("expected signature rejection")
}
}
func TestMultiGiteaReflectDispatchesByTaskSource(t *testing.T) {
var hitCorrex, hitMaven bool
correxSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hitCorrex = true
w.WriteHeader(200)
}))
defer correxSrv.Close()
mavenSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hitMaven = true
w.WriteHeader(200)
}))
defer mavenSrv.Close()
m := MultiGitea{Sources: map[string]Gitea{
"gitea:correx": {BaseURL: correxSrv.URL, Owner: "kami", Repo: "correx-repo", Project: "correx"},
"gitea:maven": {BaseURL: mavenSrv.URL, Owner: "kami", Repo: "maven-repo", Project: "maven"},
}}
if err := m.ReflectTask(domain.Task{Source: "gitea:correx", ExternalID: "7"}, domain.Event{Type: "TaskCompleted"}); err != nil {
t.Fatalf("reflect to correx: %v", err)
}
if !hitCorrex || hitMaven {
t.Fatalf("expected only correx server hit, got correx=%v maven=%v", hitCorrex, hitMaven)
}
hitCorrex, hitMaven = false, false
if err := m.ReflectTask(domain.Task{Source: "gitea:maven", ExternalID: "3"}, domain.Event{Type: "TaskFailed"}); err != nil {
t.Fatalf("reflect to maven: %v", err)
}
if hitCorrex || !hitMaven {
t.Fatalf("expected only maven server hit, got correx=%v maven=%v", hitCorrex, hitMaven)
}
// A task from a non-Gitea source (or an unregistered Gitea project) must
// be a silent no-op, not an error.
if err := m.ReflectTask(domain.Task{Source: "jsonl"}, domain.Event{Type: "TaskCompleted"}); err != nil {
t.Fatalf("unmatched source should no-op, got %v", err)
}
}
func TestLoadGiteaConfigsValidatesAndRejectsDuplicates(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "gitea.json")
good := `[
{"project":"correx","base_url":"https://gitea.internal","owner":"kami","repo":"correx"},
{"project":"maven","base_url":"https://gitea.internal","owner":"kami","repo":"maven"}
]`
if err := os.WriteFile(path, []byte(good), 0644); err != nil {
t.Fatal(err)
}
cfgs, err := LoadGiteaConfigs(path)
if err != nil || len(cfgs) != 2 {
t.Fatalf("cfgs=%d err=%v", len(cfgs), err)
}
dupPath := filepath.Join(dir, "dup.json")
dup := `[
{"project":"correx","base_url":"https://gitea.internal","owner":"kami","repo":"correx"},
{"project":"correx","base_url":"https://gitea.internal","owner":"kami","repo":"other"}
]`
if err := os.WriteFile(dupPath, []byte(dup), 0644); err != nil {
t.Fatal(err)
}
if _, err := LoadGiteaConfigs(dupPath); err == nil {
t.Fatal("expected duplicate project rejection")
}
incompletePath := filepath.Join(dir, "incomplete.json")
if err := os.WriteFile(incompletePath, []byte(`[{"project":"x"}]`), 0644); err != nil {
t.Fatal(err)
}
if _, err := LoadGiteaConfigs(incompletePath); err == nil {
t.Fatal("expected missing-field rejection")
}
}