[RUM-16940] add --debug-id upload mode for web sourcemaps#2374
Conversation
🎉 All green!🧪 All tests passed 🔗 Commit SHA: d0191ae | Docs | Datadog PR Page | Give us feedback! |
74628e3 to
616359c
Compare
Adds support for identifying sourcemaps via debug IDs (extracted from the bundle's _ddDebugIds snippet) as an alternative to service/version/ minified-path-prefix. Refactors asMultipartPayload and getMetadataPayload to accept a SourcemapUploadOptions object, and adds test fixtures and unit tests for debug ID extraction. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…load output - Move extractDebugId into debugId.ts with a module-level DD_DEBUG_ID_REGEX - Support single-quoted keys and values in the regex - Print extracted debug ID in dry-run and live upload output via renderUpload - Add debugId.test.ts covering multiple snippet formats and error cases - Add execute-level dry-run test checking debug ID appears in output Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
616359c to
8f7bda1
Compare
--debug-id upload mode for web sourcemaps
There was a problem hiding this comment.
When --debug-id mode is enabled but the debug ID cannot be extracted from the bundle, the code continues with an upload containing no sourcemap identifier. JSON.stringify silently omits undefined fields, resulting in metadata that the backend cannot match to error frames, causing silent sourcemap failures. The PR lacks validation to fail fast when extraction fails.
📊 Validated against 7 scenarios · Open Bits AI session
🤖 Datadog Autotest · Commit 8f7bda1 · What is Autotest? · Any feedback? Reach out in #autotest
| this.releaseVersion!, | ||
| this.projectPath ?? '' | ||
| ) | ||
| const debugId = this.debugId ? extractDebugId(sourcemap.minifiedFilePath, this.context) : undefined |
There was a problem hiding this comment.
Missing validation allows sourcemap uploads with no identifier when debug ID extraction fails
Sourcemap uploads fail silently. Error frames cannot be unminified. Production RUM events show unminified error stacks instead of source code.
Assertion details
- Input: User runs:
datadog-ci sourcemaps upload ./dist --debug-idwhere bundle has no ddDebugId snippet - Expected:
Command should fail with error message, or require fallback to traditional mode with service/version/prefix - Actual:
extractDebugId returns undefined, code continues with asMultipartPayload called with service=undefined, version=undefined, debugId=undefined. JSON.stringify silently omits these fields. Backend receives only {cli_version, type, minified_url} with no sourcemap identifier.
Was this helpful? React 👍 or 👎
🤖 Datadog Autotest · What is Autotest? · Any feedback? Reach out in #autotest
There was a problem hiding this comment.
Already handled — in --debug-id mode a payload is never uploaded without an identifier:
- Per file: a sourcemap with no
ddDebugIdis skipped (missing_debug_id) in validation, beforeasMultipartPayloadis built. - All files: if none yield a debug ID, the command aborts with exit 1 (
No debug ID found in any minified file. Aborting upload.) before any upload.
- addDebugIdToPayloads sets each payload's debugId and gates the abort - fold missing-debug-ID skip into validatePayload as an InvalidPayload - move debug-ID messages into renderer; keep extractDebugId pure - add debugId.test.ts coverage and partial-debug-id fixture Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
buranmert
left a comment
There was a problem hiding this comment.
LGTM but i left 2 comments before approving
|
|
||
| import type {Sourcemap} from './interfaces' | ||
|
|
||
| const DD_DEBUG_ID_REGEX = /["']ddDebugId["']\s*:\s*["']([^"']+)["']/ |
| }) | ||
| } | ||
|
|
||
| private validateOptions(): boolean { |
There was a problem hiding this comment.
(i chose a random line to leave this comment)
should we allow the customers to specify service,version,path and debug_id at the same time? or should we enforce one of these ways?
for example i'm a customer
yesterday i did datadog-ci sourcemaps upload --service foo1 --version bar111 --debug_id 123-456 ✅
if today i do datadog-ci sourcemaps upload --service foo2 --version bar222 --debug_id 123-456 this will be dropped in our ingestion pipeline as debug_id is a duplicate ❌
i'm wondering if this can create confusion
• IMO either we can disallow usage of service,version,path and debug_id at the same time
• or we can simply log a warning in terminal saying "service,version,path will be ignored as debug_id is already provided"
what do you think?
There was a problem hiding this comment.
You’re right. I’ll update it to forbid using service and version alongside --debug-id.
There was a problem hiding this comment.
Pull request overview
Adds a new --debug-id mode to the sourcemaps upload command to support per-frame sourcemap resolution (for multi–micro-frontend stacks) by extracting a ddDebugId from minified bundles and sending it as upload metadata.
Changes:
- Adds
--debug-idflag, option validation logic, and debug-id extraction from minified JS bundles. - Updates sourcemap payload metadata generation and CLI output to incorporate
debug_id. - Adds Jest coverage plus new fixtures for debug-id and partial-debug-id scenarios.
Reviewed changes
Copilot reviewed 7 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/base/src/commands/sourcemaps/validation.ts | Adds validation to require a debug ID per payload when debug-id mode is enabled. |
| packages/base/src/commands/sourcemaps/upload.ts | Adds --debug-id flag, new option validation, debug-id extraction gate, and updates payload building call-site. |
| packages/base/src/commands/sourcemaps/renderer.ts | Updates command/info output and upload rendering to include debug-id context and new abort message. |
| packages/base/src/commands/sourcemaps/interfaces.ts | Adds debugId to Sourcemap and refactors multipart payload creation to accept an options object including debug_id. |
| packages/base/src/commands/sourcemaps/debugId.ts | New helper for extracting ddDebugId from bundle content and populating payloads. |
| packages/base/src/commands/sourcemaps/tests/upload.test.ts | Adds unit tests for validateOptions and integration-style tests for debug-id upload behavior. |
| packages/base/src/commands/sourcemaps/tests/fixtures/bundle-with-partial-debug-id/a.min.js.map | New fixture sourcemap for a bundle that includes a debug ID. |
| packages/base/src/commands/sourcemaps/tests/fixtures/bundle-with-partial-debug-id/a.min.js | New fixture minified JS containing the ddDebugId snippet. |
| packages/base/src/commands/sourcemaps/tests/fixtures/bundle-with-partial-debug-id/b.min.js.map | New fixture sourcemap for a bundle without a debug ID. |
| packages/base/src/commands/sourcemaps/tests/fixtures/bundle-with-partial-debug-id/b.min.js | New fixture minified JS without the debug ID snippet. |
| packages/base/src/commands/sourcemaps/tests/fixtures/bundle-with-debug-id/common.min.js.map | New fixture sourcemap for a bundle that includes a debug ID. |
| packages/base/src/commands/sourcemaps/tests/fixtures/bundle-with-debug-id/common.min.js | New fixture minified JS containing the ddDebugId snippet. |
| packages/base/src/commands/sourcemaps/tests/debugId.test.ts | New unit tests for debug-id extraction and payload mutation logic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ied-path-prefix instead Copilot review flagged --project-path as wrongly rejected in debug-id mode; it's still used and sent in the event payload. --minified-path-prefix is the option that actually conflicts, per the PR description.
…e found addDebugIdToPayloads([]) returns false, so --debug-id mode wrongly exited 1 with a misleading "No debug ID found" error when zero sourcemaps matched, unlike non-debug-id mode which exits 0 in that case.
Context
When an error spans multiple micro-frontends, unminification breaks because all frames are resolved using the top frame’s (service, version).
This PR adds support for
debug_idsourcemaps by extracting thedebug_id(a TC39 proposal) from the source file and including it in the upload metadata. This enables the backend to resolve sourcemaps per frame using debug_id instead of a shared (service, version).What this PR does
Adds a
--debug-idflag tosourcemaps upload. When set:--service,--release-version, and--minified-path-prefixare forbidden when --debug-id is presentdebug_idfrom the bundle'sddDebugIdruntime snippet (injected by the build plugin)debug_idinstead ofservice/version/minified_urlTest plan
yarn buildyarn test packages/base/src/commands/sourcemapsyarn launch sourcemaps upload <path> --debug-id --dry-runyarn launch sourcemaps upload <path>— validates and rejects missing flags