Skip to content

Add offline GitHub proxy for E2E tests#1199

Merged
stephentoub merged 9 commits into
mainfrom
stephentoub/offline-e2e-proxy
May 5, 2026
Merged

Add offline GitHub proxy for E2E tests#1199
stephentoub merged 9 commits into
mainfrom
stephentoub/offline-e2e-proxy

Conversation

@stephentoub
Copy link
Copy Markdown
Collaborator

@stephentoub stephentoub commented May 4, 2026

E2E replay previously only covered CAPI traffic, so CLI subprocesses could still contact GitHub services directly during SDK tests. This adds a shared CONNECT proxy to the E2E harness so GitHub, GitHub API, and MCP registry traffic is intercepted locally while CAPI traffic continues to flow through the existing replay proxy.

The shared TypeScript harness now generates an ephemeral CA, starts a CONNECT/MITM proxy, mocks github.com, api.github.com, and api.mcp.github.com, and blocks unexpected outbound CONNECT targets. The Node, Python, Go, and .NET E2E wrappers parse the shared proxy metadata and inject proxy/CA/isolation environment variables into CLI subprocesses, including isolated GH_CONFIG_DIR and fake CI auth tokens for tests that start additional CLI server processes.

Generated by Copilot.

Copilot AI review requested due to automatic review settings May 4, 2026 20:52
@stephentoub stephentoub requested a review from a team as a code owner May 4, 2026 20:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR strengthens cross-SDK E2E isolation by adding a shared local CONNECT/MITM proxy to the test harness, so CLI subprocesses can’t reach GitHub services directly while CAPI traffic continues to be replayed via the existing proxy.

Changes:

  • Add a shared CONNECT/MITM proxy with an ephemeral CA and domain allow/block controls.
  • Mock github.com, api.github.com, and api.mcp.github.com, while forwarding api.githubcopilot.com to the replaying CAPI proxy.
  • Update Node/Python/Go/.NET E2E harness wrappers to parse startup metadata and inject proxy/CA + isolated GitHub CLI config/token env vars.
Show a summary per file
File Description
test/harness/util.ts Removes SDK type dependency by inlining the shell tool-name shape used by the harness.
test/harness/server.ts Boots CONNECT proxy + mocks, tracks blocked/unhandled network activity, and prints startup metadata for wrappers.
test/harness/replayingCapiProxy.ts Adds stop hook for coordinated shutdown and improves header/tool-output normalization for new proxy scenarios.
test/harness/replayingCapiProxy.test.ts Adds regression coverage for new GitHub CLI auth/proxy failure normalization.
test/harness/package.json Adds certificate-generation deps (node-forge + types) for the MITM CA/certs.
test/harness/package-lock.json Locks new deps required by the MITM proxy.
test/harness/mockHandlers.ts Implements mock routing/forwarding for GitHub/GitHub API/MCP registry and forwards CAPI to the replay proxy.
test/harness/connectProxy.ts Implements the CONNECT proxy, TLS MITM, domain allow/block, and socket lifecycle handling.
test/harness/connectProxy.test.ts Adds unit coverage for CONNECT parsing, interception, blocking, and mock behavior.
test/harness/certUtils.ts Generates an ephemeral CA and per-host certs for TLS interception.
python/e2e/testharness/proxy.py Parses proxy startup metadata and provides env vars to route subprocess HTTPS via the CONNECT proxy.
python/e2e/testharness/context.py Injects proxy env + isolates GH config dir and uses fake tokens in CI.
nodejs/test/e2e/harness/sdkTestContext.ts Injects CONNECT proxy env into Node E2E subprocess environment and isolates GH config dir.
nodejs/test/e2e/harness/CapiProxy.ts Parses harness startup metadata and exposes CONNECT proxy env vars to tests/subprocesses.
go/internal/e2e/testharness/proxy.go Parses startup metadata and provides a CONNECT-proxy environment block for subprocesses.
go/internal/e2e/testharness/context.go Injects CONNECT-proxy env + isolates GH config dir and uses fake tokens in CI.
dotnet/test/Harness/E2ETestContext.cs Injects CONNECT proxy env + isolates GH config dir and uses fake tokens in CI.
dotnet/test/Harness/CapiProxy.cs Parses startup metadata into strongly-typed fields via source-generated JSON context.

Copilot's findings

Files not reviewed (1)
  • test/harness/package-lock.json: Language not supported
  • Files reviewed: 17/18 changed files
  • Comments generated: 4

Comment thread nodejs/test/e2e/harness/CapiProxy.ts
Comment thread nodejs/test/e2e/harness/CapiProxy.ts
Comment thread test/harness/package.json
Comment thread dotnet/test/Harness/CapiProxy.cs Outdated
@github-actions

This comment has been minimized.

Comment thread test/harness/replayingCapiProxy.ts Fixed
@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Generated by SDK Consistency Review Agent for issue #1199 · ● 549.6K

Comment thread python/e2e/testharness/proxy.py
@github-actions

This comment has been minimized.

stephentoub and others added 4 commits May 4, 2026 18:11
Route SDK E2E test subprocess traffic through a shared CONNECT proxy so GitHub and MCP requests are handled locally while CAPI traffic continues to use replay snapshots. Wire the proxy metadata into the Node, Python, Go, and .NET harnesses and add coverage for the proxy and GitHub CLI auth normalization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@stephentoub stephentoub force-pushed the stephentoub/offline-e2e-proxy branch from a2b4303 to c3c50a4 Compare May 4, 2026 22:11
@github-actions

This comment has been minimized.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

Cross-SDK Consistency Review ✅

This PR adds the offline CONNECT proxy to the E2E harness across all four SDK implementations. The changes are well-implemented and consistent across Node.js, Python, Go, and .NET.

Summary of changes per SDK

All four harness wrappers implement the same behaviour:

Feature Node.js Python Go .NET
Parse URL + JSON metadata from startup line
Fail if Listening: line is missing metadata
Inject HTTP_PROXY / HTTPS_PROXY + lowercase variants
Inject NO_PROXY / no_proxy
Inject NODE_EXTRA_CA_CERTS, SSL_CERT_FILE, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE, GIT_SSL_CAINFO
Clear GH_TOKEN / GITHUB_TOKEN / GH_ENTERPRISE_TOKEN / GITHUB_ENTERPRISE_TOKEN via proxy env
Set GH_CONFIG_DIR to isolated home dir
Set fake CI tokens when GITHUB_ACTIONS=true
Skip npm/npx wrapper output before startup line

Minor implementation note (no action needed)

Python's startup parsing uses two separate regexes (one for the URL, one for the JSON metadata at end of line) instead of a single combined regex pattern used by the other three SDKs. This is functionally equivalent — Python correctly fails if metadata is absent, validates the JSON, and checks for empty connectProxyUrl/caFilePath. It's just a slightly different implementation style.

Generated by SDK Consistency Review Agent for issue #1199 · ● 377.1K ·

Copy link
Copy Markdown
Member

@devm33 devm33 left a comment

Choose a reason for hiding this comment

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

Awesome thanks!

@stephentoub stephentoub added this pull request to the merge queue May 5, 2026
Merged via the queue into main with commit c9433c4 May 5, 2026
37 of 38 checks passed
@stephentoub stephentoub deleted the stephentoub/offline-e2e-proxy branch May 5, 2026 15:25
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.

4 participants