Skip to content

feat(PRO-544): add write capability to the PR header#62

Merged
dastratakos merged 12 commits into
mainfrom
dean/pro-544-pr-header-writes
Jun 2, 2026
Merged

feat(PRO-544): add write capability to the PR header#62
dastratakos merged 12 commits into
mainfrom
dean/pro-544-pr-header-writes

Conversation

@dastratakos
Copy link
Copy Markdown
Contributor

@dastratakos dastratakos commented Jun 1, 2026

Summary

Stacked on #61. Upgrades the read-only PR header to full parity with the hosted Stage header by adding write capability over the gh CLI. Every control the hosted header exposes is now interactive.

Stacked PR — base is dean/pro-544-pr-header-readonly (#61), not main. Review/merge #61 first; this diff shows only the write layer on top.

What becomes interactive

  • Title — inline edit (✓/✗), gh pr edit --title
  • Status pill — dropdown: close / reopen / convert-to-draft / mark-ready, with a close-confirmation AlertDialog (gh pr close|reopen|ready)
  • Merge status — merge button with method picker + auto-merge toggle; merge-queue enqueue/dequeue map onto gh pr merge --auto/--disable-auto (gh pr merge)
  • Reviewers — add/remove + collaborator search (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 orpc mutations are swapped for CLI-native react-query mutation hooks (pull-request-mutations.ts) hitting new plain-HTTP write routes backed by gh. The usePullRequestStatusActions and useReviewerManager hooks are ported to the CLI's query keys.

Writes hit the user's real PR; destructive actions confirm first, and gh failures surface as toasts. gh already holds the user's write-scoped token.

Testing

  • pnpm typecheck, pnpm lint, pnpm build all clean.
  • A mutation route test drives each write through the real server + SQLite using a fake gh that records its argv, asserting the exact gh command per action (incl. the auto-merge ↔ --auto/--disable-auto mapping).

Note

Merge-queue enqueue/dequeue intentionally collapse onto gh's auto-merge handling rather than raw GraphQL mutations — gh pr merge --auto enqueues on merge-queue repos. Deployment links remain omitted (require a GitHub App).


Open in Stage

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

    • Inline title edit with save/cancel (PATCH /titlegh pr edit --title).
    • Status dropdown: close, reopen, convert to draft, mark ready; close confirms via @radix-ui/react-alert-dialog (/close|/reopen|/draftgh pr close|reopen|ready).
    • Merge controls: method picker + merge now with head-commit protection; “Merge when ready” toggles queue/auto-merge (/merge and /auto-mergegh pr merge --(merge|squash|rebase) [--match-head-commit], --auto|--disable-auto).
    • Reviewer management: add/remove and re-request; collaborator search via /collaborators (gh api .../collaborators).
    • Deployment links: show one https link per environment (latest successful) fetched alongside checks via GraphQL (gh api graphql).
  • Bug Fixes

    • Toasts show actionable gh stderr by reading the server’s { error } body across title, status, merge, and reviewer actions.
    • Forward head SHA when enabling auto-merge (both enqueue and toggle paths) to guard against stale heads (--match-head-commit).
    • Avoid duplicate requests when turning off “Merge when ready” (dequeue and disable auto-merge both map to --disable-auto).
    • Hardened mutation safety: require a loopback Host and same-origin host:port to block CSRF and DNS rebinding; non-browser clients without Origin still work.
    • Return 400 for malformed JSON bodies on mutation routes (not 500).

Written for commit b382951. Summary will update on new commits.

Review in cubic

@stage-review
Copy link
Copy Markdown

stage-review Bot commented Jun 1, 2026

Comment thread packages/web/src/lib/pull-request-mutations.ts
Comment thread packages/web/src/components/pull-request/merge-status.tsx Outdated
Comment thread packages/cli/src/github/mutations.ts
Comment thread packages/web/src/lib/pull-request-mutations.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/cli/src/github/mutations.ts
Comment thread packages/web/src/lib/pull-request-mutations.ts Outdated
@dastratakos dastratakos marked this pull request as draft June 1, 2026 20:48
@dastratakos dastratakos marked this pull request as ready for review June 1, 2026 20:48
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/web/src/lib/pull-request-mutations.ts Outdated
@dastratakos dastratakos force-pushed the dean/pro-544-pr-header-writes branch 2 times, most recently from fce07f8 to 9e4195c Compare June 1, 2026 21:11
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/web/src/lib/pull-request-mutations.ts Outdated
Comment thread packages/web/src/lib/use-reviewer-manager.ts
@dastratakos dastratakos force-pushed the dean/pro-544-pr-header-writes branch 3 times, most recently from 5d4e550 to 745d47c Compare June 1, 2026 21:34
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/web/src/components/pull-request/merge-status.tsx
@dastratakos dastratakos changed the title feat: add write capability to the PR header [PRO-544] feat(PRO-544): add write capability to the PR header Jun 1, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/web/src/components/pull-request/reviewers.tsx
@dastratakos dastratakos force-pushed the dean/pro-544-pr-header-writes branch from 4e691ab to 9371531 Compare June 1, 2026 22:00
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/web/src/lib/use-pull-request-status-actions.ts Outdated
@dastratakos dastratakos force-pushed the dean/pro-544-pr-header-writes branch from 9371531 to 41710d4 Compare June 1, 2026 22:07
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/cli/src/routes/pull-request-mutations.ts Outdated
@dastratakos dastratakos force-pushed the dean/pro-544-pr-header-writes branch from a99ad9d to c8ae7a3 Compare June 1, 2026 22:21
Comment thread packages/cli/src/routes/pull-request-mutations.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/web/src/components/pull-request/pull-request-header.tsx Outdated
Comment thread packages/web/src/components/pull-request/reviewers.tsx Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/cli/src/routes/pull-request-shared.ts Outdated
Comment thread packages/web/src/lib/use-reviewer-manager.ts
Base automatically changed from dean/pro-544-pr-header-readonly to main June 2, 2026 00:24
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.
@dastratakos dastratakos force-pushed the dean/pro-544-pr-header-writes branch from 63ed06a to e9405fa Compare June 2, 2026 00:29
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).
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread packages/web/src/lib/pull-request-mutations.ts
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.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/cli/src/routes/pull-request-shared.ts
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).
@dastratakos dastratakos merged commit 861cf81 into main Jun 2, 2026
5 checks passed
@dastratakos dastratakos deleted the dean/pro-544-pr-header-writes branch June 2, 2026 04:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant