f19b271642
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>
66 lines
2.4 KiB
Go
66 lines
2.4 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"context"
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"io"
|
|
"log/slog"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea-codex-bot/internal/config"
|
|
"gitea-codex-bot/internal/gitea"
|
|
"gitea-codex-bot/internal/store/sqlstore"
|
|
)
|
|
|
|
func TestWebhookQueuesSignedReview(t *testing.T) {
|
|
giteaServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch {
|
|
case strings.Contains(r.URL.Path, "/pulls/"):
|
|
_, _ = w.Write([]byte(`{"base":{"ref":"main","sha":"base","repo":{"clone_url":"https://gitea.test/acme/repo.git","full_name":"acme/repo"}},"head":{"ref":"feature","sha":"head","repo":{"clone_url":"https://gitea.test/acme/repo.git","full_name":"acme/repo"}},"html_url":"https://gitea.test"}`))
|
|
case r.Method == http.MethodPost:
|
|
_, _ = w.Write([]byte(`{"id":100}`))
|
|
case strings.Contains(r.URL.Path, "contents"):
|
|
http.NotFound(w, r)
|
|
default:
|
|
http.NotFound(w, r)
|
|
}
|
|
}))
|
|
defer giteaServer.Close()
|
|
settings := config.Settings{GiteaBaseURL: giteaServer.URL, GiteaToken: "token", GiteaBotUsername: "codex-bot", GiteaWebhookSecret: "secret", AllowedRepos: []string{"acme/repo"}, DatabaseURL: "sqlite://" + t.TempDir() + "/test.db", WebhookMaxBytes: 1 << 20, CooldownSeconds: 60}
|
|
st, err := sqlstore.Open(settings)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer st.Close()
|
|
if err := st.Migrate(context.Background()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
server := New(settings, st, gitea.NewClient(settings), nilLogger())
|
|
payload := []byte(`{"repository":{"full_name":"acme/repo"},"sender":{"username":"alice"},"comment":{"id":11,"body":"@codex review security"},"issue":{"number":9,"pull_request":{"url":"x"}},"pull_request":{"head":{"sha":"head"}}}`)
|
|
mac := hmac.New(sha256.New, []byte("secret"))
|
|
_, _ = mac.Write(payload)
|
|
req := httptest.NewRequest(http.MethodPost, "/webhook/gitea", strings.NewReader(string(payload)))
|
|
req.Header.Set("X-Gitea-Event", "issue_comment")
|
|
req.Header.Set("X-Gitea-Signature", hex.EncodeToString(mac.Sum(nil)))
|
|
rec := httptest.NewRecorder()
|
|
server.ServeHTTP(rec, req)
|
|
if rec.Code != 200 {
|
|
t.Fatalf("status %d", rec.Code)
|
|
}
|
|
var response map[string]any
|
|
if err := json.Unmarshal(rec.Body.Bytes(), &response); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if response["status"] != "queued" {
|
|
t.Fatalf("response %#v", response)
|
|
}
|
|
}
|
|
func nilLogger() *slog.Logger { return slog.New(slog.NewTextHandler(io.Discard, nil)) }
|