Skip to content

Expo plugin: no debugSymbolLevel (Gradle plugin 4.0.8 reads unstripped libraries); remove the old symbol block; bugsee-cli 0.7.12 - #69

Merged
krassx merged 4 commits into
mainfrom
feat/ndk-full-symbols
Oct 11, 2026
Merged

krassx merged 4 commits into
mainfrom
feat/ndk-full-symbols

Conversation

@krassx

@krassx krassx commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Replaces #64, which GitHub closed when its stacked base (#68) was merged and deleted. Same branch, rebased onto main after #68 (71d2492); plugin/build regenerated.

Reworked. This PR is stacked on #68 (Android SDK 7.3.1 and Gradle plugin 4.0.8), and its base is that branch; it moves to main when #68 merges. The earlier version (an ndkSymbolLevel option, FULL by default) is superseded: Bugsee Gradle plugin 4.0.8 uploads native symbols from the unstripped libraries in merged_native_libs, independent of ndk.debugSymbolLevel (gradle-plugin #10, PR #13; the 4.0.8 jar has useMergedNativeLibs/mergedNativeLibsDir and a CLI floor of 0.8.1). The old tip is kept as branch backup/ndk-full-symbols-633c2ae (local only).

Expo config plugin

  • Writes no debugSymbolLevel, on or off. debugSymbolLevel is the app's own choice for Google Play.
  • On every prebuild it removes the // bugsee-symbol-table: SYMBOL_TABLE block earlier versions wrote into debug/release. The block is recognised only by its marker plus its exact lines, at any indentation, with CRLF kept.
  • A level of the user's (code, dotted, defaultConfig, any build type) is never touched.
  • An old block the user changed inside is now the user's: it stays, and the prebuild log says so. It used to refuse with nativeCrashReporting: false.
  • Build-type anchors are gone, so a one-line release { … } or a closer that shares its line is no longer refused.
  • The unreleased ndkSymbolLevel option is dropped. The plugin never validated unknown options, so a config that still sets it prebuilds as if it were absent.
  • The block's text stays verbatim as the recognition fingerprint. Its claim that libreactnative.so is pre-stripped is false (the Maven AAR ships it with full DWARF), and that is noted at the constant.

Kept from the earlier version

Tests

  • Corpus: the generic oracle now forbids any Bugsee symbol-block line in the output, and requires the debugSymbolLevel count to equal the user's own across all 4 option sets, every ordered pair, and the chain. The anchor-refusal cases become kept-as-is cases. The changed-block cases stay as the user's. New cases: N01 (old blocks in debug and release beside a user FULL in defaultConfig), N02 (CRLF, beside the user's own ndk block), N03 (user levels in both build types), N04 (the block quoted in a string).
  • Unit: removal on and off, inside build types, partial markers, the changed-block note, the Expo SDK 57 template, and the old block plus a hand-written ndk block (equal to a fresh prebuild).
  • yarn lint, typecheck, test: 3335 tests, 12 skipped, all pass.
  • Focused Stryker (gradle.ts changed lines, --concurrency 3, under .mutation-lock): 18 of 19 killed. The survivor is the pre-existing equivalent ndkVersion !== null guard.

Real expo prebuild (examples/expo)

  • scripts/check-expo-prebuild.sh: ok (clean prebuild with no level; --no-clean changes nothing).
  • The old block hand-inserted into debug and release, then --no-clean: both removed, and the file is byte-identical to a fresh prebuild.
  • An old block changed inside ('FULL'), then --no-clean: kept byte-identical, and the log shows the note.

Native upload proof (in #68; loopback stub only)

A Release + R8 build of the bare example with no debugSymbolLevel: uploadBugseeReleaseNative ran bugsee-cli 0.8.1 on merged_native_libs/release and uploaded 64 libraries, each build-id equal to its stripped APK copy. libbugsee_e2e_native.so, libappmodules, libreactnative, libjsi and libfbjni went up as dwarf.

🤖 Generated with Claude Code

…ions wrote

Bugsee Gradle plugin 4.0.8 uploads native symbols from the unstripped
libraries in merged_native_libs, whatever ndk.debugSymbolLevel says, so
the level is the app's own choice for Google Play.

- ensureAppAppliesPlugin no longer inserts the SYMBOL_TABLE block into the
  debug and release build types, on or off. A one-line build type, or a
  closer that shares its line, is therefore no longer refused.
- On every prebuild the block earlier versions wrote is removed, recognised
  by its marker and exact lines only. A level of the user's is never
  touched. A block the user changed inside is now the user's: it stays,
  and the prebuild log says so (it used to refuse with nativeCrashReporting
  off).
- The block text stays verbatim as the recognition fingerprint; its claim
  that libreactnative.so is pre-stripped is false (the Maven AAR ships it
  with DWARF), noted at the constant.
- @bugsee/cli 0.7.11 -> 0.7.12 (bugsee/bugsee-cli#61).
- Corpus: the oracle now forbids any Bugsee symbol-block line in the output
  and requires the debugSymbolLevel count to equal the user's own; new
  cases N01-N04 (old blocks in debug and release beside a user FULL, CRLF,
  user levels in both build types, the block quoted in a string).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…'s unstripped libraries

- README: a Native symbols (Android) section. Gradle plugin 4.0.8 uploads
  from merged_native_libs with bugsee-cli 0.8.1+, independent of
  debugSymbolLevel, which is the app's own choice for Google Play;
  libreactnative.so ships with DWARF, so React Native's own C++ gets
  file:line; the old symbol-table block goes on the next prebuild, a
  changed one stays as the user's. The bare manual setup drops its ndk
  block, the build-type anchors and the symbol-block refusal leave the
  plugin-edits text, and the CLI notes (0.7.12 for the wrapper, 0.8.1 for
  a pinned Gradle plugin CLI, bugsee/bugsee-cli#61) are kept.
- check-expo-prebuild.sh: the generated app/build.gradle has no
  debugSymbolLevel.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…osed

CI's merged plugin score fell to 96.62 (break 97) once the well-killed
symbol-block insertion code was removed. New tests close real gaps: the
user-NDK note on the off path, an own NDK line on line 1, the inner
indentation after earlier top-level code, the exact open-comment refusals
for the dependencies opener and the React plugin line, and plugins{ with
no or several spaces before the brace (or code before it). Focused Stryker
on those ranges: 44/44 killed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

@cursor cursor 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.

Review (c62f5ab)

Replaces #64 after #68 landed. Same approach, now on main @ 71d2492: the Expo plugin writes no debugSymbolLevel, and removeInsertedSymbolTable strips only the exact // bugsee-symbol-table: 7-line block earlier versions wrote.

Reviewed against ensureAppAppliesPlugin, the Groovy lexer, BugseePluginProps, baked plugin/build, the corpus oracle, and the 4.0.8 merged_native_libs pin — not the diff alone.

Findings

No P0–P3.

The removal matcher is conservative in the ways that matter:

  • Exact 7-line fingerprint at any indent, CRLF kept — gone on or off (nativeCrashReporting no longer inserts).
  • 4–6 matched lines (comments intact, body edited) stay as the user's, with CHANGED_SYMBOL_BLOCK_NOTE.
  • 1–3 stray marker comments drop; a quoted/string/comment copy is not a marker.
  • A level of the user's (defaultConfig, dotted, either build type, own ndk { }) is never touched. Corpus oracle: leftover debugSymbolLevel count equals the user's own, including N01–N04 and every option-set pair/chain.
  • One-line release { … } / a closer that shares its line is no longer refused (the insert path is gone).
  • ndkSymbolLevel is fully gone; plugin/build matches plugin/src; wrapper @bugsee/cli 0.7.12 is a published pin (Gradle plugin CLI floor 0.8.1 is separate and documented).

Residual (not defects)

  • Apps that relied on the injected SYMBOL_TABLE for Play native-debug-symbols.zip will ship NONE unless they set a level themselves. That is the stated product choice; Bugsee's upload under 4.0.8 does not use the zip.
  • An explicit gradlePluginVersion < 4.0.8 plus this removal would skip native upload (old plugin still reads the zip). Default is 4.0.8; --no-clean rewrites the pin.

CI

GitHub: lint/typecheck/unit SUCCESS; expo prebuild SUCCESS. Plugin mutation shards were still running at review time — not claimed here.

Verdict

  1. Overall risk: Low
  2. Merge recommendation: Approve
  3. Most important to fix: Nothing in this head
  4. Positive: Dropping insert-into-build-type also drops the old anchor refusals; the fingerprint + changed-inside note is the right migration off a leftover the user may have edited for Play.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

@krassx
krassx merged commit a572be9 into main Oct 11, 2026
50 checks passed
@krassx
krassx deleted the feat/ndk-full-symbols branch October 11, 2026 17:53
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