Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 143 additions & 38 deletions packages/cli-doctor/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# @percy/cli-doctor

> Percy CLI sub-command that diagnoses network readiness for running Percy builds.
> Percy CLI sub-command that diagnoses network, authentication, configuration, and CI readiness for running Percy builds.

---

Expand Down Expand Up @@ -30,31 +30,79 @@ percy doctor [options]
Options:
--proxy-server <url> Proxy server to test alongside direct connectivity
e.g. http://proxy.corp.example.com:8080
--url <urls> Extra URL(s) to probe (comma-separated)
--timeout <ms> Per-request timeout in milliseconds (default: 10000)
--fix Automatically apply suggested Percy config fixes
-v, --verbose Log everything
--url <url> URL to open in Chrome for network activity analysis
(default: https://percy.io)
--timeout <ms> Per-request timeout in milliseconds
(default: 10000, max: 300000)
--quick Run only connectivity, SSL, and token auth checks
(~4 seconds instead of a full diagnostic run)
--output-json <path> Write the full diagnostic report to a JSON file
-v, --verbose Show detailed debug output
-h, --help Show help
```

---

## What it checks

### 1 · SSL / TLS
### 1 · Configuration Validation

| Scenario | Outcome |
Detects and validates Percy configuration files (`.percy.yml`, `.percy.yaml`, `percy.config.js`, etc.) via cosmiconfig:

- Reports file location and format
- Warns on missing or outdated `version` field (recommends version 2)
- Detects project-type/config mismatches (e.g., automate-only keys like `fullPage` used with a web token)

| Category | Meaning |
|---|---|
| `NODE_TLS_REJECT_UNAUTHORIZED=0` is set | **Warning** – SSL verification is disabled globally |
| SSL certificate error connecting to percy.io | **Fail** – likely a MITM proxy/VPN; suggests remediation |
| SSL handshake succeeds | **Pass** |
| `config_not_found` | No Percy config file detected |
| `config_found` | Config file located and loaded |
| `config_parse_error` | Config file has YAML/JSON syntax errors |
| `config_version_invalid` | `version` field is missing or non-numeric |
| `config_version_outdated` | Config uses an outdated version (< 2) |
| `config_key_automate_only` | Config contains Automate-only keys but token is not Automate |
| `config_key_web_only` | Config contains Web-only keys but token is not a Web token |

### 2 · CI Environment Detection

When a certificate error is detected, the command:
* Prints actionable suggestions (contact network admin, add proxy cert to trust store)
* With `--fix`: patches the nearest `.percy.yml` to add `ssl: { rejectUnauthorized: false }`
* When running interactively in a TTY: offers an inline yes/no prompt
Detects your CI provider and validates CI-related settings:

### 2 · Network Connectivity
- Identifies 10+ CI systems (GitHub Actions, GitLab CI, Jenkins, CircleCI, Travis, etc.)
- Validates git availability for commit/branch detection
- Checks parallel build configuration (`PERCY_PARALLEL_TOTAL` + `PERCY_PARALLEL_NONCE`)

| Category | Meaning |
|---|---|
| `ci_not_detected` | Not running in a CI environment |
| `ci_detected` | CI system identified |
| `ci_commit_missing` | Commit SHA could not be detected |
| `ci_commit_found` | Commit SHA available |
| `ci_branch_missing` | Branch name could not be detected |
| `ci_parallel_nonce_missing` | `PERCY_PARALLEL_TOTAL` set without `PERCY_PARALLEL_NONCE` |
| `ci_parallel_config_valid` | Both parallel env vars are set correctly |
| `ci_git_available` | Git repository detected |
| `ci_git_check_skipped` | Git check suppressed via `PERCY_SKIP_GIT_CHECK=true` |
| `ci_git_unavailable` | Git not installed or not in a git repository |

### 3 · Environment Variable Audit

Inventories all Percy-specific environment variables:

- Lists all set `PERCY_*` vars (names only — values are never exposed)
- Validates `PERCY_PARALLEL_TOTAL` is a positive integer
- Flags manual overrides (`PERCY_COMMIT`, `PERCY_BRANCH`, `PERCY_PULL_REQUEST`)
- Warns when `NODE_TLS_REJECT_UNAUTHORIZED=0` disables SSL validation

| Category | Meaning |
|---|---|
| `env_system_info` | OS, Node version, CPU, and RAM summary |
| `env_no_percy_vars` | No `PERCY_*` environment variables detected |
| `env_vars_listed` | Lists names of all set `PERCY_*` variables |
| `env_parallel_total_invalid` | `PERCY_PARALLEL_TOTAL` is not a valid positive integer |
| `env_manual_overrides` | Manual override vars active (e.g. `PERCY_COMMIT`, `PERCY_BRANCH`) |
| `env_tls_disabled` | `NODE_TLS_REJECT_UNAUTHORIZED=0` — SSL validation globally disabled |

### 4 · Network Connectivity

Probes each required Percy / BrowserStack domain:

Expand All @@ -70,7 +118,18 @@ Failure modes are classified as:
* **ETIMEDOUT / ECONNRESET** → Firewall dropping packets; list CIDRs to whitelist
* **via proxy only** → Proxy required, suggests setting `HTTPS_PROXY`

### 3 · Proxy Detection
### 5 · SSL / TLS

| Scenario | Outcome |
|---|---|
| `NODE_TLS_REJECT_UNAUTHORIZED=0` is set | **Warning** – SSL verification is disabled globally |
| SSL certificate error connecting to percy.io | **Fail** – likely a MITM proxy/VPN; suggests remediation |
| SSL handshake succeeds | **Pass** |

When a certificate error is detected, the command prints actionable suggestions
(contact network admin, add proxy cert to trust store, set `NODE_EXTRA_CA_CERTS`).

### 6 · Proxy Detection

Detects proxy configuration from (in priority order):

Expand All @@ -83,7 +142,7 @@ Detects proxy configuration from (in priority order):
Each discovered proxy is validated by attempting connections to percy.io and
browserstack.com through it.

### 4 · PAC / WPAD Auto-Proxy Configuration
### 7 · PAC / WPAD Auto-Proxy Configuration

Detects PAC file URLs from:

Expand All @@ -103,12 +162,72 @@ using shims for all standard PAC helper functions. The result of
If a PAC file routes percy.io through a proxy the command surfaces the exact
`HTTPS_PROXY=…` export statement to add to your CI environment.

### 8 · Token Authentication

Validates the `PERCY_TOKEN` environment variable:

- **Presence**: Checks the token is set
- **Format**: Detects project type from token prefix (`web_`, `auto_`, `app_`, `ss_`, `vmw_`, `res_`) and suggests the correct CLI command
- **Authentication**: Makes a live API call to `percy.io/api/v1/tokens` to verify the token is valid (uses proxy if one was discovered in earlier checks)

Token values are **never** included in output — only the project type and pass/fail status.

| Category | Meaning |
|---|---|
| `token_missing` | `PERCY_TOKEN` is not set or is blank |
| `token_type_info` | Token prefix decoded — project type and suggested CLI command |
| `token_auth_pass` | Token authenticated successfully; role shown |
| `token_auth_fail` | Token rejected (HTTP 401 or 403) |
| `token_auth_unexpected_status` | Percy API returned an unexpected HTTP status |
| `token_auth_network_error` | Could not reach Percy API to validate token |
| `check_skipped` | Token validation skipped because percy.io is unreachable |

### 9 · Browser Network (Chrome CDP)

Launches headless Chrome to test end-to-end network connectivity through the browser process, including proxy and PAC resolution as Chrome would see it.

---

## Quick Mode

Use `--quick` to run only the essential checks (connectivity, SSL, and token auth) in ~4 seconds:

```sh
npx percy doctor --quick
```

This is useful for fast triage in CI pipelines or when you just want to verify your token and network are working.

---

## Auto-Doctor on Build Failure

Set `PERCY_AUTO_DOCTOR=true` to automatically run diagnostics when a Percy build fails:

```sh
export PERCY_AUTO_DOCTOR=true
npx percy exec -- your-test-command
```

When enabled, a build failure triggers a diagnostic run and prints actionable findings inline. This is opt-in and has no effect on successful builds.

---

## Example output

```
Percy Doctor — network readiness check
Percy Doctor — diagnostic check

── Configuration
ℹ Configuration file detected: /project/.percy.yml
✔ Config version: 2 (current)

── CI Environment
ℹ CI system detected: GitHub Actions
✔ Git is available for commit detection.

── Environment Variables
ℹ Percy environment variables set: PERCY_TOKEN, PERCY_PARALLEL_TOTAL

── SSL / TLS
✔ SSL handshake with percy.io succeeded (47ms).
Expand All @@ -124,30 +243,16 @@ If a PAC file routes percy.io through a proxy the command surfaces the exact
── PAC / Auto-Proxy Configuration
ℹ No PAC (Proxy Auto-Configuration) file detected.

✔ All 6 checks passed
```

---
── Token Authentication
ℹ Token detected (project type: web). Use `percy exec` to run snapshots.
✔ Token authentication successful.

## Configuration fix (`--fix`)
── Browser Network
✔ Chrome loaded percy.io successfully.

When the doctor detects an SSL certificate error it can automatically patch the
nearest Percy configuration file (`.percy.yml` / `.percy.yaml`):

```sh
percy doctor --fix
```

This appends the following snippet to your config:

```yaml
ssl:
rejectUnauthorized: false
✔ 8 passed · 0 warnings · 0 failures (4.2s)
```

> **Note**: disabling SSL verification is a security trade-off. Use it only
> when your network proxy performs SSL inspection and you trust the proxy's CA.

---

## License
Expand Down
13 changes: 5 additions & 8 deletions packages/cli-doctor/package.json
Comment thread
rishigupta1599 marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,7 @@
"main": "./dist/index.js",
"type": "module",
"exports": {
".": "./dist/index.js",
"./src/utils/http.js": "./src/utils/http.js",
"./src/utils/reporter.js": "./src/utils/reporter.js",
"./src/utils/helpers.js": "./src/utils/helpers.js",
"./src/checks/connectivity.js": "./src/checks/connectivity.js",
"./src/checks/proxy.js": "./src/checks/proxy.js",
"./src/checks/pac.js": "./src/checks/pac.js",
"./src/checks/browser.js": "./src/checks/browser.js"
".": "./dist/index.js"
},
"scripts": {
"build": "node ../../scripts/build",
Expand All @@ -43,8 +36,12 @@
},
"dependencies": {
"@percy/cli-command": "1.31.10-beta.2",
"@percy/client": "1.31.10-beta.2",
"@percy/config": "1.31.10-beta.1",
"@percy/core": "1.31.10-beta.2",
"@percy/env": "1.31.10-beta.1",
"@percy/logger": "1.31.10-beta.2",
"@percy/monitoring": "1.31.10-beta.2",
"minimatch": "^9.0.0",
"ws": "^8.17.1"
}
Expand Down
Loading
Loading