Skip to content

feat: add SentryDebugIdPlugin - #1451

Open
elirangoshen wants to merge 1 commit into
callstack:mainfrom
elirangoshen:feat/sentry-debug-id-plugin
Open

feat: add SentryDebugIdPlugin#1451
elirangoshen wants to merge 1 commit into
callstack:mainfrom
elirangoshen:feat/sentry-debug-id-plugin

Conversation

@elirangoshen

Copy link
Copy Markdown

Summary

Adds SentryDebugIdPlugin, which stamps a Sentry Debug ID into the bundle and its source map.

A Debug ID is a UUID present in both artifacts. The Sentry SDK reports it with every event and Sentry uses it to pair a JS stack trace with the source map that resolves it. For Metro, @sentry/react-native provides this through createSentryMetroSerializer; Re.Pack currently has no equivalent, so apps that migrate lose JS symbolication.

Why @sentry/webpack-plugin doesn't cover this

Two independent gaps, both found while migrating a large app (Expensify, ~35MB minified prod bundle) from Metro to Re.Pack:

  1. The injection never applies. The plugin stamps the bundle through a BannerPlugin with a hardcoded include: /\.(js|ts|jsx|tsx|mjs|cjs)(\?[^?]*)?(#[^#]*)?$/. Re.Pack emits index.bundle, so nothing matches and no snippet is injected — silently, no warning.
  2. Emitted source maps never get the ID. prepareSourceMapForDebugIdUpload() sets debugId/debug_id on a copy written to the upload directory, never on the emitted asset. @sentry/react-native uploads through its own Gradle/Xcode integration, which reads the on-disk map: scripts/copy-debugid.js copies the ID onto the Hermes composed map and scripts/has-sourcemap-debugid.js verifies it. Both no-op when the field is absent, so the build succeeds and symbolication quietly fails.

The two plugins compose fine — this one handles the Debug ID, @sentry/webpack-plugin still handles release creation and upload.

Implementation

  • Injects the snippet via BannerPlugin, defaulting test to /\.([cm]?jsx?|bundle)$/ — the same pattern SourceMapPlugin already uses, so .bundle and .js outputs both work.
  • Writes debugId and debug_id into emitted .map assets in processAssets at PROCESS_ASSETS_STAGE_REPORT, after the devtool stage. Sentry's tooling reads either spelling depending on version, so both are written.
  • Not wired into RepackPlugin — Sentry is opt-in, so users add the plugin explicitly.

Because injection happens through BannerPlugin, source maps are generated after the banner and account for the added bytes; column offsets are not shifted. Verified against a no-injection build of the same app: the first mapping segment changes (60BAwJAmqCAwJA) rather than staying identical.

Verification

Unit tests do a real Rspack compile through memfs and assert the bundle stamp matches the map's debugId, for both index.bundle and index.js outputs.

Also verified end to end in the app on iOS and Android production bundles:

Check Before After
map debugId absent present (debugId + debug_id)
bundle sentry-dbid-<uuid> stamp absent present, matches the map
has-sourcemap-debugid.js fails prints UUID, exit 0
copy-debugid.js → Hermes map no-op copies the ID

pnpm jest src/plugins/__tests__ → 82 tests pass (7 suites), pnpm --filter @callstack/repack typecheck clean, pnpm biome check clean. Changeset and a docs page under website/src/latest/api/plugins/ included.

Env: @rspack/core 2.1.3, react-native 0.86.0, @sentry/react-native 8.7.0, @sentry/webpack-plugin 5.2.0.

Open questions for maintainers

  • Would you rather this lived in a separate packages/plugin-sentry package, alongside plugin-reanimated / plugin-expo-modules? Happy to move it.
  • I kept it out of RepackPlugin. If you'd prefer an opt-in flag there (e.g. sentry: true), that's an easy follow-up.

Stamps a Sentry Debug ID into the bundle and its source map, so Sentry can pair
a JS stack trace with the source map that resolves it. This is the Re.Pack
counterpart of what @sentry/react-native provides for Metro through
createSentryMetroSerializer.
@changeset-bot

changeset-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ffff910

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@callstack/repack Minor
@callstack/repack-plugin-expo-modules Minor
@callstack/repack-plugin-nativewind Minor
@callstack/repack-plugin-reanimated Minor
@callstack/repack-dev-server Minor
@callstack/repack-init Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Sep 4, 2026

Copy link
Copy Markdown

@elirangoshen is attempting to deploy a commit to the Callstack Team on Vercel.

A member of the Team first needs to authorize it.

@elirangoshen
elirangoshen marked this pull request as ready for review September 4, 2026 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant