Skip to content

Task 13.4: add the Expo config plugin - #39

Merged
krassx merged 12 commits into
mainfrom
feat/phase-13-4
Oct 3, 2026
Merged

krassx merged 12 commits into
mainfrom
feat/phase-13-4

Conversation

@krassx

@krassx krassx commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds @bugsee/react-native/app.plugin.js. Prebuild inserts the Hermes source-map hook and the Archive dSYM post-action, applies the Bugsee Gradle plugin from Maven Central, and writes root android/bugsee.properties with an unprefixed app_token.
  • plugin.ndk.enabled=true is written only for a non-empty, non-placeholder token. nativeCrashReporting still adds bugsee-android-ndk by default.
  • examples/expo prebuild --clean completed, including CocoaPods.

Test plan

  • CI=1 yarn expo prebuild --clean in examples/expo (exit 0)
  • Plugin unit tests, 16 passed: real token writes app_token and plugin.ndk.enabled; the CI placeholder does not write the NDK flag; plugin.appToken is absent
  • CI green on this head

Made with Cursor

The plugin copies the bare app's source-map hook and Archive post-action, and writes bugsee.properties without turning NDK upload on for a placeholder token.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

Stale comment

Deep code review (f1bde1f)

Reviewed Task 13.4 against the Expo SDK 57 templates (expo-template-bare-minimum Gradle + the Bundle React Native code and images phase), the bare example’s 13.1/13.2 hooks, packages/react-native/android/build.gradle, and the package files list. Unit tests cover the string helpers; they do not exercise the plugin from an npm layout or a real prebuild. I did not run expo prebuild or Jest here (node_modules was not installed in this environment).

The Gradle edits match Expo 57’s Groovy templates (apply plugin: "com.facebook.react", buildscript then allprojects, pluginManagement without repositories). The Expo bundle-phase regex matches the decoded SDK 57 invocation. Placeholder-token handling matches the 13.3 ruling. Those parts look right.

The blocker is that withBugsee cannot resolve native versions once this package is installed from npm rather than as a workspace symlink.

Findings

  1. P1 — loadNativeVersions walk-up only works in this monorepo; the published tarball has no native-versions.json (see inline).
  2. P2 — Expo rewrite hardcodes ${SRCROOT}/../node_modules/@bugsee/react-native/scripts/bugsee-xcode.sh (see inline).
  3. P2 — nativeCrashReporting: false does not keep bugsee-android-ndk out of the APK (see inline).

Overall risk: High

Merge recommendation

Request changes. Do not merge until the plugin can run from a realistic node_modules/@bugsee/react-native tree (copy or bake native-versions.json). The path and NDK-opt-out issues should be fixed in the same pass or explicitly documented as known limits.

Most important issues to fix

  1. Ship versions with the plugin (package file, or bake android.sdk / android.gradlePlugin into plugin/build at compile time). Add a test that loads versions from a fake published layout, not from the repo root.
  2. Resolve bugsee-xcode.sh with NODE_BINARY + require.resolve('@bugsee/react-native/package.json'), same as Expo resolves react-native-xcode.sh.
  3. Make nativeCrashReporting: false actually drop the NDK artifact (or stop claiming it opts out of detection/size).

Also missing, not filed separately: no CI job runs examples/expo prebuild --clean, and android/ / ios/ are gitignored, so a template-shape change will not fail the gate. Design §13 still calls prebuild-then-build the proof this plugin survives regeneration.

Residual, out of this task’s listed Android surface: Expo app/build.gradle does not get the bare app’s hermesc-preserve-js.sh wrap, so Expo Android JS debug ids are still unwired. Fine for 13.4 if 13.5 is meant to catch it; it will fail Android Expo symbolication until someone adds it.

Positive observations

  • Maven Central is injected into pluginManagement (including the no-repositories Expo 57 shape), and the Gradle plugin is apply false on the root then applied on the app module — same constraint as the bare example.
  • Expo’s ENTRY_FILE / CLI_PATH / BUNDLE_COMMAND=export:embed are preserved; the phase is not replaced with the bare script.
  • plugin.ndk.enabled is omitted for the CI placeholder UUID; plugin.appToken is never written.
  • Scheme post-action copies the bare script and binds EnvironmentBuildable to the scheme’s own .app target.
  • Gradle version strings are allowlisted before interpolation.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread packages/react-native/plugin/src/native-versions.ts Outdated
Comment thread packages/react-native/plugin/src/bundle-phase.ts Outdated
Comment thread packages/react-native/plugin/src/index.ts
krassx and others added 3 commits October 3, 2026 02:46
A published install has no repo-root native-versions.json to walk to, the Expo bundle phase assumed a sibling node_modules, and nativeCrashReporting: false still left the wrapper NDK AAR on the APK.

Co-authored-by: Cursor <cursoragent@cursor.com>
A later prebuild with the option omitted or true kept the exclude a false run had written, so the NDK artifact stayed off the app.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep 13.3 and 13.4 checked.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

Stale comment

Deep code review (23420e2)

Re-reviewed Task 13.4 at 23420e2 (prior f1bde1f plus bake, NDK-exclude, and merge of main). Checked the plugin against Expo SDK 54/56/57 expo-template-bare-minimum (Groovy Gradle + the Bundle React Native code and images phase), react-native-xcode.sh's COMPOSE_SOURCEMAP_PATH / hermesc step after export:embed, packages/react-native/android/build.gradle, the package files list, and the three prior threads. Unit tests and examples/expo prebuild were not run here (node_modules is not installed).

All three findings from f1bde1f are fully_addressed:

  • loadNativeVersions reads plugin/build/native-versions.baked.json; the published-layout test loads 7.3.0 / 4.0.7 from a tree that has only plugin/build.
  • The Expo rewrite resolves bugsee-xcode.sh with $NODE_BINARY + require.resolve('@bugsee/react-native/package.json'). The SDK 54–57 invocation matches EXPO_XCODE_INVOCATION.
  • nativeCrashReporting: false writes configurations.configureEach { exclude group: 'com.bugsee', module: 'bugsee-android-ndk' } and a later on/omitted run removes that block. Gradle configuration-level exclude applies to the wrapper's transitive api and to a leftover direct implementation line.

Findings

  1. P2 — Archive dSYM post-action still only searches sibling / this-repo node_modules for bugsee-cli (see inline). Hoisted Expo monorepos miss it and exit 1.

Overall risk: Medium

Merge recommendation

Request changes. The plugin can now run from a published plugin/build tree, and the Gradle/Xcode string edits match Expo 57. Do not treat Archive dSYM upload as done for any app whose node_modules is not ios/../node_modules — the same class of miss you just fixed on the bundle phase.

Most important issues to fix

  1. After the script finds NODE_BINARY, resolve @bugsee/cli with require.resolve (same as the Expo bundle rewrite) and invoke that path. Drop the packages/react-native/node_modules walk; that only exists in this workspace.

Residual, not re-filed: no CI job runs examples/expo prebuild --clean. Expo app/build.gradle still does not get hermesc-preserve-js.sh, so Android JS debug ids stay unwired until 13.5. Separately, a published tarball still has no native-versions.json: BugseeReactNative.podspec reads ../../native-versions.json and android/build.gradle walks for it, so the first npm/EAS pod install / Gradle configure after a successful plugin prebuild will fail. That is pre-existing packaging, not a regression in this head; it is the next break on the path this PR is meant to open.

Positive observations

  • Bake + the fake published-layout test close the f1bde1f P1 for the plugin itself.
  • Expo 54/56/57 bundle-phase text is the same NODE_BINARY + require.resolve('react-native/...') invocation the regex rewrites; ENTRY_FILE / CLI_PATH / export:embed stay.
  • react-native-xcode.sh still runs hermesc and COMPOSE_SOURCEMAP_PATH after export:embed when the CLI does not pass --bytecode, so compose-then-inject.js is still on the compose path.
  • Stale NDK exclude is removed on a later on/omitted prebuild (3a49e4b).
  • plugin.ndk.enabled stays off for the CI placeholder; plugin.appToken is never written.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread packages/react-native/plugin/src/dsym-script.ts Outdated
krassx and others added 2 commits October 3, 2026 03:30
The Archive post-action only searched three node_modules directories, so a hoisted Expo app never found the CLI and the dSYM upload failed.

Co-authored-by: Cursor <cursoragent@cursor.com>
@bugsee/cli does not export its bin subpath, and an Xcode post-action does not run from the app directory.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

Stale comment

Deep code review (16f9cd6)

Re-reviewed Task 13.4 at 16f9cd6 (prior 23420e2 plus package-graph CLI resolve, then app-root paths). Checked the plugin against Expo SDK 57 expo-template-bare-minimum (Groovy settings.gradle / root and app build.gradle, single shared .xcscheme), RN 0.86 react-native-xcode.sh (hermesc + COMPOSE_SOURCEMAP_PATH after export:embed), @bugsee/cli@0.7.11 exports / bin, the wrapper api NDK line, and the four prior threads. Confirmed node --print puts the extra argument at process.argv[1]. Empirically ran require.resolve('@bugsee/cli/package.json', { paths: [appRoot] }) against hoisted, monorepo-hoist-to-root, pnpm-nested, and Yarn nmHoistingLimits: workspaces trees. Plugin unit tests and examples/expo prebuild were not run here (node_modules is not installed).

All four prior threads are fully_addressed:

  • Baked plugin/build/native-versions.baked.json; published-layout test loads 7.3.0 / 4.0.7 from a tree that has only plugin/build.
  • Expo bundle rewrite resolves bugsee-xcode.sh via $NODE_BINARY + require.resolve('@bugsee/react-native/package.json'). SDK 57's invocation still matches EXPO_XCODE_INVOCATION.
  • nativeCrashReporting: false writes the configuration exclude and a later on/omitted run removes it.
  • Default Yarn/npm hoist from apps/mobile now walks up from ${PROJECT_DIR}/.. and finds @bugsee/cli at the repo root. That was the 23420e2 scenario.

Findings

  1. P1 — Archive post-action still cannot resolve transitive @bugsee/cli (see inline). paths: [APP_ROOT] only walks up node_modules directories; it never enters @bugsee/react-native/node_modules. pnpm and this repo's Yarn nmHoistingLimits: workspaces layout both miss it and exit 1.

Overall risk: Medium

Merge recommendation

Request changes. The plugin can run from a published plugin/build tree, and the Gradle / Expo 57 Xcode string edits match the template. Do not treat Archive dSYM upload as done for any install that does not hoist @bugsee/cli to a directory on the walk up from the app root — including examples/expo in this workspace.

Most important issues to fix

  1. After NODE_BINARY is known, resolve @bugsee/react-native/package.json from the app root, then resolve @bugsee/cli (and the optional native package) with paths: [dirname(wrapper)]. That is how Node finds a package's own dependencies, and it is the same starting point the Expo bundle rewrite already uses. Keep process.argv[1] for the post-action cwd. Replace the string-only test with one that actually require.resolves from a nested tree (CLI only under @bugsee/react-native/node_modules) and from a hoisted tree.

Residual, not re-filed: no CI job runs examples/expo prebuild --clean. Expo app/build.gradle still does not get hermesc-preserve-js.sh, so Android JS debug ids stay unwired until 13.5. A published tarball still has no native-versions.json for BugseeReactNative.podspec / android/build.gradle; that is pre-existing packaging, not a regression in this head.

Positive observations

  • node --print "…" "$APP_ROOT" really does put the app root at process.argv[1] on Node 22; the extra-arg approach is correct.
  • @bugsee/cli@0.7.11 exports ./package.json and uses an object bin, so reading .bin['bugsee-cli'] is the right workaround for the unexported bin subpath.
  • Expo 57 pluginManagement has no repositories and balanced { paths: […] } strings inside providers.exec; ensureMavenCentral still closes the block correctly and injects Maven Central.
  • Root plugins { id … apply false } lands after buildscript and before allprojects / apply plugin: "expo-root-project", which is valid Gradle and matches the bare app.
  • react-native-xcode.sh on 0.86 still runs hermesc and COMPOSE_SOURCEMAP_PATH after export:embed when Hermes is on, so compose-then-inject.js is still on the iOS compose path.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread packages/react-native/plugin/src/dsym-script.ts
Yarn and pnpm nest the CLI under @bugsee/react-native, so an app-root require.resolve misses it and the Archive post-action exits 1.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

Stale comment

Deep code review (c92ce65)

Re-reviewed Task 13.4 at c92ce65 (wrapper-directory CLI resolve). Checked the plugin against Expo SDK 57 expo-template-bare-minimum (Groovy settings.gradle / root and app build.gradle, backtick $NODE_BINARY bundle invocation, empty ArchiveAction), RN wrapper api NDK line, Gradle Configuration.exclude contract, and the five prior threads. Ran the compiled transforms in Node: Expo 57 pluginManagement still gets a balanced repositories block; the SDK 57 bundle-phase text matches EXPO_XCODE_INVOCATION (one /bin/bash); ensureAppAppliesPlugin(on → off) keeps the implementation line. Plugin unit tests and examples/expo prebuild were not run here (node_modules is not installed).

All five prior threads are fully_addressed:

  • Baked plugin/build/native-versions.baked.json; published-layout test loads 7.3.0 / 4.0.7 from a tree that has only plugin/build.
  • Expo bundle rewrite resolves bugsee-xcode.sh via $NODE_BINARY + require.resolve('@bugsee/react-native/package.json'). SDK 57's invocation still matches EXPO_XCODE_INVOCATION.
  • First-run nativeCrashReporting: false writes the configuration exclude (wrapper api is transitive, so that path is covered). Off→on still drops a stale exclude.
  • Archive post-action resolves @bugsee/react-native from ${PROJECT_DIR}/.., then @bugsee/cli from that wrapper directory, then the Darwin package from the CLI directory. resolves a nested @bugsee/cli from the wrapper and a hoisted one from the app root actually require.resolves both trees.

Findings

  1. P2 — nativeCrashReporting: false on a later prebuild does not remove the implementation line a default-on run wrote (see inline). Configuration-level exclude does not apply to that direct dependency, so the NDK AAR stays on the APK.

Overall risk: Medium

Merge recommendation

Request changes. The plugin can run from a published plugin/build tree, Expo 57 Gradle/Xcode string edits match the template, and Archive CLI resolve now covers nested Yarn/pnpm layouts. Do not treat nativeCrashReporting: false as done for any app that already ran a default-on prebuild — that is the same incremental path 3a49e4b fixed in the other direction.

Most important issues to fix

  1. When ndkVersion is null, strip implementation "com.bugsee:bugsee-android-ndk:…" (the line this plugin inserts) before writing the exclude. Add the inverse of removes a previous NDK exclude when native crash reporting is on: start from a file that already has that implementation line.

Residual, not re-filed: no CI job runs examples/expo prebuild --clean. Expo app/build.gradle still does not get hermesc-preserve-js.sh, so Android JS debug ids stay unwired until 13.5. A published tarball still has no native-versions.json for BugseeReactNative.podspec / android/build.gradle; that is pre-existing packaging, not a regression in this head.

Positive observations

  • Nested @bugsee/cli is resolved from the wrapper directory; the new test fails paths: [appRoot] on that tree and passes the script source.
  • Expo 57 pluginManagement has no repositories and balanced { paths: […] } strings inside providers.exec; ensureMavenCentral still closes the block correctly and injects Maven Central.
  • SDK 57's bundle-phase invocation is still the NODE_BINARY + require.resolve('react-native/…') form the regex rewrites; ENTRY_FILE / CLI_PATH / export:embed stay; a second bugsee-xcode.sh is not appended.
  • plugin.ndk.enabled stays off for the CI placeholder; plugin.appToken is never written.
  • Root plugins { id … apply false } still lands after buildscript and before allprojects / apply plugin: "expo-root-project".
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread packages/react-native/plugin/src/gradle.ts Outdated
A configuration exclude only removes the wrapper's transitive api, so an implementation line left by an earlier prebuild still put the NDK AAR on the APK.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

Stale comment

Deep code review (872ab71)

Reviewed Task 13.4 against the surrounding 13.1/13.3 bare-app hooks, design §11, and the Expo SDK 57 expo-template-bare-minimum Gradle/Xcode files. Ran the compiled plugin helpers on those templates (not yarn test / not a full expo prebuild in this environment).

Prior threads on this PR (baked native pins, Expo require.resolve for bugsee-xcode.sh, nested @bugsee/cli resolve, NDK exclude ↔ direct implementation round-trip) are addressed on this head.

Findings

  1. P1 — Expo Android never gets the 13.1/13.3 app/build.gradle contract. The plugin applies com.bugsee.android.gradle and the NDK artifact, then stops. It does not set debugSymbolLevel 'SYMBOL_TABLE' (13.3: AGP defaults to NONE, native upload skips) and does not install hermesc-preserve-js.sh + the createBundle*JsAndAssets inject (13.1). iOS inject/dSYM are present; Android JS debug IDs and NDK symbol upload are not. packages/react-native/plugin/src/index.ts:66-69
  2. P2 — insertDsymPostAction emits a second <PostActions> sibling when Archive already has one, instead of appending an ExecutionAction. Stock Expo schemes are empty, so the example prebuild does not catch this. packages/react-native/plugin/src/scheme.ts:50-52

Overall risk: High

Expo iOS prebuild can look correct while Android release symbolication (JS and native) is silently a no-op.

Merge recommendation: Do not merge until the Android app/build.gradle hooks from 13.1/13.3 are applied (and tested) by this plugin.

Most important to fix

  1. debugSymbolLevel + Hermes preserve/inject on the Expo app module, resolved via require.resolve (not ../../node_modules), with an Expo 57 template fixture.
  2. Merge into an existing Archive PostActions rather than inserting a sibling block.

Notes, not blocking

  • No CI job runs examples/expo prebuild --clean (design §13). Unit tests cover string rewrites; they would not have caught finding 1.
  • uploadSymbols: false does not strip an already-inserted post-action on incremental prebuild (same class as the NDK leftover that 872ab71 fixed). Secondary to the missing Android hooks.

What looks solid

  • native-versions.baked.json is what a published install can actually read.
  • Expo 57 pluginManagement has no repositories {}; ensureMavenCentral inserts portal + Google + Maven Central, which is the right replacement for the implicit portal.
  • plugins { id 'com.bugsee.android.gradle' … apply false } lands after buildscript and before allprojects / apply plugin on the Expo 57 root build.gradle (valid Gradle).
  • Expo bundle-phase regex matches the SDK 57 invocation and keeps export:embed / ENTRY_FILE / CLI_PATH.
  • Nested vs hoisted @bugsee/cli resolve is actually executed in the unit test, not only asserted as source text.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread packages/react-native/plugin/src/index.ts
Comment thread packages/react-native/plugin/src/scheme.ts Outdated
The config plugin was applying the Gradle plugin without SYMBOL_TABLE or the Hermes preserve and finish hooks, and a second Archive PostActions sibling is not a valid scheme.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

Stale comment

Deep code review (a71ec6e)

Reviewed Task 13.4 against the 13.1/13.3 bare-app hooks, design §11, and the Expo SDK 57 expo-template-bare-minimum Gradle/Xcode files. Ran the compiled plugin helpers on those templates (not yarn test / not a full expo prebuild; node_modules is not installed here).

All eight prior threads are fully_addressed: baked native pins, Expo bugsee-xcode.sh resolve, NDK exclude + leftover implementation strip, nested @bugsee/cli resolve, Android SYMBOL_TABLE / Hermes finish hook, and Archive PostActions merge.

Findings

  1. P2 — Replacing Expo 57's hermesCommand with hermesc-preserve-js.sh drops the require.resolve('hermes-compiler', { paths: [react-native] }) lookup the template used. The wrapper only checks $PWD/node_modules/hermes-compiler/…. A nested/pnpm/Yarn-workspace install fails createBundleReleaseJsAndAssets (see inline).
  2. P2 — uploadSymbols: false on a later prebuild does not remove the Archive post-action a default-on run wrote (see inline).

Overall risk: Medium

The iOS hooks and the Gradle plugin/NDK/symbol-table edits look correct on a stock SDK 57 tree. Android JS debug IDs still depend on a hermesc lookup that Expo already solved and this commit undoes.

Merge recommendation

Request changes. Do not treat Android JS symbolication as done for pnpm or Yarn-workspace Expo apps — assembleRelease dies in createBundle*JsAndAssets with bugsee: hermesc binary not found instead of compiling with the binary Expo's template would have found.

Most important issues to fix

  1. Resolve hermesc the way the Expo 57 template does (require.resolve('hermes-compiler/package.json', { paths: [require.resolve('react-native/package.json')] }) + hermesc/%OS-BIN%/hermesc), not via $PWD/node_modules/hermes-compiler. Teach find_hermesc that, or bake BUGSEE_REAL_HERMESC from the same expression. Add the inverse of the nested-CLI test: a tree where node_modules/hermes-compiler is missing and the package lives under react-native.
  2. When uploadSymbols === false, strip an ExecutionAction whose scriptText contains xcode post-action (and drop an empty leftover PostActions). Start from a scheme this plugin already edited.

Residual, not re-filed: no CI job runs examples/expo prebuild --clean. A published tarball still has no native-versions.json for the podspec / android/build.gradle walk; that is pre-existing packaging.

Positive observations

  • Expo 57 pluginManagement has no repositories and balanced { paths: […] } strings inside providers.exec; ensureMavenCentral still closes the block and injects Maven Central.
  • plugins { id 'com.bugsee.android.gradle' … apply false } lands after buildscript and before allprojects / apply plugin: "expo-root-project".
  • SDK 57's bundle-phase invocation still matches EXPO_XCODE_INVOCATION; ENTRY_FILE / CLI_PATH / export:embed stay; a second bugsee-xcode.sh is not appended.
  • debugSymbolLevel 'SYMBOL_TABLE' is written on both build types; a hand-written ndk block is left alone; nativeCrashReporting: false removes only the marked block.
  • Archive already-has-PostActions now gets one container holding both actions.
  • Nested @bugsee/cli resolve is actually executed in the unit test, not only asserted as source text.
  • plugin.ndk.enabled stays off for the CI placeholder; plugin.appToken is never written.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread packages/react-native/plugin/src/gradle.ts
Comment thread packages/react-native/plugin/src/index.ts Outdated
Expo resolves hermes-compiler from the react-native package, which a sibling node_modules walk misses. uploadSymbols false also has to remove an Archive post-action left by an earlier prebuild.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

Stale comment

Deep code review (e9ca1d0)

Reviewed Task 13.4 against the 13.1/13.3 bare-app hooks, design §11, Expo SDK 54 and 57 expo-template-bare-minimum Gradle files, and react-native@0.81.4 / 0.83.1 package manifests. Ran find_hermesc against a 0.81-shaped tree (not yarn test / not a full expo prebuild; node_modules is not installed here).

All ten prior threads are fully_addressed: baked native pins, Expo bugsee-xcode.sh resolve, NDK exclude + leftover implementation strip, nested @bugsee/cli resolve, Android SYMBOL_TABLE / Hermes finish hook, Archive PostActions merge, nested hermes-compiler lookup, and uploadSymbols: false leftover-action strip.

Findings

  1. P1 — find_hermesc still cannot see RN 0.81 / Expo SDK 54's shipped sdks/hermesc binary after the plugin overwrites that working hermesCommand (see inline).

Overall risk: High

SDK 57 prebuild and the nested-compiler test can look correct while an SDK 54 Android release dies in createBundle*JsAndAssets.

Merge recommendation

Request changes. Do not treat Android JS symbolication as done for the declared 0.81 floor — assembleRelease prints bugsee: hermesc binary not found on the layout Expo 54's template already solved.

Most important issues to fix

  1. Resolve react-native/sdks/hermesc/%OS-BIN%/hermesc from require.resolve('react-native/package.json') after the hermes-compiler lookup. Add a 0.81 fixture (shipped sdks/hermesc, no hermes-compiler package) that runs the wrapper.

Residual, not re-filed: no CI job runs examples/expo prebuild --clean. A published tarball still has no native-versions.json for the podspec / android/build.gradle walk; that is pre-existing packaging. @expo/config-plugins is pinned ~57.0.9 while the wrapper floor is SDK 54.

Positive observations

  • Nested hermes-compiler under react-native is actually executed in the unit test, not only asserted as source text.
  • uploadSymbols: false now removes the Bugsee Archive ExecutionAction and drops an empty leftover PostActions; a sibling action stays.
  • Expo 57 pluginManagement has no repositories and balanced { paths: […] } strings inside providers.exec; ensureMavenCentral still closes the block and injects Maven Central.
  • SDK 54 and 57 bundle-phase invocations still match EXPO_XCODE_INVOCATION; ENTRY_FILE / CLI_PATH / export:embed stay.
  • Nested vs hoisted @bugsee/cli resolve is actually require.resolved in the unit test.
  • plugin.ndk.enabled stays off for the CI placeholder; plugin.appToken is never written.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread packages/react-native/scripts/hermesc-preserve-js.sh
Expo SDK 54 has no hermes-compiler package. After that resolve misses, the wrapper uses sdks/hermesc beside react-native, while newer SDKs still prefer hermes-compiler.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

Stale comment

Deep code review (ec79c1f)

Reviewed Task 13.4 at ec79c1f against the 13.1/13.3 bare-app hooks, design §11, Expo SDK 54 and 57 expo-template-bare-minimum Gradle/Xcode files, and RN 0.81.4 / 0.86.3 BundleHermesCTask + detectOSAwareHermesCommand. Ran find_hermesc against a 0.81-shaped tree and a nested-compiler+shipped tree (not yarn test / not a full expo prebuild; node_modules is not installed here).

All eleven prior threads are fully_addressed. The e9ca1d0 P1 is closed by this commit: after hermes-compiler misses, the wrapper uses sdks/hermesc/%OS-BIN%/hermesc beside require.resolve('react-native/package.json'). Reproduced: 0.81 tree with executable sdks/hermesc/linux64-bin/hermesc and no hermes-compiler → exit 0, recorded path is the shipped binary. A tree with both layouts still prefers hermes-compiler. The new unit test actually runs the script.

Checked the surrounding contract this plugin now reapplies:

  • Expo 54 hermesCommand is the sdks/hermesc Groovy line this wrapper replaces; Expo 57 is the hermes-compiler line. Both are single-line assignments rewriteHermesCommand matches.
  • RN 0.81/0.86 detectOSAwareHermesCommand accepts a non-blank hermesCommand as-is (no %OS-BIN% required), so the .sh path is not rejected.
  • BundleHermesCTask.getHermescCommand uses -out ${bundle}.hbc then the JS bundle as a separate argument, so the wrapper’s skip--out scan still finds the input under /generated/assets/.
  • SDK 54 root build.gradle still has buildscript then allprojects / apply plugin; plugins { … apply false } lands after buildscript.
  • SDK 54 settings.gradle pluginManagement still has no repositories and balanced { paths: […] } strings; ensureMavenCentral still closes the block.
  • SDK 54 bundle-phase invocation still matches EXPO_XCODE_INVOCATION; ENTRY_FILE / CLI_PATH / export:embed stay.

Findings

No new P0–P3.

Overall risk: Low

Merge recommendation

Safe once CI is green on this head. Plugin correctness for the declared 0.81 / SDK 54 floor is no longer blocked. At review time rn compat (0.83) had already failed in 22s; that job runs check-rn-compat.sh and does not read plugin/. The JS unit/mutation job was still running.

Most important issues to fix

None on the plugin path. Do not treat 13.5 (a release build whose JS stack symbolicates) as done — design §13 still calls that the only proof of the whole chain.

Residual, not re-filed: no CI job runs examples/expo prebuild --clean. A published tarball still has no native-versions.json for the podspec / android/build.gradle walk; that is pre-existing packaging. @expo/config-plugins is pinned ~57.0.9 while expo@54 uses ~54.0.0.

Positive observations

  • The 0.81 shipped-binary path and the nested-compiler preference are both executed, not only asserted as source text.
  • uploadSymbols: false still removes the Bugsee Archive ExecutionAction and drops an empty leftover PostActions; a sibling action stays.
  • Nested vs hoisted @bugsee/cli resolve is still actually require.resolved in the unit test.
  • plugin.ndk.enabled stays off for the CI placeholder; plugin.appToken is never written.
  • Expo 54/57 Gradle string edits still match the templates; debugSymbolLevel 'SYMBOL_TABLE' is written on both build types and a hand-written ndk block is left alone.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

grep -q closes the pipe at the first match, so grep -v dies with SIGPIPE and a real assignment is reported as a miss. Read the filtered file to completion instead.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

Deep code review (11e090b)

Re-reviewed Task 13.4 at 11e090b against the 13.1/13.3 bare-app hooks, design §11, Expo SDK 54 and 57 expo-template-bare-minimum Gradle/Xcode templates, and the eleven prior findings.

Prior threads

All eleven remain fully addressed. Plugin sources, baked pins, NDK exclude/implementation round-trip, Archive PostActions insert/remove, nested @bugsee/cli resolve, and find_hermesc (hermes-compiler first, then RN 0.81 sdks/hermesc) are unchanged from ec79c1f.

SDK 54 and 57 iOS bundle phases still match EXPO_XCODE_INVOCATION (same `$NODE_BINARY` --print … react-native-xcode.sh line). Root android/build.gradle is still buildscript then allprojects, so the plugins { id 'com.bugsee.android.gradle' … apply false } insert after buildscript is valid Gradle. SDK 54 hermesCommand is still the single-line sdks/hermesc/%OS-BIN%/hermesc path that ec79c1f taught the wrapper to find.

New commit

11e090b stops assigns_handle from using grep -q on the comment-filter pipe. Under set -o pipefail, grep -q exits at the first match and closes the pipe; grep -v then dies with SIGPIPE, so a real __internalInstanceHandle assignment near the start of a large file is reported as a miss. Reproduced locally on an 80k-line file with the assignment on line 1: old pipeline exit 141, grep -E … >/dev/null exit 0. A comparison (===) still exits 1. rn compat (0.81) already passed on this head.

New findings

None (no P0–P3).

Residual (not re-filed)

  • No CI job runs examples/expo prebuild --clean.
  • The published tarball still has no repo-root native-versions.json for the podspec / wrapper android/build.gradle walk (pre-existing packaging; the plugin itself reads the baked copy).
  • @expo/config-plugins is pinned ~57.0.9 while the wrapper floor is SDK 54. Nested install is the likely layout; not reproduced as a prebuild break.

Verdict

  1. Overall risk: Low
  2. Merge recommendation: Safe once CI is green
  3. Most important issues to fix: None on this head
  4. Positives: The Expo regex still targets only the react-native-xcode.sh invocation so ENTRY_FILE / CLI_PATH / export:embed stay. Incremental prebuild undoes NDK exclude, leftover implementation, and the Archive post-action. The pipefail guard is covered by a unit test that actually runs the extracted function under pipefail.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

@krassx
krassx merged commit 7eaf321 into main Oct 3, 2026
12 checks passed
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