diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3191f92adefb..e233d1dec828 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -848,6 +848,7 @@ jobs: 'create-next-app', 'create-remix-app', 'create-remix-app-v2', + 'debug-id-sourcemaps', 'nextjs-app-dir', 'react-create-hash-router', 'react-router-6-use-routes', diff --git a/packages/e2e-tests/test-applications/debug-id-sourcemaps/.gitignore b/packages/e2e-tests/test-applications/debug-id-sourcemaps/.gitignore new file mode 100644 index 000000000000..1521c8b7652b --- /dev/null +++ b/packages/e2e-tests/test-applications/debug-id-sourcemaps/.gitignore @@ -0,0 +1 @@ +dist diff --git a/packages/e2e-tests/test-applications/debug-id-sourcemaps/.npmrc b/packages/e2e-tests/test-applications/debug-id-sourcemaps/.npmrc new file mode 100644 index 000000000000..c6b3ef9b3eaa --- /dev/null +++ b/packages/e2e-tests/test-applications/debug-id-sourcemaps/.npmrc @@ -0,0 +1,2 @@ +@sentry:registry=http://localhost:4873 +@sentry-internal:registry=http://localhost:4873 diff --git a/packages/e2e-tests/test-applications/debug-id-sourcemaps/package.json b/packages/e2e-tests/test-applications/debug-id-sourcemaps/package.json new file mode 100644 index 000000000000..b261ace67fb8 --- /dev/null +++ b/packages/e2e-tests/test-applications/debug-id-sourcemaps/package.json @@ -0,0 +1,23 @@ +{ + "name": "debug-id-sourcemaps", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup --config rollup.config.mjs", + "test": "vitest run", + "clean": "npx rimraf node_modules,pnpm-lock.yaml", + "test:build": "pnpm install && pnpm build", + "test:assert": "pnpm test" + }, + "dependencies": { + "@sentry/node": "latest || *" + }, + "devDependencies": { + "rollup": "^4.0.2", + "vitest": "^0.34.6", + "@sentry/rollup-plugin": "2.8.0" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/packages/e2e-tests/test-applications/debug-id-sourcemaps/rollup.config.mjs b/packages/e2e-tests/test-applications/debug-id-sourcemaps/rollup.config.mjs new file mode 100644 index 000000000000..47273c79ea9d --- /dev/null +++ b/packages/e2e-tests/test-applications/debug-id-sourcemaps/rollup.config.mjs @@ -0,0 +1,20 @@ +import { defineConfig } from 'rollup'; +import { sentryRollupPlugin } from '@sentry/rollup-plugin'; + +export default defineConfig({ + input: './src/app.js', + external: ['@sentry/node'], + plugins: [ + sentryRollupPlugin({ + org: process.env.E2E_TEST_SENTRY_ORG_SLUG, + project: process.env.E2E_TEST_SENTRY_TEST_PROJECT, + authToken: process.env.E2E_TEST_AUTH_TOKEN, + }), + ], + output: { + file: './dist/app.js', + compact: true, + format: 'cjs', + sourcemap: 'hidden', + }, +}); diff --git a/packages/e2e-tests/test-applications/debug-id-sourcemaps/src/app.js b/packages/e2e-tests/test-applications/debug-id-sourcemaps/src/app.js new file mode 100644 index 000000000000..68a4aae16d85 --- /dev/null +++ b/packages/e2e-tests/test-applications/debug-id-sourcemaps/src/app.js @@ -0,0 +1,10 @@ +import * as Sentry from '@sentry/node'; + +Sentry.init({ + environment: 'qa', // dynamic sampling bias to keep transactions + dsn: process.env.E2E_TEST_DSN, +}); + +const eventId = Sentry.captureException(new Error('Sentry Debug ID E2E Test Error')); + +process.stdout.write(eventId); diff --git a/packages/e2e-tests/test-applications/debug-id-sourcemaps/tests/__snapshots__/server.test.ts.snap b/packages/e2e-tests/test-applications/debug-id-sourcemaps/tests/__snapshots__/server.test.ts.snap new file mode 100644 index 000000000000..8b157beba9da --- /dev/null +++ b/packages/e2e-tests/test-applications/debug-id-sourcemaps/tests/__snapshots__/server.test.ts.snap @@ -0,0 +1,20 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Find symbolicated event on sentry 1`] = ` +{ + "colno": 41, + "contextLine": "const eventId = Sentry.captureException(new Error('Sentry Debug ID E2E Test Error'));", + "lineno": 8, + "postContext": [ + "", + "process.stdout.write(eventId);", + ], + "preContext": [ + "Sentry.init({", + " environment: 'qa', // dynamic sampling bias to keep transactions", + " dsn: process.env.E2E_TEST_DSN,", + "});", + "", + ], +} +`; diff --git a/packages/e2e-tests/test-applications/debug-id-sourcemaps/tests/server.test.ts b/packages/e2e-tests/test-applications/debug-id-sourcemaps/tests/server.test.ts new file mode 100644 index 000000000000..df41adb615c8 --- /dev/null +++ b/packages/e2e-tests/test-applications/debug-id-sourcemaps/tests/server.test.ts @@ -0,0 +1,53 @@ +import { test } from 'vitest'; +import childProcess from 'child_process'; +import path from 'path'; + +const authToken = process.env.E2E_TEST_AUTH_TOKEN; +const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; +const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const EVENT_POLLING_TIMEOUT = 30_000; + +test( + 'Find symbolicated event on sentry', + async ({ expect }) => { + const eventId = childProcess.execSync(`node ${path.join(__dirname, '..', 'dist', 'app.js')}`, { + encoding: 'utf-8', + }); + + console.log(`Polling for error eventId: ${eventId}`); + + let timedOut = false; + setTimeout(() => { + timedOut = true; + }, EVENT_POLLING_TIMEOUT); + + while (!timedOut) { + await new Promise(resolve => setTimeout(resolve, 2000)); // poll every two seconds + const response = await fetch( + `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${eventId}/json/`, + { headers: { Authorization: `Bearer ${authToken}` } }, + ); + + // Only allow ok responses or 404 + if (!response.ok) { + expect(response.status).toBe(404); + continue; + } + + const eventPayload = await response.json(); + const frames = eventPayload.exception?.values?.[0]?.stacktrace?.frames; + const topFrame = frames[frames.length - 1]; + expect({ + preContext: topFrame?.pre_context, + contextLine: topFrame?.context_line, + postContext: topFrame?.post_context, + lineno: topFrame?.lineno, + colno: topFrame?.colno, + }).toMatchSnapshot(); + return; + } + + throw new Error('Test timed out'); + }, + { timeout: EVENT_POLLING_TIMEOUT }, +);