feat: implement debug-files bundle-jvm command#1089
Conversation
|
Codecov Results 📊✅ Patch coverage is 88.72%. Project has 5039 uncovered lines. Files with missing lines (2)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
+ Coverage 81.17% 81.19% +0.02%
==========================================
Files 383 386 +3
Lines 26659 26792 +133
Branches 17338 17385 +47
==========================================
+ Hits 21640 21753 +113
- Misses 5019 5039 +20
- Partials 1796 1807 +11Generated by Codecov Action |
b682684 to
d160626
Compare
Create JVM source bundles from directories of Java, Kotlin, Scala, Groovy, and Clojure source files. The bundle is a ZIP archive that can be uploaded to Sentry for source context in JVM stack traces. This command is local-only — it makes no API calls. The bundle is uploaded separately via `debug-files upload --type jvm`. Key features: - Walks a directory for JVM source files (10 extensions supported) - Intelligent filtering: always excludes IDE dirs (.idea, .gradle, etc.) - Smart build-output detection: excludes bin/build/out/target dirs UNLESS they appear under a src/ ancestor (handles JVM package names like com.example.build correctly) - Strips source-set prefixes (src/main/java/, src/test/kotlin/, etc.) to produce package-relative paths matching JVM stack traces - Replaces file extensions with .jvm for symbolicator URL matching - First-seen-wins deduplication with collision warnings - Writes ZIP with SYSB header + manifest.json (symbolic source bundle format) using the existing ZipWriter - Hidden from help (experimental, like legacy CLI) Files: - src/lib/jvm-bundle.ts — core logic (walking, filtering, URL construction, ZIP) - src/commands/debug-files/bundle-jvm.ts — CLI command - src/commands/debug-files/index.ts — route map - src/app.ts — route registration (hidden) - test/lib/jvm-bundle.test.ts — 25 unit tests - test/commands/debug-files/bundle-jvm.test.ts — 6 command tests
d160626 to
12c7f7d
Compare
| const validated: ValidatedEntry[] = []; | ||
|
|
||
| for (const [url, absPath] of urlToAbsPath) { | ||
| const bundlePath = `files/_/${url.replace(URL_PREFIX_RE, "")}`; |
There was a problem hiding this comment.
Bug: The path format for JVM source bundles, files/_/<path>, is inconsistent with the sourcemap bundle format, _/_/<path>, which will likely cause symbolicator processing to fail.
Severity: HIGH
Suggested Fix
Align the JVM bundle path generation with the sourcemap implementation. Change the bundlePath construction in src/lib/jvm-bundle.ts from files/_/${url.replace(URL_PREFIX_RE, "")} to use the _/_/ prefix for consistency with other bundle types processed by symbolicator.
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: src/lib/jvm-bundle.ts#L278
Potential issue: The path for JVM source bundle entries is generated as
`files/_/<path>`, which is inconsistent with the `_/_/<path>` format used by sourcemap
bundles. This discrepancy extends to the bundle's manifest file, where the file path is
used as a key. Because Sentry's symbolicator relies on this path structure to locate
source files, this inconsistency will likely cause it to fail when processing JVM
bundles. As a result, source context for JVM stack traces will not be available,
silently degrading a core feature for JVM projects.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 12c7f7d. Configure here.
|
|
||
| if (result.fileCount === 0) { | ||
| log.warn("No JVM source files found in the given directory."); | ||
| } |
There was a problem hiding this comment.
Misleading empty-bundle warning
Medium Severity
When fileCount is zero, the command always warns that no JVM source files were found, but fileCount counts only entries that passed read and UTF-8 validation. Discovered .java/.kt files that were skipped as non-UTF-8 or unreadable still produce this message and an empty ZIP, which misleads troubleshooting of source-context uploads.
Reviewed by Cursor Bugbot for commit 12c7f7d. Configure here.
There was a problem hiding this comment.
Symlinked source files and directories are silently dropped from the bundle
Node's Dirent.isFile() and isDirectory() both return false for symbolic links, so symlinked source files are never collected and symlinked source directories are never descended — producing a silently incomplete bundle with no warning to the user.
Evidence
collectJvmSources(jvm-bundle.ts) usesentry.isDirectory()(line 239) to decide recursion andentry.isFile()(insideisJvmSourceFile) to decide inclusion.- Per Node.js docs,
Dirent.isFile()/isDirectory()do not follow symbolic links; onlyDirent.isSymbolicLink()identifies them. - Monorepo setups or projects using
ln -sfor shared sources would silently lose those files with no warning log. - The command already logs a warning for zero files found, but a partial miss (some symlinks, some real files) produces no diagnostic.
Identified by Warden find-bugs


Summary
Final command from #1055 — implements
sentry debug-files bundle-jvm, porting the legacy Rust sentry-cli's JVM source bundle creation.What it does
Creates a JVM source bundle ZIP from a directory of Java, Kotlin, Scala, Groovy, or Clojure source files. The bundle enables source context in Sentry JVM stack traces.
This command is local-only — no API calls. Upload the bundle separately via
debug-files upload --type jvm.How it works
.java,.kt,.scala,.sc,.groovy,.gvy,.gy,.gsh,.clj,.cljc).idea,.gradle,.vscode,node_modules, etc.)bin/,build/,out/,target/UNLESS under asrc/ancestor (handles JVM packages likecom.example.build)--excludepatternssrc/main/java/,src/test/kotlin/, etc.) to produce package-relative paths.jvm, prefixes with~/manifest.json(symbolic source bundle format)Flags
--output/-o--debug-id/-d--exclude/-e--jsonBuild-output filtering example
build/generated/Foo.javabuild/with nosrc/ancestorsrc/main/java/com/example/build/Builder.javabuildis undersrc/build/src/main/java/Foo.javasrc/is insidebuild/, not abovetarget/classes/Foo.javatarget/with nosrc/ancestorFiles
src/lib/jvm-bundle.tssrc/commands/debug-files/bundle-jvm.tssrc/commands/debug-files/index.tssrc/app.tsdocs/src/fragments/commands/debug-files.mdtest/lib/jvm-bundle.test.tstest/commands/debug-files/bundle-jvm.test.tsTesting
31 tests covering: