Skip to content

Fix cli-proxy TCP tunnel localhost binding on IPv6-enabled runners#4626

Merged
lpcox merged 3 commits into
mainfrom
copilot/fix-cli-proxy-tcp-tunnel-ipv6
Jun 9, 2026
Merged

Fix cli-proxy TCP tunnel localhost binding on IPv6-enabled runners#4626
lpcox merged 3 commits into
mainfrom
copilot/fix-cli-proxy-tcp-tunnel-ipv6

Conversation

Copilot AI commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

cli-proxy’s TCP tunnel only listened on 127.0.0.1, while gh may resolve localhost to ::1 first. On IPv6-enabled runners this caused liveness probe failures (connect: connection refused) during sidecar startup.

  • Tunnel binding behavior

    • Updated containers/cli-proxy/tcp-tunnel.js to start listeners on both loopback addresses:
      • 127.0.0.1
      • ::1
    • Kept error handling explicit per bind target; IPv6 loopback unavailability is handled without breaking IPv4 startup.
  • Regression coverage

    • Added scripts/ci/tcp-tunnel.test.ts to verify the tunnel accepts connections on both IPv4 and IPv6 loopback when IPv6 loopback is available.
const bindHosts = ['127.0.0.1', '::1'];

for (const bindHost of bindHosts) {
  const server = net.createServer(handleConnection);
  server.listen(localPort, bindHost, () => {
    console.log(`[tcp-tunnel] Forwarding localhost:${localPort}${remoteHost}:${remotePort}`);
  });
}

Copilot AI changed the title [WIP] Fix cli-proxy TCP tunnel to support IPv6 binding Fix cli-proxy TCP tunnel localhost binding on IPv6-enabled runners Jun 9, 2026
Copilot finished work on behalf of lpcox June 9, 2026 21:11
Copilot AI requested a review from lpcox June 9, 2026 21:11
@lpcox lpcox marked this pull request as ready for review June 9, 2026 21:50
Copilot AI review requested due to automatic review settings June 9, 2026 21:50
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

✅ Coverage Check Passed

Overall Coverage

Metric Base PR Delta
Lines 96.43% 96.47% 📈 +0.04%
Statements 96.35% 96.39% 📈 +0.04%
Functions 98.76% 98.76% ➡️ +0.00%
Branches 90.72% 90.75% 📈 +0.03%
📁 Per-file Coverage Changes (1 files)
File Lines (Before → After) Statements (Before → After)
src/config-writer.ts 89.3% → 90.9% (+1.65%) 89.3% → 90.9% (+1.65%)

Coverage comparison generated by scripts/ci/compare-coverage.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 fixes cli-proxy’s TCP tunnel loopback binding behavior on IPv6-enabled runners by ensuring the tunnel listens on both IPv4 and IPv6 loopback addresses, preventing failures when localhost resolves to ::1 first.

Changes:

  • Update containers/cli-proxy/tcp-tunnel.js to bind the listener on both 127.0.0.1 and ::1, while tolerating missing IPv6 loopback.
  • Add a Jest regression test to validate the tunnel accepts connections via both IPv4 and IPv6 loopback when IPv6 is available.
Show a summary per file
File Description
containers/cli-proxy/tcp-tunnel.js Bind TCP tunnel on both IPv4 and IPv6 loopback with explicit per-bind error handling.
scripts/ci/tcp-tunnel.test.ts Add regression test covering IPv4/IPv6 loopback connectivity to the tunnel.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 3

Comment on lines +41 to +45
const bindHosts = ['127.0.0.1', '::1'];
let startedServers = 0;
let readyLogged = false;
const servers = [];

Comment on lines +135 to +141
} finally {
tunnel.kill('SIGTERM');
await new Promise((resolve) => upstream.server.close(() => resolve(undefined)));
}

expect(tunnel.exitCode).not.toBe(1);
}, 10000);
Comment thread scripts/ci/tcp-tunnel.test.ts Outdated
Comment on lines +104 to +108
async function connectWithRetry(host: string, port: number, attempts = 20): Promise<void> {
let lastError: unknown;
for (let i = 0; i < attempts; i += 1) {
try {
await connect(host, port);
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@lpcox

lpcox commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

@copilot address review feedback

@github-actions

This comment has been minimized.

Copilot AI commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address review feedback

Done in a68ec25. Changes made:

  • tcp-tunnel.js: Removed the unused servers array.
  • tcp-tunnel.test.ts:
    • Reduced connectWithRetry default attempts from 20 → 5 (worst case ~5.25s, well within the 10s timeout).
    • finally now awaits both tunnel.once('exit', resolve) and upstream.server.close(...) in parallel, ensuring the child process is fully reaped before the test ends.
    • Dropped the expect(tunnel.exitCode).not.toBe(1) assertion (exit code is null for signal-terminated processes).
    • Also fixed a pre-existing ECONNRESET failure: the mock upstream server in createTcpServer was missing a socket error handler, so when the tunnel tore down the upstream connection the unhandled ECONNRESET caused the test to fail before even reaching the assertions.

@@ -0,0 +1,144 @@
import { describe, expect, it } from '@jest/globals';
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Smoke Test Results: Copilot BYOK (Direct) Mode

✅ GitHub MCP connectivity — Last 2 merged PRs fetched
✅ GitHub.com connectivity — HTTP 200
✅ File write/read test — smoke-test-copilot-byok.txt present
✅ BYOK inference — Direct mode active (COPILOT_PROVIDER_API_KEY)

Status: PASS — Running in direct BYOK mode via api-proxy → api.githubcopilot.com

🔑 BYOK report filed by Smoke Copilot BYOK

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🔬 Smoke Test Results

Test Result
GitHub MCP connectivity
GitHub.com HTTP connectivity ❌ (pre-step data not substituted)
File write/read ❌ (pre-step data not substituted)

Overall: FAIL

PR: Fix cli-proxy TCP tunnel localhost binding on IPv6-enabled runners
Author: @Copilot — Assignees: @lpcox, @Copilot

⚠️ Workflow template variables (steps.smoke-data.outputs.*) were not substituted — tests 2 & 3 could not be verified.

📰 BREAKING: Report filed by Smoke Copilot

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Smoke test results:

  • Hard cap ai credits and integration ✅
  • Bundle models.dev catalog for AI credits model resolution ✅
  • GitHub reads via browser fallback ✅
  • npm ci && npm run build ❌ (node missing)
  • Overall: FAIL

🔮 The oracle has spoken through Smoke Codex

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.13 Python 3.12.3
Node.js v24.16.0 v22.22.3
Go go1.22.12 go1.22.12

Overall: ❌ Not all tests passed — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

@Copilot @lpcox

Smoke test results:

  • Hard cap ai credits and integration: ✅
  • GitHub.com connectivity: ✅
  • File write/read test: ❌
  • Direct BYOK inference mode: ✅

Running in direct BYOK mode (AWF_AUTH_TYPE=github-oidc + AWF_AUTH_AZURE_* + COPILOT_PROVIDER_BASE_URL) via api-proxy → Azure OpenAI (Foundry, o4-mini-aw) authenticated via Microsoft Entra

Overall status: FAIL

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • api.openai.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "api.openai.com"

See Network Configuration for more information.

🪪 BYOK (AOAI Entra) report filed by Smoke Copilot BYOK AOAI (Entra)

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🏗️ Build Test Suite Results

Ecosystem Project Build/Install Tests Status
Bun elysia 1/1 passed ✅ PASS
Bun hono 1/1 passed ✅ PASS
C++ fmt N/A ✅ PASS
C++ json N/A ✅ PASS
Deno oak N/A 1/1 passed ✅ PASS
Deno std N/A 1/1 passed ✅ PASS
.NET hello-world N/A ✅ PASS
.NET json-parse N/A ✅ PASS
Go color 1/1 passed ✅ PASS
Go env 1/1 passed ✅ PASS
Go uuid 1/1 passed ✅ PASS
Java gson 1/1 passed ✅ PASS
Java caffeine 1/1 passed ✅ PASS
Node.js clsx all passed ✅ PASS
Node.js execa all passed ✅ PASS
Node.js p-limit all passed ✅ PASS
Rust fd 1/1 passed ✅ PASS
Rust zoxide 1/1 passed ✅ PASS

Overall: 8/8 ecosystems passed — ✅ PASS

Generated by Build Test Suite for issue #4626 · 428.9 AIC · ⊞ 35.5K ·

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Smoke Test: GitHub Actions Services Connectivity

Check Result
Redis PING ❌ Connection timeout (port 6379)
PostgreSQL pg_isready ❌ No response (port 5432)
PostgreSQL SELECT 1 ❌ Not attempted

host.docker.internal resolves to 172.17.0.1 but both ports timed out — service containers appear unreachable from this runner.

Overall: FAIL

🔌 Service connectivity validated by Smoke Services

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

GitHub API: ✅ PASS
GitHub check: ✅ PASS
File verify: ✅ PASS

Total: PASS

💥 [THE END] — Illustrated by Smoke Claude

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cli-proxy TCP tunnel binds IPv4 only — fails on runners with IPv6 enabled

4 participants