Skip to content

feat: implement debug-files bundle-jvm command#1089

Open
BYK wants to merge 1 commit into
mainfrom
feat/debug-files-bundle-jvm
Open

feat: implement debug-files bundle-jvm command#1089
BYK wants to merge 1 commit into
mainfrom
feat/debug-files-bundle-jvm

Conversation

@BYK

@BYK BYK commented Jun 9, 2026

Copy link
Copy Markdown
Member

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.

sentry debug-files bundle-jvm --output ./out --debug-id <uuid> ./src

This command is local-only — no API calls. Upload the bundle separately via debug-files upload --type jvm.

How it works

  1. Walks a directory for JVM source files (10 extensions: .java, .kt, .scala, .sc, .groovy, .gvy, .gy, .gsh, .clj, .cljc)
  2. Filters intelligently:
    • Always excludes IDE/build dirs (.idea, .gradle, .vscode, node_modules, etc.)
    • Smart build-output detection: excludes bin/, build/, out/, target/ UNLESS under a src/ ancestor (handles JVM packages like com.example.build)
    • Hidden directories (dot-prefixed) excluded
    • User-provided --exclude patterns
  3. Strips source-set prefixes (src/main/java/, src/test/kotlin/, etc.) to produce package-relative paths
  4. Builds URLs: replaces extensions with .jvm, prefixes with ~/
  5. Deduplicates by URL (first-seen wins, with collision warnings)
  6. Writes a ZIP with SYSB header + manifest.json (symbolic source bundle format)

Flags

Flag Description
--output / -o Required. Output directory for the bundle ZIP
--debug-id / -d Required. Debug ID (UUID) matching the SDK configuration
--exclude / -e Optional, repeatable. Additional directory names to exclude
--json Machine-readable output

Build-output filtering example

Path Kept? Reason
build/generated/Foo.java No build/ with no src/ ancestor
src/main/java/com/example/build/Builder.java Yes build is under src/
build/src/main/java/Foo.java No src/ is inside build/, not above
target/classes/Foo.java No target/ with no src/ ancestor

Files

File Purpose
src/lib/jvm-bundle.ts Core logic (walking, filtering, URL construction, ZIP writing)
src/commands/debug-files/bundle-jvm.ts CLI command
src/commands/debug-files/index.ts Route map
src/app.ts Route registration (hidden)
docs/src/fragments/commands/debug-files.md Doc fragment
test/lib/jvm-bundle.test.ts 25 unit tests
test/commands/debug-files/bundle-jvm.test.ts 6 command tests

Testing

31 tests covering:

  • Path filtering: ambiguous build dirs (8 tests)
  • Source-set prefix stripping: all JVM languages, backslash normalization (8 tests)
  • URL construction (3 tests)
  • Bundle creation: Java/Kotlin files, build-output exclusion, exclude patterns, empty dirs, debug ID (6 tests)
  • CLI: ZIP creation, invalid debug ID, nonexistent path, JSON output, empty dir, output dir creation (6 tests)

@BYK BYK added the enhancement New feature or request label Jun 9, 2026
@BYK BYK enabled auto-merge (squash) June 9, 2026 17:44
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://cli.sentry.dev/_preview/pr-1089/

Built to branch gh-pages at 2026-06-09 17:59 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Comment thread src/lib/jvm-bundle.ts
Comment thread src/lib/jvm-bundle.ts
Comment thread src/lib/jvm-bundle.ts Outdated
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Codecov Results 📊

✅ Patch coverage is 88.72%. Project has 5039 uncovered lines.
✅ Project coverage is 81.19%. Comparing base (base) to head (head).

Files with missing lines (2)
File Patch % Lines
src/lib/jvm-bundle.ts 88.18% ⚠️ 13 Missing and 7 partials
src/commands/debug-files/bundle-jvm.ts 90.91% ⚠️ 2 Missing and 2 partials
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       +11

Generated by Codecov Action

@BYK BYK force-pushed the feat/debug-files-bundle-jvm branch from b682684 to d160626 Compare June 9, 2026 17:51
Comment thread src/lib/jvm-bundle.ts Outdated
Comment thread src/lib/jvm-bundle.ts
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
@BYK BYK force-pushed the feat/debug-files-bundle-jvm branch from d160626 to 12c7f7d Compare June 9, 2026 17:58
Comment thread src/lib/jvm-bundle.ts
const validated: ValidatedEntry[] = [];

for (const [url, absPath] of urlToAbsPath) {
const bundlePath = `files/_/${url.replace(URL_PREFIX_RE, "")}`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.");
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 12c7f7d. Configure here.

@sentry-warden sentry-warden Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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) uses entry.isDirectory() (line 239) to decide recursion and entry.isFile() (inside isJvmSourceFile) to decide inclusion.
  • Per Node.js docs, Dirent.isFile() / isDirectory() do not follow symbolic links; only Dirent.isSymbolicLink() identifies them.
  • Monorepo setups or projects using ln -s for 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant