Skip to content

feat(dashboard): add check run external links and rerun buttons#164

Merged
stylessh merged 8 commits intostylessh:mainfrom
monotykamary:feat/check-runs-rerun-and-links
Apr 22, 2026
Merged

feat(dashboard): add check run external links and rerun buttons#164
stylessh merged 8 commits intostylessh:mainfrom
monotykamary:feat/check-runs-rerun-and-links

Conversation

@monotykamary
Copy link
Copy Markdown
Contributor

@monotykamary monotykamary commented Apr 21, 2026

Summary

Adds GitHub Actions-equivalent CI controls to the PR checks section — re-run buttons and external links to check runs on github.com.

Changes

1. htmlUrl on PullCheckRun type (github.types.ts)

  • Adds htmlUrl: string | null to surface the GitHub check run URL

2. rerunChecks server function + shared helpers (github.functions.ts)

  • deduplicateCheckRuns — extracted from computePullStatus, now shared with rerunChecks
  • isFailedCheckRun — pure function mirroring the UI getCheckRunStatus logic (any completed check that isn't success/neutral/skipped/null)
  • rerunChecks — new POST server function that:
    • Fetches the PR head SHA
    • Lists and deduplicates check runs
    • When failedOnly: true, re-runs only failed checks
    • When failedOnly: false, re-runs all checks
    • Uses checks.rerequestRun API
    • Busts pull detail caches on success
  • Refactors computePullStatus to use deduplicateCheckRuns

3. PR checks section UI (pull-detail-activity.tsx)

  • External link icon (↗) on each check run row, linking to the run on github.com
    • Uses group/run + group-hover/run:opacity-100 pattern (matches existing group/comment, group/label patterns)
  • "Re-run failed checks" button — appears when checks have failures
  • "Re-run all checks" button — appears when any checks exist
  • Both buttons follow the ghost/xs/Spinner pattern from UpdateBranchButton and MergeFooter
  • ChecksSection now receives owner/repo/pullNumber props

4. Unit tests (github-check-runs.test.ts)

  • 15 tests covering deduplicateCheckRuns (5) and isFailedCheckRun (10)
  • Follows project convention: pure unit tests on pure functions, vitest + describe/it/expect

Atomic commits

Commit Scope
f24e4a0 Type: add htmlUrl to PullCheckRun
ce1c6fb Server: rerunChecks fn + shared helpers + refactor computePullStatus
b8ee1d2 UI: external links + rerun buttons in checks section
c0b63fe Tests: 15 unit tests for deduplicateCheckRuns and isFailedCheckRun

Permission note

The existing GitHub App permission Actions: Read-only is sufficient for the UI to display checks. To fully enable re-running checks, the App permission needs to be upgraded to Actions: Read & write — this is already documented in the README permissions table with the note: "Workflow run history and logs (upgrade to Read & write for rerun/cancel)". If the token lacks write access, the existing 403 error handling + install URL flow will guide users.

Screenshots (conceptual)

Before: Check runs show name, status, and app avatar only.

After:

  • Each row gets an external link icon (↗) on hover → links to github.com/owner/repo/actions/runs/...
  • Below the check runs list: Re-run failed checks + Re-run all checks buttons

Testing

✓ src/lib/github-check-runs.test.ts (15 tests)
✓ All 73 existing tests pass (1 pre-existing failure in tab-store.test.ts unrelated)
✓ pnpm check-types passes
✓ biome check passes on all changed files

Summary by CodeRabbit

  • New Features

    • Re-run checks (all or failed) and approve pending workflow runs from the PR UI, with loading/disabled states and toast feedback
    • Check runs: clickable links, “Required”/“Expected” labels, and grouped status ordering for clearer results
    • PR/issue state badges now use a unified StatePill for consistent visuals
  • Documentation

    • README: added webhook event coverage for status, workflow run, and branch/repository protection
  • Tests

    • Added tests for check-run deduplication and failed-check detection

Surface the GitHub check run URL in the type so the UI can link
directly to the run on github.com.
…n helpers

Extract deduplicateCheckRuns and isFailedCheckRun as pure shared
helpers used by both computePullStatus and the new rerunChecks
mutation. The rerunChecks server function calls GitHub's
checks.rerequestRun API to re-trigger failed or all check runs
for a given pull request.

- RerunChecksInput extends PullFromRepoInput (project convention)
- Refactors computePullStatus to use deduplicateCheckRuns
- isFailedCheckRun mirrors the UI's getCheckRunStatus logic
- Passes html_url through computePullStatus mapping
…ction

- Add external link icon (↗) to each check run row, linking to the
  run on github.com. Uses group-hover/run opacity pattern matching
  existing project conventions.
- Add 'Re-run failed checks' button when checks have failures
- Add 'Re-run all checks' button when any checks exist
- Both buttons follow the ghost/xs/Spinner pattern used by
  UpdateBranchButton and MergeFooter
- Pass owner/repo/pullNumber through ChecksSection props
…CheckRun

15 tests covering deduplication by name/id, all failure conclusion
variants (failure, timed_out, cancelled, action_required), and all
non-failure conclusions (success, neutral, skipped, null).
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 21, 2026

Caution

Review failed

Pull request was closed or merged during review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds check-run/approval management: server mutations (rerunChecks, approveWorkflowRuns), check-run utilities (dedupe, failure classifier), PullStatus extensions (expected, pendingWorkflowApprovals, htmlUrl, required), UI wiring for approve/rerun, StatePill UI component, tests, and revalidation/cache-policy updates.

Changes

Cohort / File(s) Summary
Server check-run logic & mutations
apps/dashboard/src/lib/github.functions.ts
Added deduplicateCheckRuns, isFailedCheckRun; expanded computePullStatus to fetch checks/statuses/workflows, synthesize expected checks and pendingWorkflowApprovals; added rerunChecks and approveWorkflowRuns server mutations, types, refined 403 handling and cache-busting.
Types
apps/dashboard/src/lib/github.types.ts
Extended PullCheckRun with htmlUrl and required; added PullWorkflowApproval; added checks.expected and pendingWorkflowApprovals to PullStatus.
Pull detail UI: checks & approvals
apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
ChecksSection now receives pendingWorkflowApprovals and repo/pull identifiers; added approve/rerun handlers, loading states, approval banner, per-run links/labels, grouped run ordering, permission/toast flows.
Pull detail UI: header & page revalidation
apps/dashboard/src/components/pulls/detail/pull-detail-header.tsx, apps/dashboard/src/components/pulls/detail/pull-detail-page.tsx
Replaced inline state badge with StatePill; pull-status webhook refresh targets now include repo-level repoStatuses revalidation signal.
Issue/PR state configs
apps/dashboard/src/components/issues/detail/issue-detail-header.tsx, apps/dashboard/src/lib/pr-state.ts
Replaced badgeClass strings with tone: StatePillTone; updated returned tones for issue/PR states to use StatePill.
UI component: StatePill
packages/ui/src/components/state-pill.tsx
New StatePill component and exported StatePillTone type with tone variants (open, closed, merged, muted, secondary).
Cache invalidation / revalidation
apps/dashboard/src/lib/github-revalidation.ts, apps/dashboard/src/lib/github-cache-policy.ts, apps/dashboard/src/components/pulls/detail/pull-detail-page.tsx
Added repoProtection and repoStatuses signal keys; derive pull signals from workflow_run.pull_requests; added repoProtection cache policy; updated webhookRefreshTargets to include repoStatuses.
Tests
apps/dashboard/src/lib/github-check-runs.test.ts, apps/dashboard/src/lib/github-cache-invalidation.test.ts
New tests for deduplicateCheckRuns and isFailedCheckRun; extended webhook revalidation tests to cover repository ruleset/branch protection/status/workflow_run mappings.
Docs
README.md
Updated webhook events checklist/table: enabled Status, Repository ruleset, Branch protection rule, and reintroduced Workflow run with updated descriptions.

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as ChecksSection (Client)
    participant Server as API Server
    participant GH as GitHub API

    User->>UI: Click "Re-run checks" / "Approve workflows"
    UI->>UI: set isRerunning / isApproving = true
    UI->>Server: POST rerunChecks / approveWorkflowRuns (owner,repo,pullNumber,workflowRunIds,failedOnly)

    Server->>GH: Get PR head SHA, list check runs, combined statuses, workflow runs
    GH-->>Server: returns PR/checkRuns/statuses/workflowRuns

    Server->>Server: deduplicateCheckRuns, filter failedOnly (if set)
    alt approveWorkflowRuns
        Server->>GH: Approve workflow run(s)
        GH-->>Server: approval responses (success/fail)
    else rerunChecks
        loop per deduped run
            alt Actions workflow run
                Server->>GH: Actions re-run endpoint
            else Checks API
                Server->>GH: checks.rerequestRun
            end
            GH-->>Server: ok / 403(resource-shape) -> mark skipped
        end
    end

    Server->>Server: Bust pull-detail caches (pullEntity + repoStatuses keys)
    Server-->>UI: result { ok, rerun/skipped/approved/failed, partial }
    UI->>UI: invalidate queries, set isRerunning/isApproving = false
    UI-->>User: show toast (success/partial/failure)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding external links and rerun buttons for check runs, which is the primary feature across all modified components.
Description check ✅ Passed The description follows the template structure with Summary, Changes, Test Plan sections, provides detailed breakdown of modifications across files, includes atomic commit information, permission notes, and testing results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@monotykamary monotykamary marked this pull request as ready for review April 21, 2026 12:08
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
apps/dashboard/src/lib/github-check-runs.test.ts (1)

126-134: Rename this test description to match its payload.

Line 126 says “still running”, but Line 131 sets status: "completed". Renaming avoids semantic drift in test intent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/src/lib/github-check-runs.test.ts` around lines 126 - 134, The
test description for the unit testing is mismatched: update the it(...)
description for the test that calls isFailedCheckRun with status: "completed"
and conclusion: null so it accurately reflects the payload (e.g., change
"returns false for null conclusion (still running)" to "returns false for null
conclusion (completed)"); locate the it block that invokes isFailedCheckRun({...
status: "completed", conclusion: null ...}) and replace only the human-readable
string to match the payload.
apps/dashboard/src/lib/github.functions.ts (1)

750-759: Reuse this helper in computePullStatus too.

Failure semantics are centralized here, but computePullStatus still keeps a second hard-coded classifier at Lines 3757-3769. That makes checks.failed and failedOnly easy to drift apart. Tally failures via isFailedCheckRun so button visibility and rerun targeting stay in lockstep.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/src/lib/github.functions.ts` around lines 750 - 759,
computePullStatus currently reimplements failure semantics with a hard-coded
classifier (the block around lines 3757-3769) causing drift from the central
helper; replace that ad-hoc check with calls to the exported
isFailedCheckRun(run: CheckRunPayload) helper when tallying failed checks (e.g.,
wherever checks.failed or failedOnly are computed) so both failure counts and
rerun/visibility logic use the same predicate. Locate computePullStatus and swap
any conditionals like run.status === "completed" && run.conclusion !== ... for
isFailedCheckRun(run) and ensure any aggregates (failed count/failedOnly flag)
use that function.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx`:
- Around line 888-897: The external link anchor that renders when run.htmlUrl
exists currently hides the icon with opacity-0 except on hover; update the
anchor (the <a> that wraps ExternalLinkIcon where run.htmlUrl is checked) to
make it discoverable and accessible by adding an accessible name (e.g.,
aria-label={`Open check run in new tab`} or include visually-hidden text inside
the anchor) and adjust classes so the icon is visible to keyboard users (e.g.,
add group-focus/run:opacity-100 and focus-visible:opacity-100 or ensure
non-hover devices see it by default), and ensure rel/target remain unchanged;
this ensures the ExternalLinkIcon is both keyboard-focusable and screen-reader
labeled.

In `@apps/dashboard/src/lib/github.functions.ts`:
- Around line 6088-6104: Replace the single-page call to
context.octokit.rest.checks.listForRef with a paginated fetch using
listPaginatedGitHubItems to collect all check runs for pr.data.head.sha, then
pass the full array to deduplicateCheckRuns and proceed to compute runsToRerun
(respecting data.failedOnly and isFailedCheckRun) — i.e., call
listPaginatedGitHubItems for the checks endpoint, assemble the flattened check
run list, then use deduplicateCheckRuns(checkRuns) and the existing runsToRerun
logic.

---

Nitpick comments:
In `@apps/dashboard/src/lib/github-check-runs.test.ts`:
- Around line 126-134: The test description for the unit testing is mismatched:
update the it(...) description for the test that calls isFailedCheckRun with
status: "completed" and conclusion: null so it accurately reflects the payload
(e.g., change "returns false for null conclusion (still running)" to "returns
false for null conclusion (completed)"); locate the it block that invokes
isFailedCheckRun({... status: "completed", conclusion: null ...}) and replace
only the human-readable string to match the payload.

In `@apps/dashboard/src/lib/github.functions.ts`:
- Around line 750-759: computePullStatus currently reimplements failure
semantics with a hard-coded classifier (the block around lines 3757-3769)
causing drift from the central helper; replace that ad-hoc check with calls to
the exported isFailedCheckRun(run: CheckRunPayload) helper when tallying failed
checks (e.g., wherever checks.failed or failedOnly are computed) so both failure
counts and rerun/visibility logic use the same predicate. Locate
computePullStatus and swap any conditionals like run.status === "completed" &&
run.conclusion !== ... for isFailedCheckRun(run) and ensure any aggregates
(failed count/failedOnly flag) use that function.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3ecec03c-f83b-47c2-8ffe-9d19c288117d

📥 Commits

Reviewing files that changed from the base of the PR and between d0a7690 and c0b63fe.

📒 Files selected for processing (4)
  • apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
  • apps/dashboard/src/lib/github-check-runs.test.ts
  • apps/dashboard/src/lib/github.functions.ts
  • apps/dashboard/src/lib/github.types.ts

Comment thread apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx Outdated
Comment thread apps/dashboard/src/lib/github.functions.ts Outdated
- Paginate checks.listForRef in rerunChecks using
  listPaginatedGitHubItems to handle >100 check runs
- Add aria-label and focus-visible opacity to check run
  external links for accessibility (keyboard/screen-reader)
- Use prefersNoHover to show links on non-hover devices
- Use isFailedCheckRun in computePullStatus tallying to
  keep failure semantics in sync with rerun filtering
- Fix test description: null conclusion with completed
  status is not 'still running'
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx (1)

909-941: Remove redundant footer wrapper condition.

checks.total > 0 is already guaranteed when ChecksSection is rendered (Line 494), so this guard always evaluates true.

♻️ Suggested simplification
-				{(hasCheckFailures || checks.total > 0) && (
-					<div className="flex items-center gap-2 border-b border-border/50 bg-surface-1/50 px-4 py-1.5 pl-11">
-						{hasCheckFailures && (
-							<Button
-								variant="ghost"
-								size="xs"
-								disabled={isRerunning}
-								className="h-6 text-xs text-muted-foreground"
-								iconLeft={
-									isRerunning ? (
-										<Spinner size={12} />
-									) : (
-										<RefreshCwIcon size={12} strokeWidth={2} />
-									)
-								}
-								onClick={() => void handleRerun(true)}
-							>
-								Re-run failed checks
-							</Button>
-						)}
-						{checks.total > 0 && (
-							<Button
-								variant="ghost"
-								size="xs"
-								disabled={isRerunning}
-								className="h-6 text-xs text-muted-foreground"
-								onClick={() => void handleRerun(false)}
-							>
-								Re-run all checks
-							</Button>
-						)}
-					</div>
-				)}
+				<div className="flex items-center gap-2 border-b border-border/50 bg-surface-1/50 px-4 py-1.5 pl-11">
+					{hasCheckFailures && (
+						<Button
+							variant="ghost"
+							size="xs"
+							disabled={isRerunning}
+							className="h-6 text-xs text-muted-foreground"
+							iconLeft={
+								isRerunning ? (
+									<Spinner size={12} />
+								) : (
+									<RefreshCwIcon size={12} strokeWidth={2} />
+								)
+							}
+							onClick={() => void handleRerun(true)}
+						>
+							Re-run failed checks
+						</Button>
+					)}
+					<Button
+						variant="ghost"
+						size="xs"
+						disabled={isRerunning}
+						className="h-6 text-xs text-muted-foreground"
+						onClick={() => void handleRerun(false)}
+					>
+						Re-run all checks
+					</Button>
+				</div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx` around
lines 909 - 941, The outer conditional "(hasCheckFailures || checks.total > 0)
&&" around the footer div is redundant because ChecksSection already guarantees
checks.total > 0; remove that guard and render the footer div unconditionally
(leave the inner hasCheckFailures conditional for the "Re-run failed checks"
Button and keep the "Re-run all checks" Button using handleRerun). This affects
the JSX block that contains hasCheckFailures, checks.total, the footer div, and
the Buttons that call handleRerun.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx`:
- Around line 909-941: The outer conditional "(hasCheckFailures || checks.total
> 0) &&" around the footer div is redundant because ChecksSection already
guarantees checks.total > 0; remove that guard and render the footer div
unconditionally (leave the inner hasCheckFailures conditional for the "Re-run
failed checks" Button and keep the "Re-run all checks" Button using
handleRerun). This affects the JSX block that contains hasCheckFailures,
checks.total, the footer div, and the Buttons that call handleRerun.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 09c4b3ad-0fc9-4ba9-ac53-2510f050daff

📥 Commits

Reviewing files that changed from the base of the PR and between c0b63fe and 68e6fa5.

📒 Files selected for processing (3)
  • apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
  • apps/dashboard/src/lib/github-check-runs.test.ts
  • apps/dashboard/src/lib/github.functions.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/dashboard/src/lib/github-check-runs.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/dashboard/src/lib/github.functions.ts

Copy link
Copy Markdown
Owner

Thanks for the contribution!

…orkflow approvals

- Fetch commit statuses (CodeRabbit/CircleCI) alongside check runs
- Show required and "Expected" checks sourced from branch rulesets
- Surface workflow-approval banner + approveWorkflowRuns server fn
- Route reruns via actions API (reRunWorkflow / reRunWorkflowFailedJobs)
  for GitHub Actions jobs; per-run rerequest for other apps
- Group the checks list by status (Expected, Failed, Pending, Skipped, Passed)
- Extract reusable StatePill component for Open/Merged/Closed/Draft badges
- Webhook signals for status, workflow_run → pullEntity,
  repository_ruleset/branch_protection → repoProtection
- Distinguish 403-resource errors from 403-auth in mutation handling
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx (1)

774-796: Handle the approval-only state in the checks summary.

ChecksSection now renders even when there are no check runs yet, but this title/description block still reads only from checks.*. If pendingWorkflowApprovals.length > 0 and checks.total === 0, the section shows 0 pending checks / 0 successful checks, which is misleading above the approval banner.

Suggested adjustment
 	const pendingTotal = checks.pending + checks.expected;
+	const hasPendingApprovals = pendingWorkflowApprovals.length > 0;

 	const title = allChecksPassed
 		? "All checks have passed"
 		: hasCheckFailures
 			? `${checks.failed} failing check${checks.failed > 1 ? "s" : ""}`
-			: `${pendingTotal} pending check${pendingTotal > 1 ? "s" : ""}`;
+			: pendingTotal > 0
+				? `${pendingTotal} pending check${pendingTotal > 1 ? "s" : ""}`
+				: hasPendingApprovals
+					? `${pendingWorkflowApprovals.length} workflow${pendingWorkflowApprovals.length > 1 ? "s" : ""} awaiting approval`
+					: "No checks reported";

 	const parts: string[] = [];
 	if (checks.skipped > 0) parts.push(`${checks.skipped} skipped`);
 	parts.push(
 		`${checks.passed} successful check${checks.passed !== 1 ? "s" : ""}`,
 	);
 	if (checks.pending > 0) parts.push(`${checks.pending} pending`);
 	if (checks.expected > 0) parts.push(`${checks.expected} expected`);
 	if (checks.failed > 0) parts.push(`${checks.failed} failing`);
-	const description = parts.join(", ");
+	const description =
+		checks.total === 0 && hasPendingApprovals
+			? "This workflow requires approval from a maintainer."
+			: parts.join(", ");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx` around
lines 774 - 796, When pendingWorkflowApprovals.length > 0 and checks.total ===
0, treat this as an "approval-only" state and avoid showing the misleading
checks summary: update the logic that computes title and description (the
variables title, description and the parts array in pull-detail-activity.tsx) to
branch for approval-only and produce an approval-specific title/description
(e.g., "X pending approval(s)" and an appropriate description or empty string)
instead of using checks.* counts; reference pendingWorkflowApprovals,
checks.total, title, description and parts when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx`:
- Around line 1562-1571: The frontend getCheckRunStatus currently treats any
completed run without success/neutral/skipped/stale as "failure", which includes
conclusion === null and mismatches the backend isFailedCheckRun; update
getCheckRunStatus (the function named getCheckRunStatus) so that if run.status
!== "completed" OR run.conclusion === null it returns "pending" instead of
"failure", preserving the existing branches for "expected", "success", and
"skipped"; any other completed runs with a non-null conclusion should still
return "failure".

In `@apps/dashboard/src/lib/github.functions.ts`:
- Around line 6399-6404: The current return path treats any partial rerun as
full success; update the mutation result logic in the block that currently
returns "{ ok: true, rerun, skipped }" so that if hardFailures.length > 0 you
either return a failure via toMutationError (e.g., describing "partial rerun
failures") or return an explicit partial-failure payload the client can handle
(include fields like partial: true and hardFailures). Ensure you still call
bustPullDetailCaches(context.session.user.id, data) when appropriate but change
the final return to reflect partial failures by inspecting rerun, hardFailures
and skipped so the UI can surface dropped checks.
- Around line 3791-3798: computePullStatus is currently calling
context.octokit.rest.checks.listForRef(...) which only returns the first page
(100) of check runs; replace that call with listPaginatedGitHubItems to fetch
all pages (pass the same params: owner: data.owner, repo: data.repo, ref:
pull.head.sha, per_page: 100) and then pass the full array into
deduplicateCheckRuns, preserving existing error handling (e.g., return null or
empty array on error) so downstream code expecting a list still works.

In `@README.md`:
- Around line 247-250: Update the "Subscribe to events" setup checklist in
README.md to include the additional webhook events listed in the table: add
entries for "Status", "Repository ruleset", "Branch protection rule", and
"Workflow run" so the setup steps match the table rows; ensure the checklist
items explicitly instruct subscribing to the corresponding webhook event types
and any required checkboxes/options referenced by the table labels, and verify
the language matches existing checklist styling under the "Subscribe to events"
section.

---

Nitpick comments:
In `@apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx`:
- Around line 774-796: When pendingWorkflowApprovals.length > 0 and checks.total
=== 0, treat this as an "approval-only" state and avoid showing the misleading
checks summary: update the logic that computes title and description (the
variables title, description and the parts array in pull-detail-activity.tsx) to
branch for approval-only and produce an approval-specific title/description
(e.g., "X pending approval(s)" and an appropriate description or empty string)
instead of using checks.* counts; reference pendingWorkflowApprovals,
checks.total, title, description and parts when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ed0e7cbc-7ac7-43c4-be3f-3d76fd2f46e5

📥 Commits

Reviewing files that changed from the base of the PR and between 68e6fa5 and f541ae6.

📒 Files selected for processing (12)
  • README.md
  • apps/dashboard/src/components/issues/detail/issue-detail-header.tsx
  • apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
  • apps/dashboard/src/components/pulls/detail/pull-detail-header.tsx
  • apps/dashboard/src/components/pulls/detail/pull-detail-page.tsx
  • apps/dashboard/src/lib/github-cache-invalidation.test.ts
  • apps/dashboard/src/lib/github-cache-policy.ts
  • apps/dashboard/src/lib/github-revalidation.ts
  • apps/dashboard/src/lib/github.functions.ts
  • apps/dashboard/src/lib/github.types.ts
  • apps/dashboard/src/lib/pr-state.ts
  • packages/ui/src/components/state-pill.tsx

Comment thread apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
Comment thread apps/dashboard/src/lib/github.functions.ts Outdated
Comment thread apps/dashboard/src/lib/github.functions.ts
Comment thread README.md
- getCheckRunStatus: treat completed+null conclusion as pending (match backend)
- computePullStatus: paginate checks.listForRef to cover PRs with >100 runs
- rerunChecks: surface partial failures via { partial, failed } on result; UI
  shows a warning toast instead of a green success when some reruns hard-fail
- ChecksSection: when checks.total === 0 but workflows await approval, render
  an approval-only title/description instead of "0 pending checks"
- Approve workflows CTA: keep loading state until webhook drains the pending
  approvals list, with a 30s safety timeout
- README: align Subscribe to events setup checklist with the webhook table
  (Status, Repository ruleset, Branch protection rule, Workflow run)
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/dashboard/src/lib/github.functions.ts`:
- Around line 6457-6476: The current approveWorkflowRun batch (inside
approveWorkflowRun Promise.allSettled block) treats any non-empty success set as
full success and returns { ok: true }, hiding partial failures; change the logic
after computing results and rejected to surface partial failures by checking if
rejected.length > 0 and either (a) return a partial-failure mutation payload
containing which run IDs failed and their rejection reasons, or (b) treat any
rejection as overall failure by calling toMutationError with aggregated rejected
reasons; update the branch that currently only checks rejected.length ===
data.workflowRunIds.length to instead handle rejected.length > 0 (use
data.workflowRunIds, results, rejected, approveWorkflowRun, toMutationError and
bustPullDetailCaches to decide whether to call bustPullDetailCaches only on full
success or still call it and include partial-failure metadata).
- Around line 3809-3824: computePullStatus is only fetching the first page of
commit statuses and workflow runs via
context.octokit.rest.repos.getCombinedStatusForRef and
context.octokit.rest.actions.listWorkflowRunsForRepo, which truncates results on
busy PRs; replace those single-page calls with paginated fetches (use
context.octokit.paginate or the rest.paginate helper) to retrieve all pages for
getCombinedStatusForRef and listWorkflowRunsForRepo (remove the fixed
per_page=100 limit), then aggregate the paginated results into the same shape
the rest of computePullStatus expects so check runs and workflow runs are
complete.
- Around line 6331-6341: The run URL parser in the loop that inspects
run.html_url is too strict; update the regex used where match is computed so it
accepts both /actions/runs/{id} and /runs/{id} and allows a trailing slash, a
query string, or end-of-string as terminators. Locate the block that checks
run.app?.slug === "github-actions" and the match = run.html_url?.match(...)
expression, replace the current pattern with one that captures the numeric id
from either "/actions/runs/123" or "/runs/123" and uses a non-capturing group
for the optional "actions/" prefix and a lookahead or alternation to allow "/"
or "?" or end-of-string after the id; keep the rest of the logic that converts
match[1] to Number and sets actionsRunIdByCheck/actionsRunIds unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 81f8f623-a4d9-4aa1-8f43-3461b6a2f480

📥 Commits

Reviewing files that changed from the base of the PR and between f541ae6 and 49921a4.

📒 Files selected for processing (3)
  • README.md
  • apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
  • apps/dashboard/src/lib/github.functions.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • README.md

Comment thread apps/dashboard/src/lib/github.functions.ts Outdated
Comment thread apps/dashboard/src/lib/github.functions.ts
Comment thread apps/dashboard/src/lib/github.functions.ts Outdated
- approveWorkflowRuns: surface partial failures via { approved, failed, partial }
  matching the rerunChecks shape; UI shows a warning toast on partial success
- Broaden GHA workflow-run URL regex to accept /actions/runs/{id} OR /runs/{id}
  with `/`, `?`, or end-of-string terminators (still guarded by app.slug)
- Paginate getCombinedStatusForRef + listWorkflowRunsForRepo in computePullStatus
  so large PRs don't truncate statuses or miss approval-awaiting workflow runs
- Dedup combined statuses by context across pages
Copy link
Copy Markdown
Owner

@stylessh stylessh left a comment

Choose a reason for hiding this comment

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

Thanks!

@stylessh stylessh merged commit aee6eee into stylessh:main Apr 22, 2026
1 of 2 checks passed
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