Generate example/android via Expo prebuild + with-android-tests plugin#9
Closed
gmaclennan wants to merge 2 commits into
Closed
Conversation
5 tasks
gmaclennan
added a commit
that referenced
this pull request
Apr 21, 2026
Revert five files to origin/main state. They're re-added on the Android PR (#9), which is where they belong: - .github/workflows/android-tests.yml — Node 20 upgrade, emulator snapshot-restore crash fix (avoid `input keyevent 82`), test timeout, gradle verbose flag - android/src/main/assets/nodejs-project/index.js — late-client replay of started/ready events (the iOS copy at ios/nodejs-project/ keeps this fix; the Android-bundled copy is Android's to maintain) - android/src/main/assets/nodejs-project/lib/control-rpc.js — restore the file that was deleted as part of Android cleanup - example/android/.../ServiceLifecycleTest.kt — PID-stability check in waitForServiceRunning - example/android/.../ShutdownPathTest.kt — same PID-stability check Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
These five files carried Android-specific changes that had been authored on the iOS branch but logically belong to this PR. PR #6 has reverted them to origin/main state; the next commit re-applies them here so each change is explicitly owned by the Android PR rather than inherited through the shared merge-base. This intermediate commit restores the origin/main content so the re-apply diff is meaningful. No user-visible behavior changes between this commit and the next one — they cancel each other for these paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
These changes had been authored on the iOS branch but are Android-only; PR #6 has reverted them so this PR can own them explicitly. Paired with the previous "rewind" commit so the diff is meaningful against the post-revert origin/main. - .github/workflows/android-tests.yml — Node 18 → 20 upgrade; replace emulator-runner's `input keyevent 82` (which races snapshot-restore and crashes the emulator) with `settings put` to disable animations; add per-test `-i` gradle flag and a 15-minute timeout - android/src/main/assets/nodejs-project/index.js — track a `readinessPhase` in the state IPC server and replay `started`/`ready` to late-connecting clients (same fix already applied to the iOS copy at ios/nodejs-project/index.js) - android/src/main/assets/nodejs-project/lib/control-rpc.js — delete unused stub - example/tests/android/ServiceLifecycleTest.kt — add a PID-stability check to `waitForServiceRunning` so a `:ComapeoCore` process that dies at startup is surfaced instead of letting the test hang - example/tests/android/ShutdownPathTest.kt — same PID-stability check Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9baf548 to
68863c4
Compare
Member
Author
|
see #10 instead |
gmaclennan
added a commit
that referenced
this pull request
May 6, 2026
Addresses the high- and medium-priority issues from the review subagent's pass over Phase 1+2a+2b: Boot transaction lifecycle (was: review #1, #15) - applyAndEmit now closes bootTx and drains in-flight phase spans on STOPPING / STOPPED transitions too — not just STARTED / ERROR. stop()-from-STARTING transitions to STOPPING (rule 3 of deriveLifecycleState) and bypassed both terminals; destroy() forcing STOPPED-via-stopRequested did the same. Status mapped: STARTED→ok, ERROR→ internal_error, STOPPING/STOPPED→cancelled. - startBootTransaction now passes a TransactionContext carrying TracesSamplingDecision(true, 1.0). The previous TransactionOptions-only setup didn't actually force sampling, so with the SDK default tracesSampleRate=0.0 the boot transaction was dropped before reaching the wire. SentryConfig misconfig handling (was: review #3) - Both Kotlin and Swift readers used to crash on (DSN-set, environment-missing) — meant to be "fail loud" but a stale prebuild from before the validation was added would crash every cold start with no recovery. Now log loud (System.err on Android since android.util.Log isn't mocked on JVM tests; NSLog on iOS) and return null (Sentry off). Updated test renamed to assert "returns null, doesn't throw". Span op/description ordering (was: review #19) - transaction.startChild(op, description) — op is the indexed dashboard column. Was passing ("boot", "boot.<phase>"), swapped to ("boot.<phase>", human-readable description) so the dashboard groups by the phase taxonomy that matches the bench backend's boot-spans.js helper. Plugin idempotency (was: review #7) - Previously, dropping `props.sentry` from the plugin registration left stale meta-data / plist entries from a previous prebuild (with `expo prebuild --no-clean`). Plugin now passes through a no-Sentry cleanup mod that strips every key it owns; consumer-owned keys (e.g. io.sentry.* set by @sentry/react-native's plugin) are untouched. messageerror payload truncation (was: review #8) - src/sentry.ts now truncates the wrapped error message to 256 chars before forwarding to captureException. The control-frame parser surfaces offending input verbatim, which can include arbitrary bytes from a corrupted frame — truncating keeps Sentry events small and readable. IPC + SEND_ERROR_NATIVE breadcrumbs/events (was: review #9, #10) - NodeJSIPC's onConnectionStateChange callback wired in the FGS-side controlIpc construction; emits comapeo.ipc breadcrumbs at info (warning on Error). Per §7.4.5. - SEND_ERROR_NATIVE_TIMEOUT_MS firing now captures a level=warning event with timeout:errorNativeForward tag. Per §7.4.4. Logging swallowed surprises (was: review low-priority) - SentryFgsBridge's empty `catch (t: Throwable) {}` blocks now Log.w so debug builds notice swallowed bridge / SDK bugs. Post-init bridge tests (was: review #6) - New SentryFgsBridgeImplTest spins up a real Sentry hub via the cross-platform Sentry.init(SentryOptions) path with an in-memory ITransport. Covers: addBreadcrumb (no envelope on its own), captureException + captureMessage (envelope enqueued), startBootTransaction with global tracesSampleRate=0.0 (must still reach transport thanks to the TracesSamplingDecision override — regression test for the §15 bug above), boot span lifecycle, finishSpan with cancelled status, unknown level fallback to INFO. All Sentry-related tests pass: 25 cases across SentryConfigTest (8), SentryFgsBridgeTest (10), SentryFgsBridgeImplTest (7). Verified locally: - npm run lint clean - npx tsc --noEmit clean - ./gradlew :comapeo-core-react-native:testDebugUnitTest passes - ./gradlew :comapeo-core-react-native:compileDebugKotlin succeeds with sentry-android on the compile classpath
17 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
All Android-specific work for this repo, separated out of the iOS support PR (#6).
1. Generate
example/android/via Expo prebuild + config pluginexample/android/tree so Expo SDK upgrades can regenerate it cleanly.example/plugins/with-android-tests/config plugin mirrorswith-ios-tests: copies the Kotlin instrumented-test sources fromexample/tests/android/intoapp/src/androidTest/at prebuild time, and patchesapp/build.gradlewith the AndroidJUnit test runner andandroidTestImplementationdeps viamergeContents(idempotent — safe on re-prebuild)..github/workflows/android-tests.yml) and the locale2e/run-instrumented-tests.shrunner now callnpx expo prebuild --platform androidbefore Gradle. The runner is restructured so prebuild runs once in a shared-setup block rather than once per path.2. Android CI / test / nodejs-project changes (moved from PR #6)
These changes were originally authored on the iOS branch but are Android-only; PR #6 has reverted them so this PR can own them explicitly.
.github/workflows/android-tests.yml— Node 18 → 20 upgrade; replace emulator-runner'sinput keyevent 82(which races snapshot-restore and crashes the emulator) withsettings putto disable animations; per-test-igradle flag; 15-minute test timeout.android/src/main/assets/nodejs-project/index.js— track areadinessPhasein the state IPC server and replaystarted/readyto late-connecting clients. The iOS copy atios/nodejs-project/index.jscarries the same fix (iOS PR keeps that side); this is the Android side of the same logical change.android/src/main/assets/nodejs-project/lib/control-rpc.js— remove unused stub.example/tests/android/ServiceLifecycleTest.ktandexample/tests/android/ShutdownPathTest.kt— add a PID-stability check inwaitForServiceRunningso a:ComapeoCoreprocess that dies at startup is surfaced as a clear assertion failure instead of the test hanging.Commit trail
The rewind / re-apply pair has net-zero tree diff, but is required so the final "Apply" commit's diff is meaningful: without it, the changes would be inherited silently through the shared merge-base with PR #6 rather than attributed to this PR.
Base branch
Stacked on #6. Merge #6 first, then rebase this onto
main— the rewind + re-apply pair will resolve to a single introduction of the Android-specific changes on the post-#6-merge main.Test plan
npx expo prebuild --platform androidproducesexample/android/app/src/androidTest/java/com/comapeo/core/example/*.ktmatchingexample/tests/android/app/build.gradlecontains the AndroidJUnit test runner line and all fiveandroidTestImplementationdepsmergeContentsis idempotent)./gradlew connectedAndroidTest(ore2e/run-instrumented-tests.sh) runs the instrumented tests to greenandroid-testsCI job completes within 15 min and shows per-test output🤖 Generated with Claude Code