From 12a04f1894f3d82d779c87f6078db25be6fc5c4b Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 8 Jul 2026 13:36:08 +0200 Subject: [PATCH] test(cloudflare): Add headroom for wrangler cold-start in integration tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Cloudflare integration tests flake on CI. Each test spawns its own `wrangler dev` (cold workerd boot), makes a request, and waits for envelopes to be delivered to the mock server. The runner has no internal timeout, so it relies entirely on Vitest's `testTimeout`; and `fetchWithRetry` only tolerates a ~2s "ready-but-not-serving" window. Both are tight given how slow and variable wrangler cold-start is on a loaded CI runner (locally these tests finish in <5s, but CI cold-start can stall for much longer). - Raise `testTimeout` from 30s to 60s. - Raise the `fetchWithRetry` budget from 10 to 25 attempts (~2s -> ~5s) to cover a longer ready-but-not-serving window. Both are pure ceilings with no happy-path cost — tests still complete as soon as the worker serves and envelopes arrive. Co-Authored-By: Claude Opus 4.8 (1M context) --- dev-packages/cloudflare-integration-tests/runner.ts | 4 +++- dev-packages/cloudflare-integration-tests/vite.config.mts | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/dev-packages/cloudflare-integration-tests/runner.ts b/dev-packages/cloudflare-integration-tests/runner.ts index 1b19e9e15efd..09bf18392609 100644 --- a/dev-packages/cloudflare-integration-tests/runner.ts +++ b/dev-packages/cloudflare-integration-tests/runner.ts @@ -20,7 +20,9 @@ process.on('exit', cleanupChildProcesses); // Wrangler can report "Ready" before it can actually handle requests. // This retries fetch on connection errors and transient 500 responses to handle this race condition. -async function fetchWithRetry(url: string, init: RequestInit, maxRetries = 10, retryDelayMs = 200): Promise { +// The budget (maxRetries * retryDelayMs) must cover the "ready-but-not-serving" window, which can be +// several seconds on a loaded CI runner — hence a generous default. +async function fetchWithRetry(url: string, init: RequestInit, maxRetries = 25, retryDelayMs = 200): Promise { for (let attempt = 0; attempt < maxRetries; attempt++) { try { const res = await fetch(url, init); diff --git a/dev-packages/cloudflare-integration-tests/vite.config.mts b/dev-packages/cloudflare-integration-tests/vite.config.mts index 10b3f319b762..a93b595b6ecd 100644 --- a/dev-packages/cloudflare-integration-tests/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/vite.config.mts @@ -10,7 +10,10 @@ export default defineConfig({ }, isolate: false, include: ['./suites/**/test.ts'], - testTimeout: 30_000, + // Each test spawns its own `wrangler dev` (cold workerd boot) and waits for envelopes to be + // delivered — there is no internal runner timeout, so this ceiling covers cold-start + async work + + // delivery. Cold-start is slow and highly variable on CI, so give it generous headroom to de-flake. + testTimeout: 60_000, // Ensure we can see debug output when DEBUG=true ...(process.env.DEBUG ? {