Skip to content

Task 13.5: match a release bundle's debug id to the composed map - #43

Merged
krassx merged 2 commits into
mainfrom
feat/phase-13-5
Oct 3, 2026
Merged

krassx merged 2 commits into
mainfrom
feat/phase-13-5

Conversation

@krassx

@krassx krassx commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • A Hermes release build on the WOD_LX1 reports the same debug id the composed source map carries: 3c110b23-2416-5bc6-acac-e35ac7e69aa6 for index.android.bundle.
  • debug-files upload is still not executed. The Task 13.5 checkbox stays open because the dashboard has not symbolicated a frame. No Bugsee app was created. The example credentials are the CI placeholder.

Test plan

  • WOD_LX1 AMRJCP4718402860, release, E2E_RELEASE=1: runtime debug_ids equals the composed map's debug_id
  • iPhone XS was offline and was not run
  • iOS Simulator was not run: beta3 compiles logException out there, so a Release simulator build does not retain debug_ids
  • Dashboard symbolication, once a token for an existing app is available

Made with Cursor

Gradle 9 had removed Project.exec, so the inject hook never reached that map. The dashboard symbolication half stays open.

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 review — Task 13.5 local half (Gradle 9 inject + composed debug id)

Reviewed 5cd1209 against surrounding 13.1/13.4 code (hermes-sourcemaps.js, ensureHermesHooks, debugIds.ts, bugsee-xcode.sh, existing exception e2e). The production change is the Gradle 9 Project.exec replacement so hermes-sourcemaps.js finish actually runs after compose. The new exc-map-id path correctly leaves the inject stub alone. The dashboard / debug-files upload half is still open, and the plan checkbox stays unchecked — that matches the evidence.

I did not run unit tests or a device e2e in this environment.

Findings

P2 — Expo plugin will not migrate an existing project.exec hook

  • Location: packages/react-native/plugin/src/gradle.ts (ensureHermesHooks, used with the new ExecOperations line)
  • Problem: ensureHermesHooks returns the file unchanged once PRESERVE_REFUSAL is present. A 13.4 prebuild already contains that marker and project.exec. Re-running the config plugin (including expo prebuild without --clean) never rewrites the exec call. ensureAppAppliesPlugin(next) === next in plugin.test.ts locks that write-once behavior in.
  • Impact: The Gradle 9 inject fix is what this PR exists to ship for customers. The bare example was patched by hand; Expo apps that already have the 13.4 hook keep the removed API. createBundle*JsAndAssets then throws MissingMethodException on project.exec, so the composed map is never injected and a release JS stack cannot join the uploaded map.
  • Scenario: Prebuild with 13.4 on RN 0.87 / Gradle 9.4 (this example's wrapper). Upgrade @bugsee/react-native to this commit. Run expo prebuild without --clean. android/app/build.gradle still has project.exec. assembleRelease hits the finish doLast (preserved.isFile() is true) and fails before hermes-sourcemaps.js finish.
  • Fix: When the marker is already present, rewrite only the Bugsee finish-hook project.exec { (the 20-space line inside that doLast) to the ExecOperations call. Do not globally replace project.exec in the whole file — bundleTask is not in scope elsewhere. Add a test that starts from a 13.4 hook and asserts the exec line changed. Prefer capturing ExecOperations at configureEach time (objects.newInstance / injected interface) rather than bundleTask.services.get inside doLast; that is the public Gradle 9 replacement.

P2 — iOS device suite is enabled but the composed map path is Android-only

  • Location: examples/bare/e2e/composed-debug-id.test.ts (composedMapPath)
  • Problem: describeReleaseProof runs on iOS device, but the default map is android/app/build/generated/sourcemaps/react/release/index.android.bundle.map. iOS writes $CONFIGURATION_TEMP_DIR/main.jsbundle.composed.map (bugsee-xcode.sh). BUGSEE_COMPOSED_MAP exists, but nothing requires it on iOS.
  • Impact: The iOS half of this proof cannot succeed as written. You either throw on a missing Android map, or compare the iPhone runtime UUID to a leftover Android UUIDv5 (different bundle content → different id) and fail for the wrong reason.
  • Scenario: E2E_RELEASE=1 E2E_PLATFORM=ios E2E_IOS_TARGET=device on the XS, as the describe gate allows. beforeAll reads the Android path first, before any launch.
  • Fix: Skip iOS unless BUGSEE_COMPOSED_MAP is set, or persist the iOS composed map to a stable checkout path during the Xcode hook and default to that when ON_IOS.

Overall risk: Medium

The example's ExecOperations lookup did what 13.5 needed on WOD_LX1 (debug_ids {"index.android.bundle":"3c110b23-2416-5bc6-acac-e35ac7e69aa6"} matching the composed map). The customer-facing Expo hook does not apply that same fix to trees that already have the 13.4 snippet. iOS is opted in without a map it can read.

Merge recommendation

Request changes. Do not merge until the plugin rewrites an existing project.exec finish hook (with a test). The iOS default path should not run against the Android map.

Most important issues to fix

  1. Migrate the already-written Hermes finish hook off project.exec in ensureHermesHooks.
  2. Stop the iOS device describe from using the Android composed map unless an override is provided.

What looks good

  • Replacing Project.exec is the correct Gradle 9 fix; all finish arguments are already absolute, so working-directory differences vs Project.exec do not matter here.
  • exc-map-id skips registerDebugIds, which would have replaced the inject stub and hidden the real UUID. Launch still goes through startRun (URI on Android, launch args on iOS), so a release binary can select the scenario even though e2e-scenario.json is baked in.
  • expect(run.dev).toBe(false), airplane mode, nonce-scoped reason, and debug_id/debugId equality on the map are the right local-half checks.
  • The plan note is honest that upload and dashboard symbolication were not done.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread packages/react-native/plugin/src/gradle.ts
Comment thread examples/bare/e2e/composed-debug-id.test.ts
A 13.4 file that already had the preserve marker stayed on the API Gradle 9 removed. An iOS device proof now waits for BUGSEE_COMPOSED_MAP instead of reading the Android map.

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 review — Task 13.5 local half (181a692)

Re-reviewed 181a692 against surrounding 13.1/13.4 code (hermes-sourcemaps.js finishAfterCompose, ensureHermesHooks, debugIds.ts / payload.ts, bugsee-xcode.sh, exceptions.test.ts payloadOf, startRun URI/launch-args). Both findings from 5cd1209 are fixed. The dashboard / debug-files upload half is still open by design; the plan checkbox stays unchecked.

This environment has no node_modules, so plugin unit tests were not executed here. At posting time GitHub CI on this HEAD was still running (lint, typecheck, unit, mutation pending).

Prior findings

P2 Expo project.exec migration — fully addressed. migrateFinishHookExec scopes the replace to the Bugsee bundleTask.doLast that contains "finish" after PRESERVE_REFUSAL, so a 13.4 hook is rewritten and a sibling project.exec is left alone. The new fixture starts from that stale line and asserts a second apply is a no-op. The lookup stays bundleTask.services.get(ExecOperations); that is the call the WOD_LX1 Gradle 9.4.1 release actually ran.

P2 iOS device vs Android map — fully addressed. describeReleaseProof now requires BUGSEE_COMPOSED_MAP on iOS device. Without it the suite is skipped and does not open index.android.bundle.map.

Findings

No new P0–P3. I looked for silent migration misses (brace matching vs the generated snippet, "finish" region, CRLF), ExecOperations cwd (all finish argv paths are already absolute), exc-map-id replacing the inject stub, awaitBundles / payloadOf vs the existing exception e2e, iOS afterAll ( clearBundles → clearIosBundles → terminateIosApp), and release steering (startRun still uses the Android URI / iOS launch args). None of those produced a credible failure on this HEAD.

Overall risk: Low

The production change is the Gradle 9 Project.exec replacement plus an upgrade rewrite for trees that already have the 13.4 hook. Android local half was device-proven on WOD_LX1 (debug_ids {"index.android.bundle":"3c110b23-2416-5bc6-acac-e35ac7e69aa6"} matching the composed map). iOS remains opt-in via BUGSEE_COMPOSED_MAP; that is documented, not a false failure.

Merge recommendation

Safe to merge once CI on 181a692 is green. Do not treat the 13.5 checkbox as done: upload and dashboard symbolication are still open.

Most important issues to fix

None on this HEAD.

What looks good

  • Replacing Project.exec is the correct Gradle 9 fix; finish arguments are already absolute, so working-directory differences vs Project.exec do not matter here.
  • The migration is deliberately narrow (^([ \t]*)project\.exec \{$ inside that doLast only).
  • exc-map-id skips registerDebugIds, which would have replaced the inject stub and hidden the real UUID. Launch still goes through startRun (URI on Android, launch args on iOS), so a release binary can select the scenario even though e2e-scenario.json is baked in.
  • expect(run.dev).toBe(false), airplane mode, nonce-scoped reason, and debug_id/debugId equality on the map are the right local-half checks.
  • The plan note is honest that upload and dashboard symbolication were not done.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

@krassx
krassx merged commit 93ae292 into main Oct 3, 2026
16 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