plane: REST + webhook dual-shape decode for WorkItem refs (PFB-25)#13
Merged
Conversation
v0.1.2 (PFB-24) typed StateRef/LabelRef/AssigneeRef to match webhook deliveries, where Plane sends objects. Plane CE v1.3.1's REST surface (POST/GET/PATCH /issues/) returns the same fields as bare UUID strings, so every forge->plane create call failed decoding the POST response and silently left a duplicate Forgejo issue once Plane's own webhook came back. Custom UnmarshalJSON on each ref accepts either shape; regression tests pin both forms against verbatim captures from plane.stern.ca. Refs PFB-25. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
UnmarshalJSONonStateRef,LabelRef,AssigneeRefso each accepts both the REST bare-UUID form and the webhook object form.WorkItemstays declarative and[]LabelRef/[]AssigneeRefautomatically dispatch to the element method — works for[]string(REST) and[]object(webhook) without per-field wrappers./issues/response at both the type level (TestWorkItem_UnmarshalJSON_RESTShape_PFB25) and through the HTTP client (TestCreateIssue_RealPlaneRESTShape_PFB25). Webhook-shape tests are unchanged and continue to pass (TestParse_RealPlaneWorkItemPayload_PFB24).Why
v0.1.2 fixed PFB-24 by typing the refs as objects to match webhook deliveries. That broke every
forge → planecreate call because Plane's REST surface returns the same fields as bare UUID strings (state) and arrays of bare UUID strings (labels, assignees). Symptom on every create:Since the POST already succeeded on the Plane side, the bridge had no record of the new Plane UUID; the loop-break LRU is populated only on translator success, so Plane's webhook for the new work item then duplicated back to Forgejo as a brand-new issue. See PFB-25 body for the full trace.
Test plan
make race— all packages greenmake lint— 0 issuescurlbefore designing the fix; both fixtures in the new tests are verbatim from those captures:0on the bridge host, retry a forge→plane create againstascend-cloud(the repo that surfaced the bug), confirm no duplicate Forgejo issueBroader testdata audit + real-Plane round-trip e2e tracked separately so this PR stays focused on unblocking the rollout.
🤖 Generated with Claude Code