Skip to content

fix(native): don't flag P0_TRANSFORMS pages as uncovered server routes#2436

Open
innolope-dev wants to merge 1 commit into
mainfrom
fix/native-build-transform-scan
Open

fix(native): don't flag P0_TRANSFORMS pages as uncovered server routes#2436
innolope-dev wants to merge 1 commit into
mainfrom
fix/native-build-transform-scan

Conversation

@innolope-dev

Copy link
Copy Markdown
Collaborator

The bug — native builds fail on main today

detectUncoveredServerRoutes() in scripts/native-build.js fails the native build when it finds App Router files with server-only exports. But the script also maintains P0_TRANSFORMS — files it replaces with static-export-safe client stubs before next build runs. Their server-only exports never reach the export, yet the scan flags them anyway, because it only consults ITEMS_TO_DISABLE:

if (isCoveredByDisableList(rel)) continue

This is not hypothetical. On main right now, src/app/(mobile-ui)/claim/page.tsx has export const dynamic = 'force-dynamic' (line 11) and a matching P0_TRANSFORMS entry (native-build.js:86). Someone did the right thing — added the directive and the stub — and the anti-rot guard rejects it anyway. The native build cannot get past this scan.

The fix

Teach the scan that transformed files are already handled:

if (isCoveredByDisableList(rel) || isHandledByTransform(rel)) continue

Why this isn't a silent no-op

The obvious failure mode is a predicate that never matches — the scan keeps passing, the "fix" looks fine, and the guard still rejects real routes. Both halves were checked:

  • rel and P0_TRANSFORMS[].path are the same shape. rel is path.relative(APP_DIR, full); the transform loop consumes item.path as path.join(APP_DIR, item.path). Both are relative to src/app.
  • Negative control against the real scan. Running the actual (unmodified) scan functions over the real app tree: unpatched → reports (mobile-ui)/claim/page.tsx (export const dynamic = 'force-dynamic'); patched → zero offenders.
  • Mutation check. Breaking the predicate to the plausible-but-wrong form ('src/app/' + normalized) fails 3 of the 4 tests, so they aren't vacuous.
  • Unrelated routes (api/foo/route.ts, (mobile-ui)/claim/layout.tsx, '') correctly do not match, guarding against an always-true predicate.

Tests

scripts/__tests__/native-build-scan.test.js — 4 tests, green under the existing jest config. Plain CJS to match the plain-.js script under test. pnpm-lock.yaml untouched.

Not verified

A full pnpm native:build was not run — it's a 10–30 min native toolchain build and was deliberately skipped. What's proven is the guard logic itself, not that next build subsequently completes with the stubs in place. Note that this is already unknown on main, where the build stops at this scan; the change can only get it further, not less far.

The anti-rot scan only consulted ITEMS_TO_DISABLE, so a page whose
server-only exports are already stripped by a P0_TRANSFORMS stub still
failed the native build. This is live on main: (mobile-ui)/claim/page.tsx
has force-dynamic and a matching stub, and the scan rejects it.

Skip files handled by a transform, and cover the scan with a unit test.
@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview, Comment Jul 16, 2026 8:12pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@innolope-dev, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 10 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 500e725b-3706-4fd2-ba12-05e3b1160393

📥 Commits

Reviewing files that changed from the base of the PR and between 5ab943f and fa8937e.

📒 Files selected for processing (2)
  • scripts/__tests__/native-build-scan.test.js
  • scripts/native-build.js
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/native-build-transform-scan

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 6206.68 → 6206.68 (0)
Findings: 0 net (+0 new, -0 resolved)

@github-actions

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 1996 ran, 0 failed, 0 skipped, 32.9s

📊 Coverage (unit)

metric %
statements 59.6%
branches 43.2%
functions 48.5%
lines 59.9%
⏱ 10 slowest test cases
time test
3.3s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
1.2s src/utils/__tests__/demo-api.test.ts › isDemoMode() is false when not running under Capacitor
0.5s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.3s src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx › Bank withdrawal keeps the $1 minimum for sub-$1 amounts
0.3s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in validateInviteCode body
0.3s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in validateInviteCode
0.2s src/context/__tests__/RainCooldownContext.test.tsx › activates cooldown + intro modal when the rain:cooldown event fires
0.2s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › keeps stickers off the username pill (final pass respects the keep-out)
0.2s src/components/Global/SupportDrawer/__tests__/SupportDrawer.test.tsx › shows the mailto fallback + retry when the proxy reports CRISP_FAILED
0.1s src/utils/__tests__/demo-balance.test.ts › starts at the full balance on a fresh install and stamps a timestamp
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@kushagrasarathe kushagrasarathe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Root-cause fix — P0_TRANSFORMS files were falsely flagged as uncovered server routes, blocking native build on main. Verified rel/t.path share the same shape; negative-control test guards against an always-true predicate. Non-blocking: full pnpm native:build not run (author flagged), acceptable since main is already stuck at this scan.

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.

2 participants