Skip to content

Mobile: GitHub pull request review#4621

Open
iscekic wants to merge 19 commits into
mainfrom
feature/mobile-github-pr-review
Open

Mobile: GitHub pull request review#4621
iscekic wants to merge 19 commits into
mainfrom
feature/mobile-github-pr-review

Conversation

@iscekic

@iscekic iscekic commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a full GitHub pull request review experience to the mobile app: paste or tap a PR link, then review the PR end to end — overview + checks, file diffs with syntax highlighting, line-level comments with a client-side pending-review queue, discussion threads with replies/resolve/reactions, and merge / auto-merge / update-branch — all backed by the user's GitHub App authorization.

What's included

Mobile (apps/mobile)

  • PR review route tree (entry, [owner]/[repo]/[number] layout + Overview/Files/Discussion tabs, and comment-composer / review-submit / file-navigator / merge form-sheets), gated behind a GitHub connect gate.
  • Overview (state, checks with paginated statuses), Files (lazy diff pagination, syntax highlighting via lowlight, expand-context, viewed tracking, file navigator + search, tablet side-by-side), Discussion (threads grouped by file, replies, optimistic resolve/unresolve + reactions), and a PR-scoped pending-review queue with a single batched submission.
  • Merge section: merge / squash / rebase with editable commit fields, blocked-reason panel, update-branch, and auto-merge enable/disable.
  • Device-local recents + viewed state (SecureStore), keyed to head SHA.

Web (apps/web)githubPrReview tRPC router (reads: getPullRequest, listChecks, listFiles, getFileLines, listReviewThreads; mutations: create/reply/submit review, resolve/unresolve, add/remove reaction, merge, update-branch, enable/disable auto-merge), proxying GitHub REST + GraphQL through a single 401→rotate→retry→report boundary.

git-token-service — internal user-token endpoint that fetches/rotates/reports the caller's GitHub App user token, scoped to a dedicated internal-JWT audience.

Testing

  • Unit/integration: mobile (1232), git-token-service (500), worker-utils (300), web github-pr-review (96) — all green; typecheck, lint, format, and check:unused clean.
  • On-device E2E (iOS simulator, deterministic mock GitHub REST/GraphQL/OAuth server): entry validation, recents, overview + checks pagination, files render/expand, comment composition + selection + queue + suggestion, discussion (incl. multi-cursor-page comment pagination), resolve, merge (happy squash with mock-verified merge call, blocked-reasons panel, auto-merge sheet), and error states (500 retry+heal, 404 unavailable + install CTA, rate-limit).

E2E surfaced and fixed three real bugs, each with regression coverage:

  1. listFiles/listReviewThreads .strict() inputs rejected tRPC's injected infinite-query direction param (every page 400'd).
  2. Href<typeof PATH> with group-prefixed route literals failed the generated typed-routes constraint.
  3. GraphQL variables were passed at the top level of octokit.request('POST /graphql', …) instead of nested under variables, so they never reached GitHub — silently dropping nested comment pages and breaking all pagination cursors + GraphQL mutations against real GitHub.

iscekic added 17 commits July 18, 2026 01:30
- getPullRequest: propagate raw 401 from GraphQL enrichment to the token
  retry boundary instead of silently degrading
- Checks/Files/Discussion: dedicated reconnect state (re-check connection)
  instead of an ineffective same-query retry
- classifyPrReviewMutationError: forbidden (terminal) and reconnect classes;
  applied to comment/reply/submit/merge surfaces
- de-duplicate the diff syntax token-color palette into syntax-colors.ts
- explicit useThemeColors colors for merge Lucide icons
- drop the dead side-by-side selection path (read-only)
…wThreads

The mobile useInfiniteQuery integration injects a direction discriminator into
the procedure input; the .strict() schemas rejected it, 400-ing every files/
threads page. Accept it explicitly and add regression coverage.
Href<typeof PATH> with a group-prefixed literal fails the generated typed-routes
constraint; match the working plain-Href pattern used elsewhere in the feature.
octokit.request('POST /graphql', {query, ...vars}) sends variables at the top
level, where GitHub ignores them (all $variables resolve null). This silently
dropped nested comment pages and would break thread pagination cursors and every
GraphQL mutation (resolve/unresolve/reactions/auto-merge) against real GitHub.
Nest under `variables` at all four call sites; update the follow-up test. E2E
against a strict GraphQL mock now returns the second comment page.
@iscekic iscekic self-assigned this Jul 18, 2026
Comment thread services/git-token-service/src/github-user-authorization-service.ts Fixed
Comment thread apps/mobile/src/lib/pr-review/diff/pr-diff-list-builder.ts
Comment thread apps/mobile/src/lib/pr-review/diff/pr-diff-list-builder.ts
Comment thread apps/mobile/src/lib/github-pr-url.ts Outdated
Comment thread apps/mobile/src/lib/pr-review/classify-pr-review-query-state.ts Outdated
Comment thread apps/mobile/src/lib/pr-review/merge/merge-commit-defaults.ts Outdated
Comment thread services/git-token-service/src/github-user-authorization-service.ts
@kilo-code-bot

kilo-code-bot Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

All 6 previously flagged WARNINGs (side-by-side gap layout, malformed-patch fallback, path-traversal-like owner/repo capture, inconsistent UNAUTHORIZED classification, no-op merge method default, and unpersisted terminal_rejection) are fixed at the current commit, each with a regression test; no new issues were introduced in the incremental diff.

Files Reviewed (13 files, incremental)
  • apps/mobile/src/components/pr-review/merge/pr-merge-sheet.tsx
  • apps/mobile/src/lib/github-pr-url.ts (+ test)
  • apps/mobile/src/lib/pr-review/classify-pr-review-query-state.ts (+ test)
  • apps/mobile/src/lib/pr-review/diff/pr-diff-gap-builder.ts
  • apps/mobile/src/lib/pr-review/diff/pr-diff-list-builder.ts (+ tests, incl. new side-by-side test file)
  • apps/mobile/src/lib/pr-review/merge/merge-commit-defaults.ts (+ test)
  • services/git-token-service/src/github-user-authorization-service.ts (+ test)
Previous Review Summary (commit 73905d0)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 73905d0)

Status: 6 Issues Found | Recommendation: Address before merge

Executive Summary

The highest-risk issue is a logic gap in the mobile diff-list builder (pr-diff-list-builder.ts) where side-by-side (tablet) layout interleaves full-width unified rows for gap/context sections, breaking the two-column rendering for most expanded files.

Overview

Severity Count
CRITICAL 0
WARNING 6
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
apps/mobile/src/lib/pr-review/diff/pr-diff-list-builder.ts 176 Gap rows not adapted for side-by-side view mode, breaking tablet layout
apps/mobile/src/lib/pr-review/diff/pr-diff-list-builder.ts 133 Malformed (but non-empty) patch renders empty expanded file with no fallback UI
apps/mobile/src/lib/github-pr-url.ts 8 Owner/repo capture groups too permissive, allow path-traversal-like values
apps/mobile/src/lib/pr-review/classify-pr-review-query-state.ts 93 UNAUTHORIZED classified inconsistently between query (permission, dead-end) and mutation (reconnect, recoverable) paths
apps/mobile/src/lib/pr-review/merge/merge-commit-defaults.ts 11 method parameter has no effect on returned commit message default
services/git-token-service/src/github-user-authorization-service.ts 114 terminal_rejection outcome not persisted via revokeCurrentGeneration, unlike the equivalent branch in getUserAccessToken, causing repeated refresh attempts against a dead grant
Files Reviewed (139 files)
  • apps/mobile/package.json
  • apps/mobile/vitest.config.ts
  • apps/mobile/src/app/(app)/_layout.tsx
  • apps/mobile/src/app/(app)/pr-review/index.tsx
  • apps/mobile/src/app/(app)/pr-review/[owner]/[repo]/[number]/_layout.tsx
  • apps/mobile/src/app/(app)/pr-review/[owner]/[repo]/[number]/comment-composer.tsx
  • apps/mobile/src/app/(app)/pr-review/[owner]/[repo]/[number]/file-navigator.tsx
  • apps/mobile/src/app/(app)/pr-review/[owner]/[repo]/[number]/index.tsx
  • apps/mobile/src/app/(app)/pr-review/[owner]/[repo]/[number]/merge.tsx
  • apps/mobile/src/app/(app)/pr-review/[owner]/[repo]/[number]/review-submit.tsx
  • apps/mobile/src/components/agents/chat-link-actions.ts (+ test) - 0 issues
  • apps/mobile/src/components/agents/chat-markdown-text.tsx - 0 issues
  • apps/mobile/src/components/agents/markdown-text.tsx - 0 issues
  • apps/mobile/src/components/pr-review/** (diff, discussion, merge, screens) - 2 issues
  • apps/mobile/src/components/profile-screen.tsx - 0 issues
  • apps/mobile/src/lib/auth/auth-context.tsx - 0 issues
  • apps/mobile/src/lib/github-pr-url.ts (+ test) - 1 issue
  • apps/mobile/src/lib/hooks/is-tablet.ts, use-is-tablet.ts (+ test) - 0 issues
  • apps/mobile/src/lib/profile-agent-navigation.ts - 0 issues
  • apps/mobile/src/lib/storage-keys.ts - 0 issues
  • apps/mobile/src/lib/pr-review/** (diff, discussion, merge, mutations, providers, bridges) - 4 issues
  • apps/web/src/lib/github-pr-review/** (client, dtos, errors, mappers, mutations, retry, dev-seed) - 0 issues
  • apps/web/src/lib/integrations/platforms/github/** (user-authorization, user-token-client, user-token-envelope) - 0 new issues (existing CodeQL finding excluded)
  • apps/web/src/routers/github-pr-review-router.ts, github-apps-router.ts, root-router.ts - 0 issues
  • packages/worker-utils/src/index.ts, internal-service-token-audiences.ts - 0 issues
  • services/git-token-service/src/** - 1 issue
  • pnpm-lock.yaml - skipped (generated file)

Fix these issues in Kilo Cloud


Reviewed by claude-sonnet-5 · Input: 24 · Output: 3.6K · Cached: 606.7K

Review guidance: REVIEW.md from base branch main

- github-pr-url: restrict owner/repo to GitHub's charset and reject dot-only
  segments (no path-traversal-like values)
- classify query state: UNAUTHORIZED -> reconnect (matches mutation path);
  FORBIDDEN stays terminal permission
- merge-commit-defaults: drop the no-op method param
- diff list builder: route non-empty-but-unparsable patches through the
  patch-missing fallback; render gap/expand rows correctly in side-by-side
- git-token-service: persist revocation on terminal_rejection during selection;
  rewrite the OAuth base-URL regex to avoid polynomial backtracking (ReDoS)
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.

2 participants