feat(PRO-544): add write capability to the PR header#62
Conversation
|
Ready to review this PR? Stage has broken it down into 8 individual chapters for you: Chapters generated by Stage for commit b382951 on Jun 2, 2026 2:37am UTC. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2c27647694
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2c27647694
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
fce07f8 to
9e4195c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9e4195c14b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
5d4e550 to
745d47c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 745d47c486
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4e691abd40
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
4e691ab to
9371531
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 937153137a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
9371531 to
41710d4
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 41710d4ec5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
a99ad9d to
c8ae7a3
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 96ccf25ca6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 63ed06a957
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Mutation routes for title edit, close/reopen, draft toggle, merge, auto-merge (merge-queue enqueue/dequeue map to gh's --auto/--disable-auto), and reviewer add/remove, plus a collaborators read for the reviewer picker. Writes surface gh failures as 500s so the UI can toast them. Shared run/repo resolution is factored into pull-request-shared.ts. Covered by a route test asserting the exact gh argv per mutation.
Upgrade each read-only PR-header control to its full hosted version: inline title edit, status dropdown (close/reopen/draft) with close confirmation, merge-status controls (merge + auto-merge), and reviewer add/remove with collaborator search. Vendored components keep hosted markup; their oRPC mutations are swapped for CLI-native react-query hooks backed by the new gh write routes. Adds the alert-dialog primitive.
Relocate github-mutations.ts to github/mutations.ts and export it from the github barrel, so reads and writes live in one cohesive github/ module. Routes import the write adapters via github/index.js. No behavior change.
Addresses PR review feedback on the write layer:
- write() now reads the server's { error } body on failure so toasts show the
actionable gh stderr instead of a generic "POST … failed: 500".
- Forward expectedHeadOid through the enqueue/auto-merge path into
gh pr merge --auto --match-head-commit, guarding auto-merge against a stale
head (parity with the direct-merge path).
- The merge-queue off-toggle no longer fires both dequeue and disable-auto
(which map to the same gh --disable-auto), avoiding a duplicate request.
Draft/close/reopen onError handlers now toast error.message when present (matching the merge actions), so the actionable gh stderr preserved by write() reaches the user instead of a generic failure toast.
The mutation routes execute gh write commands and bind to a predictable loopback port, so a browser on any site could fire a no-cors POST to close/merge/retitle a PR while the CLI runs. Each mutation handler now requires a loopback Origin (browsers always send an accurate, unforgeable Origin cross-origin; non-browser clients like curl send none and are allowed). The read routes are unaffected — cross-origin reads get opaque responses.
parseBody now catches the SyntaxError readJsonBody throws on invalid JSON and responds 400 "Invalid request body" instead of letting it escape to the server's plain-text 500, so the client toasts the intended message.
Title-edit and reviewer add/remove/re-request onError handlers now toast error.message when present (mirroring the merge and status actions), so the gh stderr preserved by write() reaches the user instead of a generic toast.
63ed06a to
e9405fa
Compare
enforceSameOrigin now requires the request Origin's host:port to match the Host it connected to, instead of accepting any loopback origin. This also rejects other local origins (e.g. a page on http://localhost:3000) that could otherwise POST to the predictable Stage port. Non-browser clients (no Origin) are still allowed.
getChecks now fetches the commit's deployments via a single gh api graphql query (commit.deployments + latestStatus), in parallel with check-runs, and resolves one link per environment — the latest successful deployment with an https URL (mirrors hosted Stage's resolveDeploymentLinks). The header's already-vendored deployment button/popover renders them with no UI change. Replaces the previous always-empty deploymentLinks (and the inaccurate "needs a GitHub App" note — the Deployments data is readable via gh).
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 2f5e157. Configure here.
setAutoMergeMutationOptions dropped expectedHeadOid, so enabling auto-merge never sent --match-head-commit even though the server, merge, and enqueue paths all support it. Forward headSha from MergeActions on both enable sites (merge-queue not-ready and non-merge-queue toggle); disabling still omits it.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 681053adfb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The same-origin guard compared Origin host to Host, but DNS rebinding defeats that: an attacker page rebound to 127.0.0.1 sends its own hostname in both headers, so they match. The server only ever binds to loopback, so require the Host header's hostname to be a loopback literal (127.0.0.1/localhost) before the same-origin check. Adds a rebinding test (matching Origin + non-loopback Host).

Summary
Stacked on #61. Upgrades the read-only PR header to full parity with the hosted Stage header by adding write capability over the
ghCLI. Every control the hosted header exposes is now interactive.What becomes interactive
gh pr edit --titleAlertDialog(gh pr close|reopen|ready)gh pr merge --auto/--disable-auto(gh pr merge)gh pr edit --add-reviewer/--remove-reviewer,gh api .../collaborators)Approach
Same as #61: the vendored components keep the hosted markup; only their data layer changes. The hosted
orpcmutations are swapped for CLI-native react-query mutation hooks (pull-request-mutations.ts) hitting new plain-HTTP write routes backed bygh. TheusePullRequestStatusActionsanduseReviewerManagerhooks are ported to the CLI's query keys.Writes hit the user's real PR; destructive actions confirm first, and
ghfailures surface as toasts.ghalready holds the user's write-scoped token.Testing
pnpm typecheck,pnpm lint,pnpm buildall clean.ghthat records its argv, asserting the exactghcommand per action (incl. the auto-merge ↔--auto/--disable-automapping).Note
Merge-queue enqueue/dequeue intentionally collapse onto
gh's auto-merge handling rather than raw GraphQL mutations —gh pr merge --autoenqueues on merge-queue repos. Deployment links remain omitted (require a GitHub App).Summary by cubic
Adds write capability to the CLI PR header and surfaces per-environment deployment links, matching the hosted header. Satisfies PRO-544 by making the detected PR fully interactive with clearer feedback and safer mutations.
New Features
PATCH /title→gh pr edit --title).@radix-ui/react-alert-dialog(/close|/reopen|/draft→gh pr close|reopen|ready)./mergeand/auto-merge→gh pr merge --(merge|squash|rebase) [--match-head-commit],--auto|--disable-auto)./collaborators(gh api .../collaborators).gh api graphql).Bug Fixes
ghstderr by reading the server’s{ error }body across title, status, merge, and reviewer actions.--match-head-commit).--disable-auto).Hostand same-origin host:port to block CSRF and DNS rebinding; non-browser clients withoutOriginstill work.Written for commit b382951. Summary will update on new commits.