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>
This commit is contained in:
1 parent
425c242ae7
commit
0c868f7bac
3 files changed
+29
No files matched your search
@@ -46,6 +46,7 @@ All through environment variables; nothing about where it runs lives in this rep
|
||||
| `OLLAMA_URL` | Ollama for the model (or `MODEL_PROVIDER=gemini` with `GEMINI_API_KEY`) |
|
||||
| `SEARXNG_URL`, `READER_URL` | A SearXNG instance (JSON API) and a page-to-text reader (`READER_URL/<page url>`) |
|
||||
| `MODEL`, `POLL_INTERVAL`, `WORKER_NAME`, `WORK_DIR` | Optional: model name, poll interval (20s), name shown in the panel, work folder |
|
||||
| `BOT_NAME` | Optional: commit author when the token can't read its own account (no `read:user` scope); default `gbr-bot` |
|
||||
|
||||
## Running a build by hand
|
||||
|
||||
|
||||
@@ -60,8 +60,13 @@ func (c *workerConfig) checkBot() error {
|
||||
Email string `json:"email"`
|
||||
}
|
||||
if err := c.giteaGet("/user", &user); err != nil {
|
||||
if !strings.HasPrefix(err.Error(), "HTTP 403") {
|
||||
return fmt.Errorf("GITEA_TOKEN: %w", err)
|
||||
}
|
||||
// A repository-only token (all the worker needs) may not read its own account: name the author from
|
||||
// BOT_NAME instead. Whether it can push is still checked below.
|
||||
user.Login = envOr("BOT_NAME", "gbr-bot")
|
||||
}
|
||||
var repo struct {
|
||||
Permissions struct {
|
||||
Push bool `json:"push"`
|
||||
|
||||
@@ -45,3 +45,26 @@ func TestCheckBotNeedsPushAccess(t *testing.T) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user