Skip to content

feat(cli): honor HTTPS_PROXY/HTTP_PROXY/NO_PROXY behind corporate and CI proxies#169

Merged
zeshi-du merged 3 commits into
TestSprite:mainfrom
Andy00L:feat/proxy
Jul 5, 2026
Merged

feat(cli): honor HTTPS_PROXY/HTTP_PROXY/NO_PROXY behind corporate and CI proxies#169
zeshi-du merged 3 commits into
TestSprite:mainfrom
Andy00L:feat/proxy

Conversation

@Andy00L

@Andy00L Andy00L commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Node's built-in fetch (undici) ignores the proxy environment variables, so
behind a corporate or CI proxy every TestSprite request dies with fetch failed
after a full retry cycle. This installs undici's EnvHttpProxyAgent as the
global dispatcher at startup only when a proxy variable is present, honoring
HTTPS_PROXY/HTTP_PROXY (upper and lower case) and NO_PROXY exemptions. No
proxy var set → no-op, default path byte-identical, zero startup cost.

Related issue

Fixes #119

Type of change

  • New feature (non-breaking change that adds functionality)

Checklist

  • PR targets the main branch.
  • Commits follow Conventional Commits.
  • npm run lint and npm run format:check pass.
  • npm run typecheck passes.
  • npm test passes and coverage stays at or above the 80% gate.
  • New behavior is covered by unit tests (mock-based; no network).
  • No secrets, API keys, internal endpoints, or personal data are included.

Notes for reviewers

Adds undici as an explicit runtime dependency (the same engine Node already
bundles for fetch) — per the triage note on #119 approving this. The installer
is dependency-injected (ProxyDeps.install) so the unit tests never touch the
global dispatcher. EnvHttpProxyAgent reads NO_PROXY itself per request, so
exemptions work with no extra plumbing. I'm the assignee of #119.

Summary by CodeRabbit

  • New Features
    • Added automatic proxy support for Node network requests by honoring HTTP_PROXY/HTTPS_PROXY (including uppercase and lowercase variants).
    • Proxy handling is enabled only when a non-empty proxy value is provided; otherwise it does nothing.
    • If proxy configuration is invalid, the app now warns and continues running.
  • Tests
    • Expanded coverage for proxy env handling, empty/missing values, NO_PROXY behavior, and installer failure/warning behavior.
  • Chores
    • Added the undici runtime dependency to support proxy-aware fetching.

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 948cdd1e-01ed-47d3-92ed-0d9c22301a8c

📥 Commits

Reviewing files that changed from the base of the PR and between 2a9fad7 and 6120705.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json, !package-lock.json
📒 Files selected for processing (1)
  • package.json
✅ Files skipped from review due to trivial changes (1)
  • package.json

Walkthrough

This PR adds proxy environment handling at startup by introducing an undici-based dispatcher installer, wiring it into the CLI entrypoint, adding the runtime dependency, and expanding tests for proxy detection, NO_PROXY coexistence, and failure handling.

Changes

Proxy Agent Support

Layer / File(s) Summary
Proxy detection and installer implementation
src/lib/proxy.ts, package.json
Defines ProxyDeps with an optional stderr sink and implements maybeInstallProxyAgent() to detect proxy env vars across case variants, install EnvHttpProxyAgent through a configurable dispatcher installer, and add undici as a runtime dependency.
CLI startup wiring
src/index.ts
Imports maybeInstallProxyAgent() and invokes it during startup before command parsing.
Proxy behavior tests
src/lib/proxy.test.ts
Adds coverage for installation success, alternate env var spellings, empty and missing proxy values, install failure warnings, and NO_PROXY alongside HTTPS_PROXY.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is clear, specific, and matches the main proxy-support change.
Linked Issues check ✅ Passed The changes implement proxy-aware startup, undici integration, and NO_PROXY-focused tests as requested in #119.
Out of Scope Changes check ✅ Passed Only proxy support, dependency pinning, and tests were added; no unrelated changes are evident.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@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

🧹 Nitpick comments (1)
src/lib/proxy.ts (1)

16-17: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Avoid EnvHttpProxyAgent on the CLI path for now. undici@8.5.0 still emits the [UNDICI-EHPA] experimental warning on proxy-enabled starts, which adds avoidable stderr noise.

🤖 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/lib/proxy.ts` around lines 16 - 17, Avoid using EnvHttpProxyAgent in the
CLI proxy setup because undici@8.5.0 still emits the [UNDICI-EHPA] warning on
proxy-enabled starts. Update src/lib/proxy.ts so the proxy initialization path
used by the CLI relies on setGlobalDispatcher without importing or constructing
EnvHttpProxyAgent, and keep the dispatcher logic in the proxy-related helper(s)
isolated so the warning is not triggered.
🤖 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/lib/proxy.test.ts`:
- Around line 1-34: The current proxy tests only cover proxy-variable detection
in maybeInstallProxyAgent and miss the required NO_PROXY coverage. Add a test
that exercises actual dispatcher installation and NO_PROXY bypass behavior by
constructing an EnvHttpProxyAgent (or invoking deps.install through
maybeInstallProxyAgent) with NO_PROXY set, then assert a matching host is routed
around the proxy while the proxy-install path still behaves as expected.

In `@src/lib/proxy.ts`:
- Around line 30-41: The proxy setup in maybeInstallProxyAgent should not let
malformed or unsupported proxy environment values abort startup; wrap the
EnvHttpProxyAgent installation in a try/catch and fall back to the default
dispatcher when it fails. Keep the existing proxy detection logic in
maybeInstallProxyAgent, but ensure the call to install(new EnvHttpProxyAgent())
is protected so bad HTTP_PROXY/HTTPS_PROXY values do not propagate out through
src/index.ts and stop CLI execution.

---

Nitpick comments:
In `@src/lib/proxy.ts`:
- Around line 16-17: Avoid using EnvHttpProxyAgent in the CLI proxy setup
because undici@8.5.0 still emits the [UNDICI-EHPA] warning on proxy-enabled
starts. Update src/lib/proxy.ts so the proxy initialization path used by the CLI
relies on setGlobalDispatcher without importing or constructing
EnvHttpProxyAgent, and keep the dispatcher logic in the proxy-related helper(s)
isolated so the warning is not triggered.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 54693c93-d286-4eb7-b932-7f090a38c504

📥 Commits

Reviewing files that changed from the base of the PR and between e53257d and 5d43a71.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json, !package-lock.json
📒 Files selected for processing (4)
  • package.json
  • src/index.ts
  • src/lib/proxy.test.ts
  • src/lib/proxy.ts

Comment thread src/lib/proxy.test.ts
Comment on lines +1 to +34
import { describe, expect, it, vi } from 'vitest';
import { maybeInstallProxyAgent } from './proxy.js';

describe('maybeInstallProxyAgent', () => {
it('installs an agent when HTTPS_PROXY is set', () => {
const install = vi.fn();
const installed = maybeInstallProxyAgent({
env: { HTTPS_PROXY: 'http://proxy.corp.example.com:8080' },
install,
});
expect(installed).toBe(true);
expect(install).toHaveBeenCalledTimes(1);
});

it.each(['https_proxy', 'HTTP_PROXY', 'http_proxy'] as const)(
'also honors the %s spelling',
name => {
const install = vi.fn();
const installed = maybeInstallProxyAgent({
env: { [name]: 'http://proxy.corp.example.com:8080' },
install,
});
expect(installed).toBe(true);
expect(install).toHaveBeenCalledTimes(1);
},
);

it('does nothing when no proxy variable is set (default path unchanged)', () => {
const install = vi.fn();
expect(maybeInstallProxyAgent({ env: {}, install })).toBe(false);
expect(maybeInstallProxyAgent({ env: { HTTPS_PROXY: '' }, install })).toBe(false);
expect(install).not.toHaveBeenCalled();
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Missing NO_PROXY test coverage per stated objective.

The linked issue's acceptance criteria call for tests verifying "dispatcher installation and NO_PROXY behavior," but this suite only covers proxy-var detection/no-op cases — no test exercises NO_PROXY exemptions. Since that logic lives inside EnvHttpProxyAgent itself, a meaningful test would need to construct a real agent with NO_PROXY set and assert it bypasses the proxy for a matching host, rather than only checking maybeInstallProxyAgent's boolean return.

Want me to draft a test that constructs EnvHttpProxyAgent directly (or via deps.install) and asserts requests to a NO_PROXY-listed host bypass the proxy dispatch?

🤖 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/lib/proxy.test.ts` around lines 1 - 34, The current proxy tests only
cover proxy-variable detection in maybeInstallProxyAgent and miss the required
NO_PROXY coverage. Add a test that exercises actual dispatcher installation and
NO_PROXY bypass behavior by constructing an EnvHttpProxyAgent (or invoking
deps.install through maybeInstallProxyAgent) with NO_PROXY set, then assert a
matching host is routed around the proxy while the proxy-install path still
behaves as expected.

Comment thread src/lib/proxy.ts
@Andy00L

Andy00L commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Andy00L

Andy00L commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@zeshi-du

zeshi-du commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Direction approved — an explicit undici dependency was green-lit for exactly this use (issue #119), and EnvHttpProxyAgent at startup + graceful fallback on a malformed proxy value is the right shape.

One blocker: undici@8.6.0 requires Node >=22.19.0, but this package supports ^20.19.0 || ^22.13.0 || >=24 — and the committed .npmrc sets engine-strict=true, so npm ci on the Node 20 CI job will refuse the lockfile. Please pin undici@^7 (EnvHttpProxyAgent is available there and v7 supports Node 20) and regenerate package-lock.json. Green Node 20+22 matrix after that → merge.

@Andy00L

Andy00L commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for running CI — fixed the Node 20 failure. The npm ci step failed under engine-strict because undici 8.x (including 8.5.0) requires node >=22.19.0, but the project supports Node 20 (^20.19.0 || ^22.13.0 || >=24). Pinned undici to ^7.16.0 (resolves to 7.28.0, engines: node >=20.18.1), compatible with the whole supported range and exposing the same EnvHttpProxyAgent / setGlobalDispatcher API — no code change. Full gate (typecheck, lint, tests, build) green locally.

@zeshi-du zeshi-du merged commit 768da46 into TestSprite:main Jul 5, 2026
9 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.

[Hackathon] Honor HTTPS_PROXY / HTTP_PROXY / NO_PROXY for corporate and CI networks

2 participants