feat(service,features,desktop): a merge box on the Pull request tab, merging as the member who presses

Merged
DA
7h ago
+1522-46

A2 of the "Act on the PR" stack, stacked on #3272 (W1: writes as the member). It adds a stage-cli-style merge box to the Pull request tab's fixed header.

What the box offers

The header's merge line ends in the one thing that may be done from where an open pull request stands:

  • Merge, by the method chosen among those the repository allows (merge commit, squash, rebase). A split chevron picks the method. The choice is kept per repository across launches, in this window's own storage as the sidebar's folds are. The merge asks first, since it can't be undone from here, and names the head commit the header read, so GitHub refuses it against a newer push.
  • Enable auto-merge, by the chosen method, while checks are still running and the repository allows auto-merge.
  • Merge when ready, on a base merged through a merge queue. This turns auto-merge on with no method, so GitHub adds the pull request to the queue once it is ready, as gh pr merge --auto does.
  • Disable auto-merge once auto-merge is on, and Remove from queue once the pull request is queued, with its place in the queue shown.
  • Nothing for a conflict or a draft. A blocked merge says what it waits on: changes requested, a required review missing, required checks running or failing.

Each press goes through W1's seam (memberPullRequestWrite), so it is made on GitHub as the member who presses, using GraphQL mergePullRequest, enablePullRequestAutoMerge, disablePullRequestAutoMerge or dequeuePullRequest. GitHub's refusals (branch protection, a moved head, a method a ruleset forbids) show in GitHub's own words on W1's line.

The read

The header's read (/overview/pull-request) now carries an optional merging, read in one GraphQL query on the App's installation token beside the REST read. It holds:

  • the allowed merge methods and whether auto-merge is allowed;
  • whether a merge queue merges the base, and the pull request's place in it;
  • whether auto-merge is on, and by which method;
  • the head commit, the review decision, and the head's check rollup.

If GitHub won't answer that query, merging is left out and the header stands without the box. The methods are the repository's settings only. A ruleset that narrows them is left to GitHub to refuse, in its own words.

Goldens

Recorded with LUKE_UPDATE_FIXTURES=1:

  • pull-request-write-wire-pullRequestActionRequestSchema and coding-agent-view-codingAgentPullRequestActionParamsSchema gain the merge, enable-auto-merge, disable-auto-merge and dequeue actions.
  • pull-request-write-wire-mergeMethodSchema is new.
  • coding-agent-wire- and coding-agent-view-codingAgentOverviewPullRequestAnswer… gain the optional merging.

Tests

  • Service:
    • each merge action is sent as the member, with the right mutation and variables (method uppercased, head named, no method on a queue's Merge when ready);
    • a head that is missing or not a commit is refused before GitHub;
    • the header read carries merging read on the App's token, and stands without it when the query fails.
  • Renderer:
    • the method picker, with the choice kept across a redraw;
    • Merge asks first, then sends the head it read;
    • Enable or Disable auto-merge, Merge when ready and Remove from queue each send their action;
    • the blocked wording, and nothing offered for a conflict.
  • PRIVACY.md says what the merge read reads, and lists Merge and Enable auto-merge among the button presses made as you.

Checks

The full pnpm check:affected runs out of memory in the sandbox. I ran the parts separately instead, and all passed: per-package tsc, oxlint, biome, knip, and the affected vitest files.

Screenshots follow in a comment.

Made with Luke


Devin Review


Summary by cubic

Adds a merge box to the Pull request tab's fixed header so members can merge a pull request or set up auto-merge from where it stands, with each action made on GitHub as the member who presses, through the existing write seam.

  • Offers Merge, Enable auto-merge, Merge when ready on a merge-queued base, Disable auto-merge, and Remove from queue; drafts and conflicts get no box, and a blocked merge says what it waits on.
  • Merge asks first in a dialog whose act keeps the accent as GitHub draws Merge, and merges the head it was asked about, even if a later read names a newer one; the chosen method persists per repository.
  • The overview read carries optional merging data from one GraphQL query on the App's token and stands without the box when GitHub won't answer it; GitHub's refusals, like branch protection or a forbidden method, come through in GitHub's own words.