PRs: plain Close / Reopen action with issue-style state badge (no merge/review/comment required) #517
Labels
No labels
actions
bug
cli
duplicate
enhancement
fork
forum
git storage
help wanted
insights
invalid
issues
moderation
oidc
ownership transfer
packages
pr/merge protection rules
projects
pull requests
question
releases
sponsorships
tags
webhooks
wiki
wontfix
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
crueber/walhub#517
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
What's requested
A plain Close (and Reopen) action on the pull request conversation page, for PRs that should not be merged and need no review or comment — with the PR's state displayed exactly the way the issue page displays state.
Evidence
The backend and SDK already fully support this; only the UI is missing:
internal/pulls/service.go(~L848–955):UpdatePRapplies PUT fieldstate(open|closed). Auth: author or triage (triage may close others'). Closing a merged PR is refused (409). Close/reopen appendstate_changedevents and emitpullstream events (closed/reopenedactions).web/sdk/src/pulls.jsL37–39:repo.pulls.update(num, fields)—PUT …/pulls/{num}(title/body/state; unknown keys 400). The client surface exists and is unused for state.web/src/pages/Pull.jsx: the only PR lifecycle affordance isMergeBox. There is no Close button, no Reopen button, and the header does not render an open/closed state badge. A stale or unwanted PR can only be abandoned open, or merged to get rid of it.web/src/pages/Issue.jsx): header with state badge (title left, state badge right, per its header comment), a Close menu in the comment-composer area (including comment-and-close), and a Reopen control once closed. State-label helpers live inweb/src/lib/issue-events.js(closedStateLabel,closePatch).Architecture notes
repo.pulls.update(num, { state: "closed" | "open" })from the PR page. Same params, same permissions the server already enforces.repo.pulls.get) carries the current state (thread.state/prheader) — use it as the state source of truth for badge and button visibility, same as the issue page does.UpdatePRstreamspullevents (closed/reopened); Pull.jsx already subscribes to the collaboration stream and has the cross-page reconcile pattern (issue #319 / the #318 pattern, ~L585) — invalidation of coalesced keys on those frames should cover list cards + open_pulls badges; verify the streamacceptfilter runs before invalidation (seePull.jsxL34–36,state_changed→ "closed"/"reopened" timeline text already exists).Acceptance criteria
PUT { state: "closed" }, adds a "closed" timeline entry, and flips the header state badge to closed without a full reload (stream reconcile)internal/pulls— pure client wiringFix ready for review: #523 (branch fix/issue-517) — pure client wiring, no backend change. Badge (title-left/badge-right, Merged wins via chip-merged), Close + Comment-and-Close on open PRs and Reopen on closed-unmerged for author-or-triage, no control on merged (409 → tray toast), #318-style reconcile via new invalidatePullLists + existing pull-frame stream path. Tests: 1159 pass / 0 fail (3 live-server smoke skipped), vite+esbuild green, no new deps.
Review of PR #523 (fix/issue-517, commit
e820570) — all 7 acceptance criteria verified, no fixes needed.(1) Badge — PASS. Pull.jsx L716-723 mirrors Issue.jsx L434-442 exactly (flex flex-wrap items-start justify-between, title left / badge right). Open/Closed reuse chip-open/chip-closed; merged-wins via pr.merged is correct since merge stamps StateClosed too (merge.go outcome is write-once, thread.state alone can't distinguish). chip-merged (ui.css L114-115, purple) is warranted — new visual state, GitHub convention, no existing class fits.
(2) Visibility — PASS. pull-state.js L42-44 mirrors UpdatePR auth (service.go L875-876: author-or-triage) with the hierarchical P6 ladder (policy.go + perms.jsx LADDER identical: read<triage<write<maintain<admin, so write ⊇ triage). Below-triage non-authors get plain composer only (canComment at Pull.jsx L578 is role-non-null-gated, independent of closeVis). Author-with-read can close own PR — matches server.
(3) Close / Comment-and-Close / Reopen — PASS. Correct endpoint: pulls.update → PUT …/pulls/{num} {state} (sdk pulls.js L37-39). commentAndClosePR (Pull.jsx L678-690) is line-for-line the Issue.jsx L174-190 pattern (comment-first GitHub semantics, same split-failure note + plain-Close fallback). Merged → closeVis false/false, no control; raced merged-close 409 lands in tray via CommentComposer runClose/commentAndClose catch → reportError (CommentComposer.jsx L206-229), never silent. No reason chooser — correct, PR state is open|closed only.
(4) Stream reconcile — PASS. Mutation site reload()s own thread key (badge flip + closed timeline entry, no full reload; eventText state_changed→closed/reopened already at Pull.jsx L35-36) + invalidatePullLists. Other tabs follow closed/reopened pull frames on the existing repo stream; accept filter runs before invalidateCollab (collab.jsx L28-29), and the pull frame table already covers thread+lists+repo (collab.js L54-57). No new kinds, no ETag change.
(5) open_pulls — PASS. invalidatePullLists (data.js L361-364) clears pulls:{full}:* (matches Pulls.jsx L37 list-key shape) + repo:{full} (open_pulls numerator per tabs.js); reload() also clears repo:. Mirrors invalidateIssueLists (#318 precedent).
(6) Scope/hygiene — PASS. No .go diff, no package.json/pnpm diff (no new deps), docs Decision entry in 03_pull_requests.md (law 12, same commit). Badge reads live thread/pr fetch, never repo summary.
Verified in scratch worktree /tmp/pr523 (removed afterward): new pull-state-517.test.js 8/8 pass; full suite minus smoke 1159 pass / 0 fail (smoke.test.js hangs without a live server — expected, same 3-skipped shape as PR description); vite build green with 'Comment and Close' + 'chip-merged' confirmed in dist bundle. No browser drive (node tests + reasoning only — shared chrome-cdp daemon blocks loopback; header/composer rows reuse the issue page's flex-wrap pattern). Main worktree left clean (only pre-existing untracked .opencode/).
MERGE RECOMMENDATION: ready to merge.
Fixed by PR #523 (review clean — all 6 areas pass, issue convention mirrored, reconcile verified), merged. Closing.