Skip to content
Draft
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
45 changes: 45 additions & 0 deletions dev-packages/e2e-tests/test-applications/node-esbuild/assert.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* Asserts that a plain esbuild build bundles the runtime diagnostics-channel injection by default,
* and that the Sentry esbuild plugin build (build-time instrumentation) succeeds.
*
* NOTE: unlike webpack/vite/rollup, esbuild's single-pass tree-shaking does NOT remove the runtime
* injection when `bundleSizeOptimizations.excludeChannelInjection` is defaulted on by the plugin: the
* `if (useChannelInjection)` branch goes dead (so it never runs at runtime), but esbuild keeps the
* module in the bundle. We therefore don't assert its absence here — we only assert the plugin build
* succeeds. The runtime-behavior side of this is covered by the node-vite-runtime-injection app.
*
* @module
*/
import { readdirSync, readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = dirname(fileURLToPath(import.meta.url));

const RUNTIME_INJECTION_MARKER = 'Registered diagnostics-channel injection';

function bundleText(name) {
const dir = join(__dirname, 'dist', name);
return readdirSync(dir)
.map(f => readFileSync(join(dir, f), 'utf8'))
.join('\n');
}

let failed = false;
function check(condition, message) {
// eslint-disable-next-line no-console
console.log(`${condition ? 'ok ' : 'FAIL'} - ${message}`);
if (!condition) failed = true;
}

const plain = bundleText('plain');
const plugin = bundleText('plugin');

check(plain.includes(RUNTIME_INJECTION_MARKER), 'plain build bundles the runtime channel injection by default');
check(plugin.length > 0, 'sentryEsbuildPlugin build (build-time instrumentation) succeeds');

if (failed) {
process.exit(1);
}
// eslint-disable-next-line no-console
console.log('All bundle assertions passed.');
41 changes: 41 additions & 0 deletions dev-packages/e2e-tests/test-applications/node-esbuild/build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Bundles the entrypoint with esbuild twice:
// - `plain`: no Sentry plugin — the runtime diagnostics-channel injection is bundled (v11 default).
// - `plugin`: with `sentryEsbuildPlugin` (build-time instrumentation).
// assert.mjs inspects both outputs. Note: unlike webpack/vite/rollup, esbuild's single-pass
// tree-shaking does not drop the (now dead) runtime injection code, so this app only asserts the
// plugin build succeeds — see assert.mjs.
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { build } from 'esbuild';
import { sentryEsbuildPlugin } from '@sentry/node/esbuild';

const __dirname = dirname(fileURLToPath(import.meta.url));

function run(name, plugins) {
return build({
entryPoints: [join(__dirname, 'src', 'entry.mjs')],
outfile: join(__dirname, 'dist', name, 'main.mjs'),
bundle: true,
platform: 'node',
format: 'esm',
minify: true,
logLevel: 'silent',
plugins,
});
}

await run('plain', []);
await run(
'plugin',
// No auth/release/telemetry — we only care about the build-time transforms and defines.
[
sentryEsbuildPlugin({
telemetry: false,
sourcemaps: { disable: true },
release: { create: false, finalize: false, inject: false },
}),
],
);

// eslint-disable-next-line no-console
console.log('built plain + plugin with esbuild');
23 changes: 23 additions & 0 deletions dev-packages/e2e-tests/test-applications/node-esbuild/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "node-esbuild",
"description": "ensure the Sentry esbuild plugin builds with build-time instrumentation",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"clean": "npx rimraf node_modules dist pnpm-lock.yaml",
"test:build": "pnpm install && node ./build.mjs",
"test:assert": "node ./assert.mjs"
},
"dependencies": {
"@sentry/node": "file:../../packed/sentry-node-packed.tgz",
"@sentry/server-utils": "file:../../packed/sentry-server-utils-packed.tgz",
"@sentry/bundler-plugins": "file:../../packed/sentry-bundler-plugins-packed.tgz"
},
"devDependencies": {
"esbuild": "0.28.2"
},
"volta": {
"extends": "../../package.json"
}
}

This file was deleted.

This file was deleted.

48 changes: 48 additions & 0 deletions dev-packages/e2e-tests/test-applications/node-rollup/assert.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Asserts that the Sentry rollup plugin excludes the *runtime* diagnostics-channel injection by
* default (because it instruments at build time instead), while a plain build keeps it.
*
* @module
*/
import { readdirSync, readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = dirname(fileURLToPath(import.meta.url));

// This string literal lives only in `@sentry/server-utils`' runtime injection module
// (`orchestrion/runtime/register.ts`) — the code `registerDiagnosticsChannelInjection()` pulls in.
// Its presence means the runtime injection was bundled; its absence means it was tree-shaken.
const RUNTIME_INJECTION_MARKER = 'Registered diagnostics-channel injection';

function bundleText(name) {
const dir = join(__dirname, 'dist', name);
return readdirSync(dir)
.map(f => readFileSync(join(dir, f), 'utf8'))
.join('\n');
}

let failed = false;
function check(condition, message) {
// eslint-disable-next-line no-console
console.log(`${condition ? 'ok ' : 'FAIL'} - ${message}`);
if (!condition) failed = true;
}

const plain = bundleText('plain');
const plugin = bundleText('plugin');

check(
plain.includes(RUNTIME_INJECTION_MARKER),
'plain build (no plugin) bundles the runtime channel injection by default',
);
check(
!plugin.includes(RUNTIME_INJECTION_MARKER),
'sentryRollupPlugin excludes the runtime channel injection by default (build-time instrumentation)',
);

if (failed) {
process.exit(1);
}
// eslint-disable-next-line no-console
console.log('All bundle assertions passed.');
42 changes: 42 additions & 0 deletions dev-packages/e2e-tests/test-applications/node-rollup/build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Bundles the entrypoint with Rollup twice:
// - `plain`: no Sentry plugin — the runtime diagnostics-channel injection is bundled (v11 default).
// - `plugin`: with `sentryRollupPlugin` (build-time instrumentation), which defaults
// `bundleSizeOptimizations.excludeChannelInjection` to `true`, so Rollup tree-shakes
// the runtime injection out.
// assert.mjs inspects both outputs.
import { builtinModules } from 'node:module';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import { rollup } from 'rollup';
import { sentryRollupPlugin } from '@sentry/node/rollup';

const __dirname = dirname(fileURLToPath(import.meta.url));
const external = [...builtinModules, ...builtinModules.map(m => `node:${m}`)];

async function run(name, extra) {
const bundle = await rollup({
input: join(__dirname, 'src', 'entry.mjs'),
external,
plugins: [nodeResolve({ exportConditions: ['node', 'import', 'default'] }), commonjs(), ...extra],
onwarn: () => {},
});
await bundle.write({ dir: join(__dirname, 'dist', name), format: 'es', entryFileNames: 'main.mjs' });
await bundle.close();
}

await run('plain', []);
await run(
'plugin',
// `sentryRollupPlugin` returns an array of Rollup plugins. No auth/release/telemetry — we only care
// about the build-time transforms and defines.
sentryRollupPlugin({
telemetry: false,
sourcemaps: { disable: true },
release: { create: false, finalize: false, inject: false },
}),
);

// eslint-disable-next-line no-console
console.log('built plain + plugin with rollup');
25 changes: 25 additions & 0 deletions dev-packages/e2e-tests/test-applications/node-rollup/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "node-rollup",
"description": "ensure the Sentry rollup plugin excludes runtime channel injection by default",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"clean": "npx rimraf node_modules dist pnpm-lock.yaml",
"test:build": "pnpm install && node ./build.mjs",
"test:assert": "node ./assert.mjs"
},
"dependencies": {
"@sentry/node": "file:../../packed/sentry-node-packed.tgz",
"@sentry/server-utils": "file:../../packed/sentry-server-utils-packed.tgz",
"@sentry/bundler-plugins": "file:../../packed/sentry-bundler-plugins-packed.tgz"
},
"devDependencies": {
"rollup": "4.62.3",
"@rollup/plugin-node-resolve": "^16.0.0",
"@rollup/plugin-commonjs": "^28.0.0"
},
"volta": {
"extends": "../../package.json"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line no-console
console.log('this is the application');
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as Sentry from '@sentry/node';

Sentry.init({
traceLifecycle: 'static',
dsn: 'https://public@dsn.ingest.sentry.io/1337',
tracesSampleRate: 1,
});

await import('./app.mjs');
48 changes: 48 additions & 0 deletions dev-packages/e2e-tests/test-applications/node-vite/assert.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Asserts that the Sentry vite plugin excludes the *runtime* diagnostics-channel injection by
* default (because it instruments at build time instead), while a plain build keeps it.
*
* @module
*/
import { readdirSync, readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = dirname(fileURLToPath(import.meta.url));

// This string literal lives only in `@sentry/server-utils`' runtime injection module
// (`orchestrion/runtime/register.ts`) — the code `registerDiagnosticsChannelInjection()` pulls in.
// Its presence means the runtime injection was bundled; its absence means it was tree-shaken.
const RUNTIME_INJECTION_MARKER = 'Registered diagnostics-channel injection';

function bundleText(name) {
const dir = join(__dirname, 'dist', name);
return readdirSync(dir)
.map(f => readFileSync(join(dir, f), 'utf8'))
.join('\n');
}

let failed = false;
function check(condition, message) {
// eslint-disable-next-line no-console
console.log(`${condition ? 'ok ' : 'FAIL'} - ${message}`);
if (!condition) failed = true;
}

const plain = bundleText('plain');
const plugin = bundleText('plugin');

check(
plain.includes(RUNTIME_INJECTION_MARKER),
'plain build (no plugin) bundles the runtime channel injection by default',
);
check(
!plugin.includes(RUNTIME_INJECTION_MARKER),
'sentryVitePlugin excludes the runtime channel injection by default (build-time instrumentation)',
);

if (failed) {
process.exit(1);
}
// eslint-disable-next-line no-console
console.log('All bundle assertions passed.');
Loading