Skip to content

Add React Doctor to GitHub Actions - #20

Merged
AndersonDesign1 merged 23 commits into
mainfrom
react-doctor/add-github-actions-202606090951
Jun 9, 2026
Merged

Add React Doctor to GitHub Actions#20
AndersonDesign1 merged 23 commits into
mainfrom
react-doctor/add-github-actions-202606090951

Conversation

@AndersonDesign1

@AndersonDesign1 AndersonDesign1 commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Adds a React Doctor scan to every pull request and every push to the default branch. The workflow file is documented inline.

Docs: https://www.react.doctor/ci

Summary by CodeRabbit

  • Chores

    • Added an automated React Doctor workflow for PRs and main branch scans.
  • New Features

    • Improved file upload flow with better validation and clearer upload error messages.
    • Centralized panel layout and consistent mutation error banners for clearer UI feedback.
  • UI Updates

    • Standardized card/panel layouts across dashboards and project pages.
    • Minor visual tweaks to buttons, badges, and date formatting.
  • Accessibility

    • Added reduced-motion support to respect user preference.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clientra Ready Ready Preview, Comment Jun 9, 2026 12:42pm

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@AndersonDesign1, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 21 minutes and 54 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2926da1b-d83e-4894-ab27-5ca00ffe4100

📥 Commits

Reviewing files that changed from the base of the PR and between 8f0225e and 4c978a8.

📒 Files selected for processing (5)
  • .gitignore
  • src/components/common/state-panel.tsx
  • src/components/evilcharts/ui/evil-brush.tsx
  • src/components/evilcharts/ui/tooltip.tsx
  • src/db/records.ts
📝 Walkthrough

Walkthrough

Adds React Doctor CI workflow and config; introduces shared UI primitives (PanelSection, MutationErrorBanner, optionalString), refactors charts/evilcharts and pending skeletons, updates many portal pages/routes and API handlers, reformats DB schema/migrations and Drizzle queries, and tweaks package scripts and styles.

Changes

Monolithic PR: tooling, shared UI, charts, routes, DB

Layer / File(s) Summary
React Doctor workflow & config
.github/workflows/react-doctor.yml, doctor.config.json, package.json
Adds a GitHub Actions workflow to run millionco/react-doctor on PRs and pushes to main; includes concurrency and scoped permissions. Adds doctor npm script and React Doctor config that ignores specified files and disables several rules.
Shared UI primitives
src/components/common/panel-section.tsx, src/components/common/state-panel.tsx, src/lib/utils.ts
Introduces PanelSection layout component, MutationErrorBanner component, and optionalString utility for trimmed-empty-to-undefined semantics.
Charts & evilcharts refactors
src/components/common/product-charts.tsx, src/components/evilcharts/*
Moves chart color palettes and sankey/node color maps to module-level constants; replaces inline empty-array defaults with shared constants; extracts loading skeletons/helpers; adjusts context memoization and styling rendering in chart UI.
Pending skeletons consolidation
src/components/common/route-pending.tsx
Centralizes skeleton ID arrays into shared constants and updates multiple pending-page components to iterate those constants.
Project feature panels & forms
src/components/projects/* (project-files-panel.tsx, project-milestones-panel.tsx, project-updates-panel.tsx, project-collaboration-panel.tsx)
Wraps panels with PanelSection, replaces inline error UI with MutationErrorBanner, introduces useCrudDialogs<T>(), swaps plain inputs for Field/Input/Select/Textarea patterns, and consolidates file-type icon/color logic.
Portal pages & API routes
src/routes/portal/*, src/routes/api/portal/*, src/routes/clients/$id.tsx, src/routes/projects/$id.tsx, src/routes/dashboard.tsx, src/routes/settings.tsx
Reformats authorization guards and handler early-returns, introduces shared date formatters, adds ChartCard wrapper, adjusts redirect loader to use router redirect, reorganizes UI markup and props ordering, and changes settings sync logic to ref-based/derived effect.
DB & migrations
scripts/migrate-portal.ts, src/db/schema.ts, src/db/records.ts
Reformats migration and schema references calls to multi-line forms; reorders/imports and reformats Drizzle query joins and discriminated unions; minor interface field order adjustments (no type changes).
Utilities, API, tests, minor fixes
src/lib/api.ts, src/lib/insights.ts, src/routes/api/*, src/__tests__/*, src/styles.css
Destructures query results for mapQueryState, refactors insight functions to imperative loops, small route handler formatting/early-return changes, adds prefers-reduced-motion media rule, and minor test/import reorders.

Sequence Diagram(s)

(since the PR adds a CI workflow that invokes checkout then runs react-doctor, a small sequence diagram is included above in the hidden artifact)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 A rabbit hops in with a checklist so neat,
Lints the React trees and keeps code tidy and neat.
New panels and charts in a warm, tidy line —
CI hums, builds pass, and the dashboard looks fine. 🥕

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch react-doctor/add-github-actions-202606090951

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

React Doctor found no issues. 🎉

Reviewed by React Doctor for commit 4c978a8.

@greptile-apps

greptile-apps Bot commented Jun 9, 2026

Copy link
Copy Markdown

Greptile Summary

This PR integrates React Doctor as a CI check on every PR and push to main, and bundles the auto-formatting changes the tool produced on the existing codebase. The workflow addition is straightforward; the bulk of the diff is React Doctor's reformatting output applied across ~45 source files.

  • New CI workflow (.github/workflows/react-doctor.yml) runs millionco/react-doctor@v2 on pull requests and main-branch pushes, with concurrency cancellation to avoid stale runs.
  • doctor.config.json is added to configure which files and rules to skip; 12 rules are disabled, including no-giant-component, prefer-dynamic-import, only-export-components, and unused-export/unused-file, scoping the scan to a narrower set of checks.
  • package.json removes @tanstack/router-plugin and web-vitals as direct dependencies (both are confirmed unused in source); it also adds a doctor convenience script using npx react-doctor@latest.

Confidence Score: 5/5

Safe to merge; changes are additive CI infrastructure plus formatting auto-fixes with no functional regressions

The workflow and config are new additive files, the dependency removals are confirmed safe (web-vitals is not imported anywhere; @tanstack/router-plugin remains as a transitive dep and is not referenced in vite.config.ts), and all source-file changes are React Doctor's own reformatting output with no altered runtime logic

doctor.config.json is worth a second look to confirm the 12 disabled rules represent intentional suppression and not accidental over-silencing of the scan

Important Files Changed

Filename Overview
.github/workflows/react-doctor.yml Adds React Doctor CI scan; both action refs use mutable version tags (already flagged in previous review threads)
doctor.config.json New React Doctor config that disables 12 rules and excludes ui/node_modules/dist directories; intentional configuration
package.json Removes @tanstack/router-plugin (still available as transitive dep via @tanstack/react-start) and web-vitals (unused in source); adds doctor convenience script with unpinned @latest tag
src/lib/insights.ts getNextDeadline and getBudgetByClientData refactored from array-chain to for-loop style; behavior is equivalent, no logic changes
src/lib/api.ts Formatting-only changes plus minor destructure refactor in usePendingInvitesData/useSearchData; interface field reordering (alphabetical) with no behavioral change
src/db/records.ts Pure formatting reformats (multi-line joins, expanded ternaries, brace-wrapped single-line returns); no logic changes
src/routes/portal/files.tsx Formatting changes plus a Map-based project lookup optimization in onClientUploadComplete; condition !a&&!b rewritten as !(a

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[PR opened or push to main] --> B{Event type}
    B -- pull_request --> C[Cancel in-flight scan for same PR]
    B -- push to main --> D[Cancel in-flight scan for same ref]
    C --> E[checkout]
    D --> E
    E --> F[millionco/react-doctor v2]
    F --> G[Read doctor.config.json]
    G --> H{Scan scope}
    H -- PR --> I[Changed files vs merge base]
    H -- push --> J[Full project health scan]
    I --> K[Sticky PR comment plus inline comments plus commit status]
    J --> L[Health score trend plus commit status]
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
package.json:16
The `doctor` script fetches and executes `react-doctor@latest` on every invocation via `npx`, so developers on the same codebase can get different scan results depending on when they run it. Pinning to the same major version used by the CI workflow (`@2`) keeps local runs consistent with CI.

```suggestion
    "doctor": "npx react-doctor@2"
```

Reviews (2): Last reviewed commit: "Merge branch 'main' into react-doctor/ad..." | Re-trigger Greptile

Comment thread .github/workflows/react-doctor.yml Outdated
steps:
- uses: actions/checkout@v5

- uses: millionco/react-doctor@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Third-party action not pinned to a commit SHA

millionco/react-doctor@v2 is a mutable tag — if the publisher force-pushes to that tag (intentionally or after a supply-chain compromise), the updated code will run automatically on every future PR with the pull-requests: write, issues: write, and statuses: write permissions granted here. GitHub's hardened-runner guidance and OSSF Scorecard both require pinning third-party actions to an immutable full-length commit SHA (e.g. millionco/react-doctor@<40-char-sha>). The commented-out version: input pins the react-doctor binary version but not the action's own JavaScript runner, so it does not close this gap.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/react-doctor.yml
Line: 34

Comment:
**Third-party action not pinned to a commit SHA**

`millionco/react-doctor@v2` is a mutable tag — if the publisher force-pushes to that tag (intentionally or after a supply-chain compromise), the updated code will run automatically on every future PR with the `pull-requests: write`, `issues: write`, and `statuses: write` permissions granted here. GitHub's hardened-runner guidance and OSSF Scorecard both require pinning third-party actions to an immutable full-length commit SHA (e.g. `millionco/react-doctor@<40-char-sha>`). The commented-out `version:` input pins the *react-doctor binary* version but not the action's own JavaScript runner, so it does not close this gap.

How can I resolve this? If you propose a fix, please make it concise.

Comment thread .github/workflows/react-doctor.yml Outdated
react-doctor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 actions/checkout also uses a mutable tag

actions/checkout@v5 points to a mutable version tag. While GitHub's own actions are lower risk than third-party ones, pinning to the full SHA is still the recommended practice for supply-chain hardness. Resolve the SHA with gh api /repos/actions/checkout/git/ref/tags/v5 (or check the release page) and pin it.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/react-doctor.yml
Line: 32

Comment:
**`actions/checkout` also uses a mutable tag**

`actions/checkout@v5` points to a mutable version tag. While GitHub's own actions are lower risk than third-party ones, pinning to the full SHA is still the recommended practice for supply-chain hardness. Resolve the SHA with `gh api /repos/actions/checkout/git/ref/tags/v5` (or check the release page) and pin it.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/react-doctor.yml:
- Around line 32-34: The workflow uses mutable tags actions/checkout@v5 and
millionco/react-doctor@v2 and leaves checkout credentials persisted; update the
checkout step to pin actions/checkout to its full commit SHA and replace
millionco/react-doctor@v2 with its corresponding full commit SHA, and add
persist-credentials: false to the checkout step to avoid persisting GITHUB_TOKEN
in git config; locate these tokens by searching for "actions/checkout@v5",
"millionco/react-doctor@v2", and the checkout step block (persist-credentials)
in the react-doctor.yml and replace accordingly.
- Line 32: The checkout step using "uses: actions/checkout@v5" currently
persists credentials; update that GitHub Actions step to include a with block
setting persist-credentials: false so the checkout token/SSH key is not written
to the runner git config (i.e., modify the step that references
actions/checkout@v5 to add "with: persist-credentials: false").
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: bdb5ddd9-49d4-4911-b2d1-0503fca36c8f

📥 Commits

Reviewing files that changed from the base of the PR and between a0e02c0 and 8a77b03.

📒 Files selected for processing (1)
  • .github/workflows/react-doctor.yml

Comment thread .github/workflows/react-doctor.yml Outdated
Comment thread .github/workflows/react-doctor.yml Outdated
@AndersonDesign1
AndersonDesign1 deleted the react-doctor/add-github-actions-202606090951 branch June 9, 2026 10:56
@AndersonDesign1
AndersonDesign1 restored the react-doctor/add-github-actions-202606090951 branch June 9, 2026 11:36

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/routes/settings.tsx (1)

166-184: 💤 Low value

isDefaultSettings used inside effect but not listed in dependencies.

The effect uses isDefaultSettings which is derived outside the effect. While this works because the underlying values (workspaceNameVal, supportEmailVal) are in the dependency array, this pattern may trigger exhaustive-deps lint warnings and creates an implicit dependency that could confuse maintainers.

Consider adding to dependency array for explicitness
   }, [
     isDefaultSettings,
+    isDefaultSettings,
     hasSettings,
     hasUser,
     currentUserName,
     currentUserEmail,
     workspaceNameVal,
     supportEmailVal,
   ]);

Or compute isDefaultSettings inside the effect body for self-contained logic.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/settings.tsx` around lines 166 - 184, The effect in the Settings
component references the external variable isDefaultSettings but doesn't include
it in the dependency array, causing an implicit dependency and potential lint
warnings; either add isDefaultSettings to the dependency array for the useEffect
that sets workspaceName/supportEmail, or move the isDefaultSettings computation
into the effect body so the effect is self-contained (update the useEffect
surrounding setWorkspaceName/setSupportEmail and the dependency list
accordingly).
src/db/records.ts (1)

645-655: ⚡ Quick win

Consider splitting the validation into separate, explicit checks.

The combined condition if (!(project && isValidTransition)) conflates two distinct error cases: a missing project and a no-op status change. Separating these would improve clarity and allow more specific error messages.

♻️ Suggested refactor for clarity
-      const isValidTransition =
-        project && project.status !== updated.requestedStatus;
-
-      if (!(project && isValidTransition)) {
+      if (!project) {
+        console.error(
+          `Status change approval failed: Project ${updated.projectId} not found.`
+        );
+        throw new Error(`Project ${updated.projectId} not found`);
+      }
+
+      if (project.status === updated.requestedStatus) {
         console.error(
-          `Status change approval failed: Project ${updated.projectId} missing or invalid transition to ${updated.requestedStatus}.`
+          `Status change approval failed: Project ${updated.projectId} is already in ${updated.requestedStatus} status.`
         );
-        throw new Error(
-          `Invalid status transition to ${updated.requestedStatus}`
-        );
+        throw new Error(`Project is already in ${updated.requestedStatus} status`);
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/db/records.ts` around lines 645 - 655, Split the combined conditional
that currently reads if (!(project && isValidTransition)) into two explicit
checks: first verify the existence of project and throw a clear "Project not
found" (or similar) error if missing, then separately check isValidTransition
and throw a distinct "No-op status change" or "Invalid status transition" error
if the transition is not allowed; update the function that performs the status
update (the block referencing project and isValidTransition) so it uses these
two checks and returns/throws the more specific error messages.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/common/state-panel.tsx`:
- Around line 58-69: The MutationErrorBanner currently renders errors in a plain
<p> so screen readers may not announce new messages; update the
MutationErrorBanner function to add live-region semantics to the banner element
by setting role="alert" and aria-live="assertive" (and optionally
aria-atomic="true") on the rendered paragraph element so assistive tech will
announce new mutation errors immediately while keeping the existing styling and
structure.

---

Nitpick comments:
In `@src/db/records.ts`:
- Around line 645-655: Split the combined conditional that currently reads if
(!(project && isValidTransition)) into two explicit checks: first verify the
existence of project and throw a clear "Project not found" (or similar) error if
missing, then separately check isValidTransition and throw a distinct "No-op
status change" or "Invalid status transition" error if the transition is not
allowed; update the function that performs the status update (the block
referencing project and isValidTransition) so it uses these two checks and
returns/throws the more specific error messages.

In `@src/routes/settings.tsx`:
- Around line 166-184: The effect in the Settings component references the
external variable isDefaultSettings but doesn't include it in the dependency
array, causing an implicit dependency and potential lint warnings; either add
isDefaultSettings to the dependency array for the useEffect that sets
workspaceName/supportEmail, or move the isDefaultSettings computation into the
effect body so the effect is self-contained (update the useEffect surrounding
setWorkspaceName/setSupportEmail and the dependency list accordingly).
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: d50e8dc2-d5d4-490d-b175-3e97cc5b0613

📥 Commits

Reviewing files that changed from the base of the PR and between 8a77b03 and 8f0225e.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (47)
  • .github/workflows/react-doctor.yml
  • doctor.config.json
  • package.json
  • scripts/migrate-portal.ts
  • src/__tests__/api-invite-management.test.ts
  • src/components/auth/auth-shell.tsx
  • src/components/auth/worker-invite-form.tsx
  • src/components/common/panel-section.tsx
  • src/components/common/product-charts.tsx
  • src/components/common/route-pending.tsx
  • src/components/common/state-panel.tsx
  • src/components/evilcharts/charts/bar-chart.tsx
  • src/components/evilcharts/charts/line-chart.tsx
  • src/components/evilcharts/charts/radial-chart.tsx
  • src/components/evilcharts/charts/sankey-chart.tsx
  • src/components/evilcharts/ui/chart.tsx
  • src/components/evilcharts/ui/evil-brush.tsx
  • src/components/evilcharts/ui/legend.tsx
  • src/components/evilcharts/ui/tooltip.tsx
  • src/components/layout/portal-shell.tsx
  • src/components/projects/project-collaboration-panel.tsx
  • src/components/projects/project-files-panel.tsx
  • src/components/projects/project-milestones-panel.tsx
  • src/components/projects/project-updates-panel.tsx
  • src/db/records.ts
  • src/db/schema.ts
  • src/lib/api.ts
  • src/lib/insights.ts
  • src/lib/utils.ts
  • src/routes/api/admin/status-change-requests.ts
  • src/routes/api/admin/status-change-requests/$id.ts
  • src/routes/api/clients/$id/invites.ts
  • src/routes/api/invites/$id/approve.ts
  • src/routes/api/portal/activity.ts
  • src/routes/api/portal/files.ts
  • src/routes/api/portal/status-change-requests.ts
  • src/routes/api/portal/team.ts
  • src/routes/clients/$id.tsx
  • src/routes/dashboard.tsx
  • src/routes/portal/activity.tsx
  • src/routes/portal/files.tsx
  • src/routes/portal/index.tsx
  • src/routes/portal/projects/$id.tsx
  • src/routes/portal/team.tsx
  • src/routes/projects/$id.tsx
  • src/routes/settings.tsx
  • src/styles.css
✅ Files skipped from review due to trivial changes (14)
  • src/routes/api/admin/status-change-requests.ts
  • src/routes/api/clients/$id/invites.ts
  • doctor.config.json
  • src/routes/api/portal/activity.ts
  • scripts/migrate-portal.ts
  • src/components/evilcharts/charts/line-chart.tsx
  • src/styles.css
  • src/tests/api-invite-management.test.ts
  • src/routes/api/invites/$id/approve.ts
  • src/db/schema.ts
  • src/routes/clients/$id.tsx
  • src/routes/portal/activity.tsx
  • src/routes/portal/team.tsx
  • src/components/evilcharts/charts/bar-chart.tsx

Comment thread src/components/common/state-panel.tsx
… to formatter in tooltip, and exclude react-doctor-report.json in gitignore
@AndersonDesign1
AndersonDesign1 merged commit 4c978a8 into main Jun 9, 2026
4 of 6 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.

1 participant