Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dev-packages/cloudflare-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
"openai": "5.18.1"
},
"devDependencies": {
"@cloudflare/vite-plugin": "1.34.0",
"@cloudflare/workers-types": "^4.20260426.0",
"@sentry-internal/test-utils": "10.67.0",
"@sentry/conventions": "0.16.0",
"eslint-plugin-regexp": "^3.1.0",
"prisma": "6.15.0",
"vite": "7.3.2",
"vitest": "^3.2.6",
"wrangler": "4.86.0"
},
Expand Down
62 changes: 58 additions & 4 deletions dev-packages/cloudflare-integration-tests/runner.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Envelope, EnvelopeItemType } from '@sentry/core';
import { normalize } from '@sentry/core';
import { createBasicSentryServer } from '@sentry-internal/test-utils';
import { spawn } from 'child_process';
import { existsSync } from 'fs';
import { spawn, spawnSync } from 'child_process';
import { existsSync, readdirSync, readFileSync } from 'fs';
import { join } from 'path';
import { inspect } from 'util';
import { expect } from 'vitest';
Expand All @@ -18,6 +18,60 @@ export function cleanupChildProcesses(): void {

process.on('exit', cleanupChildProcesses);

/**
* Resolve the wrangler config `wrangler dev` should serve for a worker.
*
* Most suites run straight from source (`wrangler dev --config <name>.jsonc`).
* A suite that opts into the Sentry Vite plugin instead ships a `vite.config.*`
* (and no top-level `main` in its wrangler config): for those we run `vite build`
* first — so the plugin's build-time auto-instrumentation transform runs — and
* point wrangler at the generated config under `dist/<worker>/wrangler.json`.
*
* `wranglerConfigName` selects which source config the Vite build corresponds to
* (`wrangler.jsonc` for the main worker, `wrangler-sub-worker.jsonc` for a sub),
* so a Vite suite's generated output is matched to the right worker.
*/
function resolveWorkerConfig(testPath: string, wranglerConfigName: string): string {
const sourceConfig = join(testPath, wranglerConfigName);
const viteConfig = ['vite.config.ts', 'vite.config.mts', 'vite.config.js', 'vite.config.mjs']
.map(name => join(testPath, name))
.find(existsSync);

// No Vite config → serve the source wrangler config unchanged (existing path).
if (!viteConfig) {
return sourceConfig;
}

const result = spawnSync('vite', ['build'], { cwd: testPath, stdio: process.env.DEBUG ? 'inherit' : 'ignore' });
if (result.status !== 0) {
throw new Error(`vite build failed for ${testPath} (exit code ${result.status})`);
}

// `@cloudflare/vite-plugin` emits one directory per worker under `dist/`, each
// containing a resolved `wrangler.json`. Match the one whose original config is
// this worker's source config so multi-worker suites map correctly.
const distDir = join(testPath, 'dist');
const builtConfig = readdirSync(distDir, { withFileTypes: true })
.filter(entry => entry.isDirectory())
.map(entry => join(distDir, entry.name, 'wrangler.json'))
.find(configPath => existsSync(configPath) && builtFromSource(configPath, sourceConfig));

if (!builtConfig) {
throw new Error(`Could not locate a Vite-built wrangler config for ${sourceConfig} under ${distDir}`);
}
return builtConfig;
}

/** Whether a generated `wrangler.json` was built from the given source config. */
function builtFromSource(builtConfigPath: string, sourceConfigPath: string): boolean {
try {
const built = JSON.parse(readFileSync(builtConfigPath, 'utf8')) as { userConfigPath?: string; configPath?: string };
return built.userConfigPath === sourceConfigPath || built.configPath === sourceConfigPath;
} catch {
return false;
}
}
Comment on lines +66 to +73

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.

Bug: The strict path comparison in builtFromSource() will likely fail because path.join() creates an OS-specific absolute path, while the Vite plugin may generate a relative or differently formatted path string.
Severity: MEDIUM

Suggested Fix

Before comparing the paths in builtFromSource(), normalize them. Convert both built.userConfigPath and sourceConfigPath to a consistent format, such as absolute paths with normalized separators, using functions from the path module.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: dev-packages/cloudflare-integration-tests/runner.ts#L66-L73

Potential issue: The `builtFromSource()` function compares a generated config path
(`built.userConfigPath`) with a locally constructed path (`sourceConfigPath`) using
strict string equality (`===`). The `sourceConfigPath` is an absolute path created with
`path.join()`, which uses OS-native separators. The `userConfigPath`, generated by the
`@cloudflare/vite-plugin`, is likely to be a relative path or use a different separator
format (e.g., forward slashes). This mismatch will cause the comparison to fail,
preventing Vite-built test suites from being located and throwing an error. This issue
is particularly likely to manifest on Windows due to path separator differences.

Did we get this right? 👍 / 👎 to inform future reviews.


// 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.
// The budget (maxRetries * retryDelayMs) must cover the "ready-but-not-serving" window, which can be
Expand Down Expand Up @@ -299,7 +353,7 @@ export function createRunner(...paths: string[]) {
[
'dev',
'--config',
join(testPath, 'wrangler-sub-worker.jsonc'),
resolveWorkerConfig(testPath, 'wrangler-sub-worker.jsonc'),
'--show-interactive-dev-session',
'false',
'--var',
Expand All @@ -325,7 +379,7 @@ export function createRunner(...paths: string[]) {
[
'dev',
'--config',
join(testPath, 'wrangler.jsonc'),
resolveWorkerConfig(testPath, 'wrangler.jsonc'),
'--show-interactive-dev-session',
'false',
'--var',
Expand Down
Loading
Loading