Skip to content

chore: improve pull request reviewer list#2193

Open
janburzinski wants to merge 9 commits into
mainfrom
jan/eng-1176-improve-pull-requests-page-reviewer-list
Open

chore: improve pull request reviewer list#2193
janburzinski wants to merge 9 commits into
mainfrom
jan/eng-1176-improve-pull-requests-page-reviewer-list

Conversation

@janburzinski
Copy link
Copy Markdown
Collaborator

@janburzinski janburzinski commented May 22, 2026

summary

  • persisted pr reviewer
  • sync github pr and latest review states into local db
  • add reviewer badge in in pr list
  • add review-state filters
image

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 22, 2026

Greptile Summary

This PR persists PR reviewer data into a new pull_request_reviewers table, syncing reviewer states (approved, changes_requested, commented, pending) from GitHub's latestReviews + reviewRequests GraphQL fields on every PR sync. It adds reviewer avatar badges in the PR list row and a review-state filter dropdown with eight options (including user- and team-aware filters).

  • DB layer: New pull_request_reviewers table with composite PK (pull_request_url, user_id), two indexes, and cascade-delete FK constraints. _upsertOne now builds reviewer rows via buildReviewerRows, deletes the old reviewer set for the PR, and re-inserts all current reviewers.
  • Query layer: fetchRelated joins pullRequestReviewers per batch; buildReviewStateCondition translates eight ReviewStateFilter values into subquery conditions against the reviewer table. Team-aware filters resolve the current user's team IDs via a cached REST call.
  • UI layer: PrReviewerBadges renders up to three reviewer avatars with state dots (approval = green dot, changes requested = red dot, pending = muted/greyscale avatar); a ReviewsFilterDropdown drives the new filter state in usePrViewState.

Confidence Score: 5/5

Safe to merge — the reviewer sync, DB schema, and filter logic are all well-structured with no correctness issues found.

The migration, schema, sync engine, query service, and UI components all fit together cleanly. The latestReviews GraphQL field eliminates the old multi-review-per-user ordering complexity; reviewer state transitions (approved → pending on re-request, DISMISSED → removed) are handled correctly. The eight review-state filter variants produce correct SQL subqueries, and the team-aware filter correctly falls back when the viewer has no teams. Only minor style observations were found.

No files require special attention.

Important Files Changed

Filename Overview
drizzle/0012_tearful_vermin.sql New migration creating pull_request_reviewers table with composite PK, two indexes, and cascade-delete FKs. Correct schema; missing newline at EOF.
src/main/db/schema.ts Adds pullRequestReviewers table definition mirroring the migration. Schema structure, indexes, and FK references are consistent with the migration file.
src/main/core/pull-requests/pr-sync-engine.ts Core reviewer sync logic added: buildReviewerRows processes latestReviews + reviewRequests, _upsertOne deletes and re-inserts reviewer rows. The createdAt sort in buildReviewerRows is now a no-op since latestReviews returns one entry per reviewer.
src/main/core/pull-requests/pr-query-service.ts fetchRelated now joins pullRequestReviewers; buildReviewStateCondition handles all 8 ReviewStateFilter cases correctly including team-aware subqueries.
src/renderer/features/projects/components/pr-view/pr-row.tsx Adds PrReviewerBadges component with ReviewerAvatar. Filters out commented reviewers from display; overflow tooltip shows names and review states correctly.
src/renderer/features/projects/components/pr-view/usePrViewState.ts Adds reviewStateFilter state and viewer-teams query. currentUserTeamIds gracefully degrades to undefined when the user has no teams or teams haven't loaded yet.
src/main/core/github/services/viewer-teams-service.ts New service fetching authenticated user's teams via REST API. teamReviewerId(team.id) correctly maps to the same ID format used by the GraphQL sync path.
src/shared/pull-requests.ts Adds ReviewStateFilter union type, TEAM_REVIEWER_ID_PREFIX, teamReviewerId/isTeamReviewerId helpers, and PullRequestReviewer type with isTeam flag. Clean additions.
src/shared/github.ts Adds GitHubViewerTeam type used by the new getViewerTeams RPC. Straightforward type addition.
src/main/core/github/controller.ts Adds getViewerTeams RPC handler with authentication guard and error handling (returns empty array on failure).
src/renderer/features/projects/components/pr-view/usePullRequests.ts Minor: getFilterOptions query key now consistently uses repositoryUrl. No functional changes to the hook logic.
src/main/core/pull-requests/pr-utils.ts assemblePullRequest now maps reviewer rows with isTeam flag via isTeamReviewerId. normalizeReviewState provides safe fallback for unknown states.
src/renderer/features/projects/components/pr-view/pr-view.tsx Adds ReviewsFilterDropdown to the filter bar; user-specific options are disabled when not authenticated. Toggle/clear interaction is clean.

Sequence Diagram

sequenceDiagram
    participant GH as GitHub GraphQL
    participant SE as PrSyncEngine._upsertOne
    participant DB as SQLite (pull_request_reviewers)
    participant QS as PrQueryService.listPullRequests
    participant UI as Renderer (PrReviewerBadges)

    SE->>GH: latestReviews(first:100) + reviewRequests(first:100)
    GH-->>SE: reviews[] + reviewRequests[]
    SE->>SE: "buildReviewerRows()<br/>DISMISSED → delete from map<br/>reviewRequests → overwrite as pending"
    SE->>DB: "DELETE FROM pull_request_reviewers WHERE pr_url=?"
    SE->>DB: INSERT/UPSERT each reviewer row
    Note over DB: (pull_request_url, user_id) PK<br/>reviewState: approved|changes_requested|commented|pending

    UI->>QS: listPullRequests(projectId, filters)
    QS->>DB: "SELECT pull_requests JOIN pull_request_reviewers<br/>WHERE reviewState subquery condition"
    DB-->>QS: PullRequest rows with reviewer joins
    QS-->>UI: PullRequest[] with reviewers[]
    UI->>UI: "PrReviewerBadges — filter commented out<br/>show up to 3 avatars with state dots"
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
src/main/core/pull-requests/pr-sync-engine.ts:161
The `sort()` call is a no-op now that the fragment uses `latestReviews` instead of `reviews(last: N)`. `latestReviews` returns at most one review per reviewer, so chronological ordering has no effect on the "later entry wins" map logic. The sort can be dropped.

```suggestion
  const reviews = node.reviews.nodes.slice();
```

### Issue 2 of 2
drizzle/0012_tearful_vermin.sql:11
Missing newline at end of file. Some tooling (e.g., `diff`, linters) can warn about this; adding a trailing newline keeps the file POSIX-conformant.

Reviews (4): Last reviewed commit: "Fix pull request filter reset state" | Re-trigger Greptile

Comment thread src/main/core/github/services/pr-queries.ts
Comment thread src/renderer/features/projects/components/pr-view/pr-row.tsx Outdated
@janburzinski
Copy link
Copy Markdown
Collaborator Author

@greptileai

@janburzinski
Copy link
Copy Markdown
Collaborator Author

@greptileai

@janburzinski
Copy link
Copy Markdown
Collaborator Author

@greptileai

@arnestrickmann
Copy link
Copy Markdown
Contributor

Thanks!

How frequently is the "reviewers" data updated? Below, for example, you can see how the most recent PR is rendered.

CleanShot 2026-05-23 at 17 34 55@2x

As you can see in the second picture, Jona has been set as a reviewer, but is not rendered in image Nr 1
CleanShot 2026-05-23 at 17 35 38@2x

Do you know what the issue could be here?

@janburzinski
Copy link
Copy Markdown
Collaborator Author

oh probably because reviewer data is cached locally here and refreshed on project open/manual/5min this should probably always jsut get the freshest data :D

@arnestrickmann
Copy link
Copy Markdown
Contributor

happy to have another look after resolving the merge conflicts:)

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