Skip to content
Merged
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.5",
"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' });
Comment thread
sentry[bot] marked this conversation as resolved.
if (result.status !== 0) {
throw new Error(`vite build failed for ${testPath} (exit code ${result.status})`);
Comment on lines +45 to +47

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 resolveWorkerConfig function may run vite build twice for the same test path if a sub-worker config exists, as the build result is not cached.
Severity: LOW

Suggested Fix

Cache or memoize the result of the vite build execution per testPath. This can be done using a module-level Map to store whether a build has already been completed for a given path, preventing the spawnSync('vite', ['build'], ...) call from running a second time.

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#L45-L47

Potential issue: The `start` function in `runner.ts` can call `resolveWorkerConfig`
twice for the same test path: once for a sub-worker (if `wrangler-sub-worker.jsonc`
exists) and again for the main worker. The `resolveWorkerConfig` function runs `vite
build` if a `vite.config.*` file is found. Because the build result is not cached or
memoized, this can lead to `vite build` being executed twice for the same test suite.
While no current test suite triggers this condition, it represents a latent inefficiency
that could be triggered by future test suites that use both a sub-worker and a local
vite configuration, causing wasteful resource usage.

Also affects:

  • dev-packages/cloudflare-integration-tests/runner.ts:356~356
  • dev-packages/cloudflare-integration-tests/runner.ts:382~382

}

// `@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 })
Comment thread
sentry[bot] marked this conversation as resolved.
.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;
Comment thread
andreiborza marked this conversation as resolved.
}

/** 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;
Comment thread
sentry[bot] marked this conversation as resolved.
} catch {
return false;
}
}
Comment thread
andreiborza marked this conversation as resolved.

// 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'),
Comment thread
andreiborza marked this conversation as resolved.
'--show-interactive-dev-session',
'false',
'--var',
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@
"**/nx/minimatch": "10.2.5",
"**/ng-packagr/postcss-url/minimatch": "3.1.5",
"**/@angular-devkit/build-angular/minimatch": "5.1.9",
"**/nitropack/rollup-plugin-visualizer": "^6.0.3"
"**/nitropack/rollup-plugin-visualizer": "^6.0.3",
"vite": "^6.4.3"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Vite 7 pin forced to 6

Medium Severity

cloudflare-integration-tests pins vite to 7.3.5, but the root Yarn resolutions entry forces every vite request—including that pin—to ^6.4.3. The lockfile already shows vite@7.3.5 resolving to 6.4.3, so the intended Vite 7 install never lands.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3071610. Configure here.

},
"version": "0.0.0",
"name": "sentry-javascript"
Expand Down
Loading
Loading