mirror of
https://github.com/saltbo/zpan.git
synced 2026-08-29 00:01:42 +08:00
fix(ci): isolate quick tunnel callback traffic
This commit is contained in:
@@ -10,6 +10,17 @@ export class CloudE2eCommandError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
export function cloudE2eEndpoints(localBaseUrl, tunnelUrl) {
|
||||
return {
|
||||
browserBaseUrl: localBaseUrl,
|
||||
publicBaseUrl: tunnelUrl ?? localBaseUrl,
|
||||
}
|
||||
}
|
||||
|
||||
export function cloudflaredQuickTunnelArgs(target) {
|
||||
return ['tunnel', '--url', target, '--protocol', 'http2', '--no-autoupdate']
|
||||
}
|
||||
|
||||
export function isRetryableQuickTunnelFailure({ commandOutput, tunnelOutput }) {
|
||||
if (QUICK_TUNNEL_502.test(commandOutput)) return true
|
||||
return (
|
||||
|
||||
@@ -2,6 +2,8 @@ import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
CloudE2eCommandError,
|
||||
cloudE2eAttemptCount,
|
||||
cloudE2eEndpoints,
|
||||
cloudflaredQuickTunnelArgs,
|
||||
isRetryableQuickTunnelFailure,
|
||||
} from './cloud-e2e-resilience.mjs'
|
||||
|
||||
@@ -15,6 +17,28 @@ describe('cloud E2E resilience', () => {
|
||||
expect(error.output).toBe('gateway response')
|
||||
})
|
||||
|
||||
it('keeps browser traffic local and reserves the tunnel for public callbacks', () => {
|
||||
expect(cloudE2eEndpoints('http://localhost:5185', 'https://callback.trycloudflare.com')).toEqual({
|
||||
browserBaseUrl: 'http://localhost:5185',
|
||||
publicBaseUrl: 'https://callback.trycloudflare.com',
|
||||
})
|
||||
expect(cloudE2eEndpoints('http://localhost:5185', null)).toEqual({
|
||||
browserBaseUrl: 'http://localhost:5185',
|
||||
publicBaseUrl: 'http://localhost:5185',
|
||||
})
|
||||
})
|
||||
|
||||
it('uses HTTP/2 instead of QUIC for the Quick Tunnel transport', () => {
|
||||
expect(cloudflaredQuickTunnelArgs('http://localhost:5185')).toEqual([
|
||||
'tunnel',
|
||||
'--url',
|
||||
'http://localhost:5185',
|
||||
'--protocol',
|
||||
'http2',
|
||||
'--no-autoupdate',
|
||||
])
|
||||
})
|
||||
|
||||
it('retries a Cloudflare Quick Tunnel gateway page', () => {
|
||||
expect(
|
||||
isRetryableQuickTunnelFailure({
|
||||
|
||||
@@ -5,6 +5,8 @@ import { createRequire } from 'node:module'
|
||||
import {
|
||||
CloudE2eCommandError,
|
||||
cloudE2eAttemptCount,
|
||||
cloudE2eEndpoints,
|
||||
cloudflaredQuickTunnelArgs,
|
||||
isRetryableQuickTunnelFailure,
|
||||
} from './cloud-e2e-resilience.mjs'
|
||||
|
||||
@@ -71,17 +73,17 @@ for (let attempt = 1; attempt <= maxRunAttempts; attempt += 1) {
|
||||
|
||||
async function buildE2eEnv(tunnel) {
|
||||
const tunnelHost = tunnel ? new URL(tunnel.url).hostname : ''
|
||||
const tunnelIp = tunnel ? await waitForPublicTunnelIp(tunnelHost) : ''
|
||||
const baseUrl = tunnel?.url ?? localBaseUrl
|
||||
if (tunnel) await waitForPublicTunnelIp(tunnelHost)
|
||||
const { browserBaseUrl, publicBaseUrl } = cloudE2eEndpoints(localBaseUrl, tunnel?.url)
|
||||
return {
|
||||
...cloudEnv,
|
||||
E2E_BASE_URL: baseUrl,
|
||||
E2E_BASE_URL: browserBaseUrl,
|
||||
E2E_LOCAL_BASE_URL: localBaseUrl,
|
||||
E2E_PUBLIC_BASE_URL: publicBaseUrl,
|
||||
E2E_APP_PORT: String(appPort),
|
||||
E2E_API_PORT: String(apiPort),
|
||||
BETTER_AUTH_URL: baseUrl,
|
||||
TRUSTED_ORIGINS: `${baseUrl},${localBaseUrl}`,
|
||||
...(tunnel ? { E2E_CHROME_HOST_RESOLVER_RULES: `MAP ${tunnelHost} ${tunnelIp}` } : {}),
|
||||
BETTER_AUTH_URL: publicBaseUrl,
|
||||
TRUSTED_ORIGINS: `${publicBaseUrl},${localBaseUrl}`,
|
||||
...s3MockEnv(),
|
||||
...credentialsEnv,
|
||||
...(runtime === 'cf' ? { E2E_RUNTIME: 'cf' } : {}),
|
||||
@@ -145,7 +147,7 @@ async function startTunnel(target) {
|
||||
}
|
||||
|
||||
function startTunnelOnce(target) {
|
||||
const child = spawn(cloudflared, ['tunnel', '--url', target, '--no-autoupdate'], {
|
||||
const child = spawn(cloudflared, cloudflaredQuickTunnelArgs(target), {
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
})
|
||||
writeFileSync(pidFile, String(child.pid))
|
||||
|
||||
Reference in New Issue
Block a user