From f58f646b7d8d4b92321226e581b1960aff3a80c5 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Mon, 16 Feb 2026 09:14:29 -0800 Subject: [PATCH] Fix "customer" label not being assigned --- internal/forgejo/client.go | 44 ++++++++++++++++++++++++++++- internal/handlers/admin/tickets.go | 2 +- internal/handlers/public/tickets.go | 2 +- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/internal/forgejo/client.go b/internal/forgejo/client.go index ac97285..14b8b29 100644 --- a/internal/forgejo/client.go +++ b/internal/forgejo/client.go @@ -366,7 +366,7 @@ func (c *Client) InitBotLogin() error { } func (c *Client) GetLabel(owner, repo, labelName string) (*Label, error) { - listURL := fmt.Sprintf("%s/api/v1/repos/%s/%s/labels", c.baseURL, owner, repo) + listURL := fmt.Sprintf("%s/api/v1/repos/%s/%s/labels?limit=50", c.baseURL, owner, repo) httpReq, err := http.NewRequest("GET", listURL, nil) if err != nil { return nil, err @@ -396,6 +396,48 @@ func (c *Client) GetLabel(owner, repo, labelName string) (*Label, error) { return nil, fmt.Errorf("label %q not found in %s/%s", labelName, owner, repo) } +func (c *Client) CreateLabel(owner, repo, labelName, color string) (*Label, error) { + reqURL := fmt.Sprintf("%s/api/v1/repos/%s/%s/labels", c.baseURL, owner, repo) + + body, err := json.Marshal(map[string]string{"name": labelName, "color": color}) + if err != nil { + return nil, err + } + + httpReq, err := http.NewRequest("POST", reqURL, bytes.NewReader(body)) + if err != nil { + return nil, err + } + httpReq.Header.Set("Content-Type", "application/json") + httpReq.Header.Set("Authorization", "token "+c.apiToken) + + resp, err := c.httpClient.Do(httpReq) + if err != nil { + return nil, fmt.Errorf("forgejo API request failed: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusCreated { + respBody, _ := io.ReadAll(resp.Body) + return nil, fmt.Errorf("forgejo API returned %d: %s", resp.StatusCode, string(respBody)) + } + + var label Label + if err := json.NewDecoder(resp.Body).Decode(&label); err != nil { + return nil, err + } + return &label, nil +} + +// GetOrCreateLabel looks up a label by name, creating it if it doesn't exist. +func (c *Client) GetOrCreateLabel(owner, repo, labelName, color string) (*Label, error) { + label, err := c.GetLabel(owner, repo, labelName) + if err == nil { + return label, nil + } + return c.CreateLabel(owner, repo, labelName, color) +} + func (c *Client) CreateIssue(owner, repo string, req CreateIssueRequest) (*Issue, error) { reqURL := fmt.Sprintf("%s/api/v1/repos/%s/%s/issues", c.baseURL, owner, repo) diff --git a/internal/handlers/admin/tickets.go b/internal/handlers/admin/tickets.go index 88f818a..c418b4b 100644 --- a/internal/handlers/admin/tickets.go +++ b/internal/handlers/admin/tickets.go @@ -303,7 +303,7 @@ func (h *TicketHandler) UpdateStatus(c *gin.Context) { newStatus := c.PostForm("status") // Get or create the in_progress label - inProgressLabel, err := h.deps.ForgejoClient.GetLabel(repo.ForgejoOwner, repo.ForgejoRepo, "in_progress") + inProgressLabel, err := h.deps.ForgejoClient.GetOrCreateLabel(repo.ForgejoOwner, repo.ForgejoRepo, "in_progress", "#e4e669") if err != nil { log.Error().Err(err).Msg("forgejo get/create in_progress label error") h.deps.Renderer.RenderError(c.Writer, c.Request, http.StatusServiceUnavailable, "Service temporarily unavailable") diff --git a/internal/handlers/public/tickets.go b/internal/handlers/public/tickets.go index bb8c1b8..d43287e 100644 --- a/internal/handlers/public/tickets.go +++ b/internal/handlers/public/tickets.go @@ -192,7 +192,7 @@ func (h *TicketHandler) Create(c *gin.Context) { // Synchronous Forgejo issue creation var labelIDs []int64 - label, err := h.deps.ForgejoClient.GetLabel(repo.ForgejoOwner, repo.ForgejoRepo, "customer") + label, err := h.deps.ForgejoClient.GetOrCreateLabel(repo.ForgejoOwner, repo.ForgejoRepo, "customer", "#0075ca") if err != nil { log.Error().Err(err).Msg("forgejo get/create label error") } else {