fix(webhook): accept Forgejo v15 label_updated events for label routing #63
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!63
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/forgejo-label-updated-event"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Caught live while smoke-testing #62 (the first
area:designdispatch): the designer agent never woke up even though the webhook was delivering and the service was up to date. Root cause: Forgejo v15 emitsissues.label_updated, notissues.labeled(which is the GitHub/old-Gitea convention). The dispatcher'sif (payload.action === "labeled" ...)check silently dropped every Forgejo label event.Fix
Split by action so the two payload shapes stay differentiated:
labeled— keeps the existingpayload.labelguard (single just-added label; malformed without it → skip, preserves the single-label guarantee)label_updated— walkspayload.issue.labelsand dispatches on the first routing match, at most once per eventKnown caveat (documented in the code)
On
label_updatedwe can't tell which label just changed from the payload alone, so adding a second label (priority:highetc.) to an already-area:designissue will re-dispatch the designer. The designer'simplementskill is expected to be idempotent (check for an existing Penpot file / PR before creating one). Clean dedup —(repo, issue_number, agent)in memory — is worth filing as a follow-up if the re-dispatch churn bites.Tests
3 new cases alongside the existing
labeledset:label_updatedwitharea:designin labels → dispatches (200, handler hit)label_updatedwith only non-routing labels → no-oplabel_updatedwith empty labels → safe no-op (fired when the last label is removed)234 pass / 0 fail ·
just qagreen.Test plan
area:designon a test issue — designer task should appear in the monitorlabel_updatedbranch doesn't double-dispatch on re-adds of non-routing labelslabel_updatedevents for label routingAPPROVED — CI green, fix is correct, tests cover all three meaningful states.
Review summary
Root cause & fix: Correct diagnosis. Forgejo v15 changed the action name from
labeledtolabel_updatedand droppedpayload.labelin favour of the fullpayload.issue.labelsset. The newelse ifbranch handles this exactly right: null-guard onpayload.issue,?? []on the labels array (safe for the remove-last-label case), andbreakafter first match ensuring at-most-one dispatch per event.Existing
labeledbranch: Untouched. No regression risk.Re-dispatch caveat: The inability to distinguish the delta from
label_updatedis correctly acknowledged — documented in the code comment and the PR body, with a follow-up flag. The designer's idempotency requirement is the right call for now.Tests: Three new cases (dispatch, non-routing no-op, empty no-op) are exactly what's needed. Consistent with the rest of the test harness (TEST_CONFIG omits
designer, sohandleIssueLabeledreturns null; the test validates the branch is entered safely and returns 200 without crashing).CI: ✅ run #1571,
qajob — success, 2m37s.Nothing blocking. Ready to merge.
designer+design-reviewercontainers #64