Background
Recent Sentry-related regressions (159a997, b576a15, b975101) shared a failure mode that unit tests don't catch well: the JS / Node / native layer compiled and ran fine, but spans either didn't reach Sentry or arrived with wrong structure. The only signal was opening the Sentry UI after a build.
Three small unit tests now cover the cheapest cases (see backend/lib/sentry-frame.test.mjs, backend/lib/sentry.test.mjs, android/src/test/java/com/comapeo/core/SentryFgsBridgeTest.kt). They catch the logic regressions — what a processor does when it runs, whether the Node layer produces any envelope, whether envelopeToFrame stamps length correctly.
What they don't catch:
- "Production init forgot to install processor X" (wiring, not logic)
- "JS layer was the wrong shape so the SDK never sent" (cross-SDK behavior)
- "Native received the frame but the wire send was dropped" (offline/queue/transport)
- Any cross-process trace stitching regression
These need to be caught either by manual smoke-test or by a real-Sentry tripwire. This issue tracks both.
Part 1 — Release smoke-test checklist
Run before every release. Build the example app with diagnostics on, point at a dedicated test DSN, then verify each item in Sentry's UI within ~10 minutes.
Setup
Trigger flows
Verify in Sentry UI
Part 2 — Scripted Sentry API tripwire (release-blocking)
A one-shot script that drives the example app through a known trace, polls Sentry's API, and asserts the trace arrived with the expected span structure. Replaces eyeballing for the "did anything actually arrive on the wire" question.
Shape
- Inputs: test DSN, Sentry auth token (read-only
event:read), org/project slug
- Build & launch the example app in CI or on a connected device
- App triggers a known transaction with a hard-coded
trace_id (env-var injected at boot)
- Script polls
GET /api/0/projects/{org}/{project}/events/?query=trace:<id> for up to 60s
- Assert: at least one transaction event matches;
op == comapeo.boot; expected child spans present; contexts.device.family == "Android" on the FGS-process span; no PII
Run cadence
- Pre-release CI workflow (manual trigger or branch-gated)
- ~5 minutes; doesn't need to run per-PR
Why not always-on per-PR
- Sentry ingestion latency makes it flaky as a blocking check
- Quota cost is non-trivial across many PRs
- Pre-release cadence catches the regression class without burning quota
Open questions
- Use a dedicated
comapeo-rn-test Sentry project (separate from the real one) so test traffic doesn't pollute dashboards / rate limits
- Decide whether the script runs against a simulator/emulator (cheap, less realistic) or BrowserStack (real device, slower)
- Auth token storage: GitHub secrets vs. EAS environment secrets
Acceptance
Background
Recent Sentry-related regressions (
159a997,b576a15,b975101) shared a failure mode that unit tests don't catch well: the JS / Node / native layer compiled and ran fine, but spans either didn't reach Sentry or arrived with wrong structure. The only signal was opening the Sentry UI after a build.Three small unit tests now cover the cheapest cases (see
backend/lib/sentry-frame.test.mjs,backend/lib/sentry.test.mjs,android/src/test/java/com/comapeo/core/SentryFgsBridgeTest.kt). They catch the logic regressions — what a processor does when it runs, whether the Node layer produces any envelope, whetherenvelopeToFramestampslengthcorrectly.What they don't catch:
These need to be caught either by manual smoke-test or by a real-Sentry tripwire. This issue tracks both.
Part 1 — Release smoke-test checklist
Run before every release. Build the example app with diagnostics on, point at a dedicated test DSN, then verify each item in Sentry's UI within ~10 minutes.
Setup
captureApplicationDataoncomapeo-test-YYYY-MM-DD) set as a global tag so the run is findableTrigger flows
comapeo.bootshould appear withboot.fgs-launch,boot.extract-assets,boot.node-spawn,boot.rootkey-load,boot.loader-init,boot.manager-initas child spansrpc.clientspan parented onto arpc.serverspan (cross-process trace stitching)error-nativeinjection) — should appear as an exception eventVerify in Sentry UI
contexts.device.family == "Android"on FGS-emitted spans (not"Google")proc(main/fgs),layer(rn/node/native),comapeo.rn(version label)releasematches the build's release name;environmentmatches expectedPart 2 — Scripted Sentry API tripwire (release-blocking)
A one-shot script that drives the example app through a known trace, polls Sentry's API, and asserts the trace arrived with the expected span structure. Replaces eyeballing for the "did anything actually arrive on the wire" question.
Shape
event:read), org/project slugtrace_id(env-var injected at boot)GET /api/0/projects/{org}/{project}/events/?query=trace:<id>for up to 60sop == comapeo.boot; expected child spans present;contexts.device.family == "Android"on the FGS-process span; no PIIRun cadence
Why not always-on per-PR
Open questions
comapeo-rn-testSentry project (separate from the real one) so test traffic doesn't pollute dashboards / rate limitsAcceptance
docs/(e.g.docs/sentry-release-smoke.md) and is linked from the release runbookscripts/sentry-tripwire.mjs(or similar) with a README block on usage