Files
gbr-games/cmd/gbrgames/worker_test.go
T
gregandClaude Opus 5.5 0c868f7bac
Validate game templates / validate (push) Successful in 20s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
fix(worker): start with a repository-only token
The start-up check read the token's account with GET /user, which needs the
read:user scope. A token with only repository scope, which is all the worker
needs, got 403 and the worker exited in a restart loop. On 403 it now
names the commit author from BOT_NAME (default gbr-bot) and still checks
push access on the games repo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 17:18:22 -04:00

71 lines
2.1 KiB
Go

package main
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
)
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)
}
}