chore: integrate react-doctor scanning#9223
Conversation
Add react-doctor for React lint/a11y/perf/architecture diagnostics: - Add react-doctor devDependency and "doctor" npm script - Add .claude/skills/react-doctor skill for local triage workflow - Add GitHub Actions workflow to scan PRs and track health score
📝 WalkthroughWalkthroughThis PR integrates React Doctor, a code quality scanning tool for React codebases, into the repository. It adds skill documentation defining the tool's workflows and commands, a GitHub Actions automation for running scans on PRs and main branch pushes, and project configuration adding the dependency and npm scripts for local development use. ChangesReact Doctor Integration
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
No React Doctor issues found. 🎉 Reviewed by React Doctor for commit |
There was a problem hiding this comment.
Pull request overview
Integrates React Doctor into the repository as additive tooling to scan React code for security/performance/correctness/accessibility issues, including a CI workflow and a local developer script, plus contributor guidance via a Claude skill.
Changes:
- Added a root
doctorscript andreact-doctordevDependency. - Added a GitHub Actions workflow to run React Doctor on PRs and on pushes to the default branch.
- Added a
.claudeskill document describing local regression scans and a full triage workflow.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| package.json | Adds react-doctor devDependency and a doctor script for local scanning. |
| .github/workflows/react-doctor.yml | Introduces CI automation to run React Doctor on PRs and on default-branch pushes. |
| .claude/skills/react-doctor/SKILL.md | Adds contributor/agent instructions for running and triaging React Doctor results. |
| "prepare": "husky", | ||
| "doctor": "npx react-doctor@latest" |
| push: | ||
| branches: [main] |
| react-doctor: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v5 |
There was a problem hiding this comment.
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 49-51: Replace the tag-based action references with immutable
commit SHAs and disable checkout credential persistence: update the step that
uses actions/checkout@v5 to use the corresponding commit SHA instead of the tag
and add a with: persist-credentials: false mapping to that checkout step, and
replace millionco/react-doctor@v2 with its exact commit SHA; target the "uses:
actions/checkout" and "uses: millionco/react-doctor" lines in the workflow to
make these edits so the job token isn’t persisted and the actions are pinned to
immutable SHAs.
In `@package.json`:
- Around line 20-21: Update the non-deterministic "doctor" npm script to pin the
react-doctor version and change the devDependency spec to the repo's
external-dependency format: set "doctor" to use npx react-doctor@0.4.2 (instead
of `@latest`) and change devDependencies.react-doctor from "^0.4.2" to the catalog
specifier (e.g., "catalog:react-doctor@0.4.2") so the script and dependency
resolution are deterministic and match the pnpm lock state.
🪄 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: 21342314-c9b3-4ee4-b408-1eeff96cf841
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
.claude/skills/react-doctor/SKILL.md.github/workflows/react-doctor.ymlpackage.json
| - uses: actions/checkout@v5 | ||
|
|
||
| - uses: millionco/react-doctor@v2 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
ls -la .github/workflows || true
sed -n '1,140p' .github/workflows/react-doctor.yml | nl -ba | sed -n '1,140p'
echo "---- exact lines 40-70 ----"
nl -ba .github/workflows/react-doctor.yml | sed -n '40,75p'Repository: makeplane/plane
Length of output: 879
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "---- head (first 120 lines with line numbers) ----"
awk '{printf "%6d\t%s\n", NR, $0}' .github/workflows/react-doctor.yml | sed -n '1,120p'
echo "---- lines 40-80 (for requested range) ----"
awk '{printf "%6d\t%s\n", NR, $0}' .github/workflows/react-doctor.yml | sed -n '40,80p'
echo "---- search for persist-credentials ----"
rg -n "persist-credentials" .github/workflows/react-doctor.yml || true
echo "---- search for actions/checkout usage ----"
rg -n "uses:\s*actions/checkout@" .github/workflows/react-doctor.yml || trueRepository: makeplane/plane
Length of output: 5048
🌐 Web query:
actions/checkout persist-credentials default true false meaning git config credential.helper
💡 Result:
The actions/checkout action uses the persist-credentials input to determine whether to configure the authentication token or SSH key in the local Git configuration [1][2]. Key details regarding persist-credentials: Default Value: true [1][2] Functionality: When set to true (the default), the action configures the provided authentication token or SSH key into the repository's local Git configuration [3][4][2]. This allows subsequent git commands (e.g., git fetch, git push) executed within the same job to use the same authentication credentials automatically [3][4][2]. Opt-out: Setting persist-credentials: false prevents the action from modifying the local Git configuration with these credentials [3][4]. Post-job Cleanup: The action includes a post-job step that automatically removes the persisted credentials from the Git configuration to maintain security [4][2]. Git Configuration Mechanism: Instead of using the Git credential helper (git config credential.helper), the action writes the authentication details directly into the local Git configuration (e.g., using git config --local) [4][5]. For HTTPS, it often sets up credential-related configurations like insteadOf to ensure the provided token is used for repository operations [5]. In summary, persist-credentials is not an option for configuring git config credential.helper; rather, it is a feature of the actions/checkout action that manually manages Git repository authentication by directly editing local Git config files, which are then cleaned up after the job completes [3][4][5].
Citations:
- 1: https://github.com/actions/checkout/blob/34e114876b0b11c390a56381ad16ebd13914f8d5/action.yml
- 2: https://github.com/actions/checkout/blob/main/action.yml
- 3: https://github.com/actions/checkout/?tab=readme-ov-file
- 4: actions/checkout@c170eef
- 5: https://github.com/actions/checkout/blob/5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f/src/git-auth-helper.ts
Pin workflow actions to commit SHAs and disable checkout credential persistence.
actions/checkout@v5andmillionco/react-doctor@v2are tag-based; pin both to immutable commit SHAs to avoid supply-chain drift.- Add
with: persist-credentials: falseto checkout so the job token/credentials aren’t written into the local git configuration for later steps.
Suggested patch
jobs:
react-doctor:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v5
+ - uses: actions/checkout@<full_commit_sha>
+ with:
+ persist-credentials: false
- - uses: millionco/react-doctor@v2
+ - uses: millionco/react-doctor@<full_commit_sha>🧰 Tools
🪛 zizmor (1.25.2)
[warning] 49-49: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 49-49: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 51-51: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 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 @.github/workflows/react-doctor.yml around lines 49 - 51, Replace the
tag-based action references with immutable commit SHAs and disable checkout
credential persistence: update the step that uses actions/checkout@v5 to use the
corresponding commit SHA instead of the tag and add a with: persist-credentials:
false mapping to that checkout step, and replace millionco/react-doctor@v2 with
its exact commit SHA; target the "uses: actions/checkout" and "uses:
millionco/react-doctor" lines in the workflow to make these edits so the job
token isn’t persisted and the actions are pinned to immutable SHAs.
Source: Linters/SAST tools
| "prepare": "husky", | ||
| "doctor": "npx react-doctor@latest" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the relevant portion of package.json
if [ -f package.json ]; then
echo "== package.json =="
nl -ba package.json | sed -n '1,120p'
else
echo "package.json not found at repo root"
fi
# Check if repo uses pnpm 'catalog:' specifiers
echo
echo "== Search for 'catalog:' in repo =="
rg -n "catalog:" . || true
echo
echo "== Search for react-doctor usage =="
rg -n "react-doctor" . || true
echo
echo "== Search for react-doctor version pin/cat entry examples (package manager config) =="
rg -n "doctor\"|react-doctor@|react-doctor" package.json pnpm-workspace.yaml .npmrc .pnpmfile.cjs .pnpmfile.js . || true
# If a catalog/workflow file exists, list common locations
echo
echo "== List potential catalog files =="
find . -maxdepth 3 -type f \( -iname "*catalog*" -o -iname "*versions*" -o -iname "*pnpmfile*" -o -iname "*lock*" \) | head -n 50 || trueRepository: makeplane/plane
Length of output: 139
🏁 Script executed:
#!/bin/bash
set -euo pipefail
if [ -f package.json ]; then
echo "== package.json =="
awk '{printf "%6d\t%s\n", NR, $0}' package.json | sed -n '1,140p'
else
echo "package.json not found at repo root"
exit 0
fi
echo
echo "== Search for 'catalog:' in repo =="
rg -n "catalog:" . || true
echo
echo "== Search for 'react-doctor' in repo =="
rg -n "react-doctor" . || true
echo
echo "== Search for doctor script in package.json =="
rg -n "\"doctor\"\s*:" package.json || true
echo
echo "== Show scripts/deps block if present (best-effort) =="
# Print a smaller window around scripts/devDependencies if the file is longer
rg -n '"scripts"\s*:' package.json || true
rg -n '"devDependencies"\s*:' package.json || trueRepository: makeplane/plane
Length of output: 43581
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Extract small windows around react-doctor entries in pnpm-lock.yaml
echo "== react-doctor@0.4.2 windows =="
rg -n "react-doctor@0\.4\.2" pnpm-lock.yaml | head -n 20
# Use the first match line number from rg and print a window around it (if found)
LINE=$(rg -n "react-doctor@0\.4\.2" pnpm-lock.yaml | head -n 1 | cut -d: -f1)
if [ -n "${LINE:-}" ]; then
START=$((LINE-40))
END=$((LINE+80))
echo
echo "== Around react-doctor@0.4.2 at line ${LINE} (pnpm-lock.yaml) =="
sed -n "${START},${END}p" pnpm-lock.yaml
fi
echo
echo "== Search for 'bin' or 'executables' references near react-doctor =="
rg -n "bin:|executables:|react-doctor" pnpm-lock.yaml | head -n 50Repository: makeplane/plane
Length of output: 5861
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show more context around react-doctor@0.4.2 entries
for L in 8523 16586; do
echo
echo "== pnpm-lock.yaml around react-doctor@0.4.2 at line $L =="
START=$((L-40))
END=$((L+120))
sed -n "${START},${END}p" pnpm-lock.yaml | sed -n '1,200p'
done
echo
echo "== Search for 'hasBin' near react-doctor =="
# Limit output by extracting only lines containing hasBin that are close to react-doctor occurrences
rg -n "hasBin:|react-doctor@0\.4\.2" pnpm-lock.yaml | head -n 80Repository: makeplane/plane
Length of output: 12609
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Show tight window around react-doctor@0.4.2 in pnpm-lock.yaml (lines ~8515-8545) =="
sed -n '8515,8545p' pnpm-lock.yaml
echo
echo "== Search for an explicit bin mapping near react-doctor in pnpm-lock.yaml =="
rg -n "react-doctor@0\.4\.2:|react-doctor@0\.4\.2\(|bin:" pnpm-lock.yaml | head -n 50
echo
echo "== Search for occurrences of 'bin:' in a small neighborhood around those matches =="
# Print 40 lines after each match for react-doctor@0.4.2 lines
rg -n "react-doctor@0\.4\.2" pnpm-lock.yaml | head -n 5 | cut -d: -f1 | while read -r L; do
START=$((L-5))
END=$((L+25))
echo
echo "---- Neighborhood: ${START}-${END} ----"
sed -n "${START},${END}p" pnpm-lock.yaml
doneRepository: makeplane/plane
Length of output: 6494
Make the doctor script deterministic and fix react-doctor’s dependency spec.
package.jsonruns"doctor": "npx react-doctor@latest"(non-deterministic drift).devDependencies.react-doctoris"^0.4.2"instead of the required external-dependencycatalog:specifier (repo usescatalog:for external deps, andpnpm-lock.yamlresolvesreact-doctor@0.4.2withhasBin: true).
Suggested patch
"scripts": {
@@
- "doctor": "npx react-doctor@latest"
+ "doctor": "pnpm exec react-doctor"
},
"devDependencies": {
@@
- "react-doctor": "^0.4.2",
+ "react-doctor": "catalog:",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "prepare": "husky", | |
| "doctor": "npx react-doctor@latest" | |
| "prepare": "husky", | |
| "doctor": "pnpm exec react-doctor" |
🤖 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 `@package.json` around lines 20 - 21, Update the non-deterministic "doctor" npm
script to pin the react-doctor version and change the devDependency spec to the
repo's external-dependency format: set "doctor" to use npx react-doctor@0.4.2
(instead of `@latest`) and change devDependencies.react-doctor from "^0.4.2" to
the catalog specifier (e.g., "catalog:react-doctor@0.4.2") so the script and
dependency resolution are deterministic and match the pnpm lock state.
Source: Coding guidelines
Description
Integrates React Doctor into the repo to surface security, performance, correctness, accessibility, bundle-size, and architecture issues in our React code, and to track an overall health score over time.
This PR wires it up in three places:
react-doctoras a devDependency and adoctorscript (npx react-doctor@latest) to the rootpackage.json, with the correspondingpnpm-lock.yamlupdates..claude/skills/react-doctorskill so contributors can run a regression check after React changes or a full local triage pass via/doctor, following the canonical playbook..github/workflows/react-doctor.ymlworkflow that scans changed files on PRs (posting a sticky summary comment and commit status) and scansmainon push to track the health-score trend. Configuration knobs (blocking level, scope, comments, version pinning) are documented inline and commented out by default.No application code is changed; this is additive tooling/CI only.
Type of Change
Screenshots and Media (if applicable)
Test Scenarios
pnpm doctor(ornpx react-doctor@latest) locally and confirm it produces a 0–100 health score without crashing.concurrencygroup when a new commit is pushed to the same PR.mainand confirm a health-score commit status is published (no PR comment expected on push events).react-doctorskill is discoverable and that/doctorfetches and follows the canonical triage playbook.References
Summary by CodeRabbit
doctorcommand to run React codebase analysis locally.