feat(diff): review a GitHub pull request with --pr - #663
Conversation
Add `hunk diff --pr <number|url> [--repo <owner/repo>]`. Hunk shells out to the authenticated GitHub CLI (`gh pr diff --patch`) and feeds the patch through the existing patch loader, so a pull request opens for review without a manual `gh pr checkout`. - `src/core/github.ts`: `fetchPullRequestPatch()` wraps `gh`, with friendly errors when `gh` is missing, the PR can't be fetched, or the diff is empty. - `PatchCommandInput.label` lets an in-memory patch carry a header label (`PR modem-dev#68`) since it has no backing file. - Scope: patch display only. Importing unresolved review threads (modem-dev#487/modem-dev#460) and current-branch PR auto-detection are intentionally left as follow-ups. Closes modem-dev#465
|
PR author is not in the allowed authors list. |
|
@habakan is attempting to deploy a commit to the Modem Team on Vercel. A member of the Team first needs to authorize it. |
|
Did you try: If that's too tough to remember (it is), you could make a little shell fn and add it to your hunk-pr() {
gh pr diff "$1" --patch "${@:2}" | hunk patch -
}Usage: hunk-pr 663
hunk-pr 663 --repo modem-dev/hunkI'd prefer if we documented + shared this workflow vs. coupling hunk to |
|
That makes sense — keeping hunk decoupled from I've turned this into a docs PR instead: #672 documents |
Summary
Implements
hunk diff --pr <number|url> [--repo <owner/repo>]— review a GitHub pull request directly, without a manualgh pr checkout.Closes #465.
Hunk stays a local diff viewer: it shells out to the user's authenticated GitHub CLI (
gh pr diff <ref> --patch) and feeds the resulting patch through the existing patch pipeline. A PR is just another patch source, so no new rendering/loader path was needed.Changes
src/core/github.ts(new):fetchPullRequestPatch()wrapsgh, with friendly errors whenghis missing (ENOENT), the PR can't be fetched (surfacesghstderr — not-authenticated / not-found), or the diff is empty.src/core/cli.ts:--pr/--repooptions ondiff;parseDiffCommandreturns akind: "patch"input when--pris set.--prcombined with a target /--staged/ pathspecs errors out.src/core/types.ts:PatchCommandInput.labellets an in-memory patch carry a header label (PR #68), since it has no backing file.loadPatchChangesethonors it.generate:docs) + changeset + tests.Scope (deliberately an MVP)
Per the issue, this is the inbound direction only — open a PR to review it. Left as follow-ups so this PR stays focused:
Happy to adjust the surface (e.g.
patchvsdiff, flag naming,--repoinclusion) if you'd prefer a different shape.Verification
bun run typecheck— clean.bun test src/core/cli.test.ts src/core/github.test.ts src/core/loaders.test.ts— pass. New coverage:github.test.ts(success,--repopassthrough, URL label,ghmissing, non-zero exit, empty diff) andcli.test.ts(diff --pr→ patch input,--pr+ target rejected).bun run lint— 0 warnings/errors.bun run check:docs— clean after regen.gh: fetches the patch and parses tokind: "patch",label: "PR #68".