import { DocsActionButton } from "@/components/docs/docs-github-action-button";

# GitHub Actions

Add React Doctor to GitHub Actions to catch security risks and performance regressions on every pull request.

## Install with the CLI

If React Doctor detects a supported coding agent, run the installer from the project root:

```bash
npx react-doctor@latest install
```

Choose **Yes** when it asks to add React Doctor to GitHub Actions. React Doctor writes `.github/workflows/react-doctor.yml`, adds a `doctor` package script, and then continues with agent setup.

## Add the workflow manually

If you want a CI-only setup, create `.github/workflows/react-doctor.yml`:

```yaml
name: React Doctor

on:
  # Scans the PR's changed files and posts a sticky summary comment listing only the new issues introduced relative to the merge base of the target branch.
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
  # Scans `main` on every push to track the health-score trend and catch regressions that slipped past PR review.
  push:
    branches: [main]

permissions:
  contents: read
  pull-requests: write
  issues: write
  statuses: write

# Cancels any in-flight scan for the same PR (or branch, on push) the moment a new commit arrives, so reviewers only ever see the latest run.
concurrency:
  group: react-doctor-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  react-doctor:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
        with:
          fetch-depth: 0
      - uses: millionco/react-doctor@v2
```

Create a pull request against `main` to start the check. The workflow passes when React Doctor finds no blocking security, performance, or correctness issues in the changed files.

### Configure the first scan

React Doctor blocks pull requests by default, but it scans only changed files so old issues don't stop unrelated work. To map existing security and performance debt before you enforce the gate, run the first full scan in advisory mode:

```yaml
- uses: millionco/react-doctor@v2
  with:
    blocking: none # or: `warning` or `error`
    scope: full # or: `changed`
```

`blocking: none` reports issues without failing the check. `scope: full` scans the whole project instead of only the changed files.

After the first pass, remove both options to use the default behavior: React Doctor blocks new warnings and errors on changed files. To roll out gradually, start with `blocking: none`, move to the default `error` gate next, and use `blocking: warning` only after the project has a stable baseline.

For more configuration options, see the [Action reference](/docs/reference/github-action-reference).

#### Monorepos and subdirectories

Point the Action at an app in a subfolder with `directory`:

```yaml
- uses: millionco/react-doctor@v2
  with:
    directory: apps/web
```

By default (`project: "*"`) it finds and scans every React project. To scan only some, list them:

```yaml
- uses: millionco/react-doctor@v2
  with:
    project: "web,admin"
```

## What happens on a pull request

On a pull request, React Doctor reports findings in the PR conversation, inline review comments, and CI logs.

{/* TODO: put a screenshot of the CI here */}

For example, [CDCgov/cdc-open-viz#2868](https://github.com/CDCgov/cdc-open-viz/pull/2868) changed `3` files on `fix/nonnumeric-circles` against `dev`. React Doctor posted `No React Doctor issues found in this scan` with a `100/100 (Great)` score for that pull request scope.

That scope matters. The check passed because the changed files had no findings. When React Doctor finds a new issue on a changed line, it leaves an inline review comment, updates the same summary comment, and reports a failing commit status for branch protection.

Pushes to `main` only record the score, with no comment and no failure, so `main` never goes red over old issues.

### Pull request feedback

The Action creates or updates one sticky summary comment instead of stacking new comments. The comment shows issue counts, the score, links each error to its `file:line`, groups warnings by file, and notes what your change added or fixed.

Inline review comments appear on changed lines that triggered a diagnostic. Each comment includes a suggested fix and a link to the relevant docs. React Doctor caps inline comments so the summary stays the complete record.

Every run also includes full terminal output in the CI logs. Reviewers can use the logs when PR comments are disabled or unavailable.

### Feedback controls

Use Action inputs to control where feedback appears:

```yaml
- uses: millionco/react-doctor@v2
  with:
    comment: false
    review-comments: false
    commit-status: false
```

`comment` needs `issues: write`, `review-comments` needs `pull-requests: write`, and `commit-status` needs `statuses: write`. To control what reaches the pull request comment, use `surfaces.prComment` in your React Doctor config.

## Not on GitHub?

The scanner is a plain CLI, so it runs on GitLab CI, CircleCI, Jenkins, and Buildkite. See [Other CI providers](/docs/ci-and-prs/other-ci-providers).

## Troubleshooting

### It flagged tons of old issues on a PR

The checkout couldn't find where your PR started. Add `fetch-depth: 0` to the `actions/checkout` step.

### No comment showed up

Check the workflow has `pull-requests: write` and `issues: write`, and that `comment` isn't `false`. Comments never appear on `push` runs, only pull requests.

### The status or score isn't showing

That needs `statuses: write` (unless you set `commit-status: false`). The Action warns in the run log when the permission is missing.

### It's failing PRs before the team is ready

Set `blocking: none` to report findings without failing the workflow, then tighten later.

### A failing check doesn't block the merge

Add the React Doctor check as required under **Settings → Branches → Branch protection rules**. Without that, a red check shows but the merge button still works.

### PRs from forks don't get comments

GitHub blocks write access on fork PRs for security. The scan still runs and still passes or fails; it can't post a comment.
