package main import ( "net/http" "net/http/httptest" "strings" "testing" "time" ) func TestCheckBotNeedsPushAccess(t *testing.T) { push := false srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Authorization") != "token secret" { w.WriteHeader(http.StatusUnauthorized) return } switch r.URL.Path { case "/api/v1/user": w.Write([]byte(`{"login":"git_ai_bot","email":"bot@example.com"}`)) case "/api/v1/repos/org/games": if push { w.Write([]byte(`{"permissions":{"push":true}}`)) } else { w.Write([]byte(`{"permissions":{"push":false}}`)) } default: w.WriteHeader(http.StatusNotFound) } })) defer srv.Close() c := &workerConfig{gitea: srv.URL, repo: "org/games", botToken: "secret"} if err := c.checkBot(); err == nil || !strings.Contains(err.Error(), "git_ai_bot can't push to org/games") { t.Errorf("read-only bot: got %v", err) } push = true if err := c.checkBot(); err != nil { t.Fatal(err) } if c.botLogin != "git_ai_bot" || c.botEmail != "bot@example.com" { t.Errorf("identity = %s <%s>", c.botLogin, c.botEmail) } c.botToken = "wrong" if err := c.checkBot(); err == nil || !strings.Contains(err.Error(), "GITEA_TOKEN") { t.Errorf("bad token: got %v", err) } } func TestCheckBotWithRepositoryOnlyToken(t *testing.T) { // Gitea answers /user with 403 when the token only has repository scope srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/api/v1/user": w.WriteHeader(http.StatusForbidden) w.Write([]byte(`{"message":"token does not have at least one of required scope(s), required=[read:user]"}`)) case "/api/v1/repos/org/games": w.Write([]byte(`{"permissions":{"push":true}}`)) } })) defer srv.Close() t.Setenv("BOT_NAME", "gbr-bot") c := &workerConfig{gitea: srv.URL, repo: "org/games", botToken: "secret"} if err := c.checkBot(); err != nil { t.Fatal(err) } if c.botLogin != "gbr-bot" || c.botEmail != "gbr-bot@users.noreply" { t.Errorf("identity = %s <%s>", c.botLogin, c.botEmail) } } func TestDraftBranchIsNewForEveryRun(t *testing.T) { first := draftBranch("example", "4b174b2d", time.Date(2026, 10, 25, 21, 30, 0, 0, time.UTC)) rerun := draftBranch("example", "4b174b2d", time.Date(2026, 10, 25, 22, 5, 9, 0, time.UTC)) if first != "draft/example-4b174b2d-20261025-213000" || first == rerun { t.Errorf("first %q, rerun %q", first, rerun) } }