Skip to content

Commit d68bad7

Browse files
habnarkclaude
andcommitted
docs: add CI troubleshooting guide for mobile checks
Closes #442 Contributors hitting a failing check (TypeScript, lint, tests, Expo config, dependency install) had no single place documenting the local command to reproduce it or how to fix it. - Add docs/ci-troubleshooting.md: the four local commands that mirror CI (npm install --legacy-peer-deps, npm run typecheck, npm run lint, npm test), plus fixes for the failure patterns actually reproduced while writing this guide in this repo: - Peer dependency conflicts requiring --legacy-peer-deps - Multiple lock files (pnpm-lock.yaml/bun.lock alongside package-lock.json) causing Expo tooling to pick the wrong package manager, observed as `spawn bun ENOENT` when `expo lint` tried to auto-install eslint via bun - TypeScript syntax-error cascades (JSX parent element / unclosed brace errors) - Jest "Unexpected token 'export'" from an untransformed ESM dependency (lucide-react-native) missing from transformIgnorePatterns - Empty test files ("must contain at least one test") - Async test timeouts from unmocked dependencies - expo-doctor's network-dependent config-schema check failing in offline/sandboxed environments - A "clean install" recovery sequence - What reviewers/GrantFox evaluators expect from a green PR - Add "lint": "expo lint" to package.json so the guide (and CONTRIBUTING.md) can reference npm run lint consistently with npm run typecheck / npm test, instead of a bare npx invocation. - Link the guide from README.md, CONTRIBUTING.md's PR checklist, and mobile-onboarding-checklist.md's new "Common CI Failures" pointer. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent f021db1 commit d68bad7

5 files changed

Lines changed: 265 additions & 0 deletions

File tree

CONTRIBUTING.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ We strive to build a wallet that is accessible to everyone. Before submitting a
196196
npm test
197197
```
198198

199+
Also run `npm run typecheck` and `npm run lint` — all three, plus your
200+
tests, are expected to pass before you open a PR. If any of them fail and
201+
you're not sure why, see the
202+
[CI Troubleshooting Guide](docs/ci-troubleshooting.md).
203+
199204
4. **Commit** with a clear, descriptive message:
200205

201206
```bash

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ PocketPay Mobile is part of a broader PocketPay stack:
4848

4949
- [Screen Inventory](docs/screen-inventory.md) - A map of the main screens and routes in the app.
5050
- [Mobile Onboarding Checklist](docs/mobile-onboarding-checklist.md) - Quick-reference setup checklist for new contributors
51+
- [CI Troubleshooting Guide](docs/ci-troubleshooting.md) - Local commands and fixes for common TypeScript, lint, test, dependency, and Expo CI failures
5152
- [Evaluation Readiness Checklist](docs/evaluation-readiness-checklist.md) - Contract-issue review checklist for GrantFox contributors before payment evaluation
5253
- [UI State Catalogue](docs/ui-states.md) and [Accessibility Checklist](docs/accessibility.md) - Governance for major-screen states, shared component contracts, and accessible review evidence
5354
- [QR Receive Payload Format](docs/qr-payment-requests.md) - The address-only and SEP-0007-based payment-request formats the Receive screen encodes into its QR code

docs/ci-troubleshooting.md

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
# CI Troubleshooting Guide
2+
3+
A reference for the checks that run against every pull request — what they
4+
check, the exact command to reproduce a failure locally, and fixes for the
5+
errors contributors hit most often.
6+
7+
This guide is about **fixing red checks**. For initial project setup, see the
8+
[Mobile Onboarding Checklist](mobile-onboarding-checklist.md). For what
9+
evaluators look for on GrantFox contract issues, see the
10+
[Evaluation Readiness Checklist](evaluation-readiness-checklist.md).
11+
12+
> ⚠️ **Failing CI can block PR approval and payment evaluation.** Reviewers
13+
> and the GrantFox evaluation process expect all checks to pass before a PR
14+
> is merged. Don't skip, mute, or work around a failing check — fix the
15+
> underlying problem, or ask a maintainer if you believe the check itself is
16+
> wrong.
17+
18+
## Run These Locally Before You Push
19+
20+
Reproduce what CI checks in four commands:
21+
22+
```bash
23+
npm install --legacy-peer-deps # dependencies
24+
npm run typecheck # TypeScript
25+
npm run lint # lint / formatting
26+
npm test # unit and integration tests
27+
```
28+
29+
If your change touches `src/types/pocketpay-sdk.d.ts` or `src/sdk-stub/`,
30+
also run `npm run api:check` (see
31+
[SDK API Compatibility](sdk-api-compatibility.md)).
32+
33+
All four commands must exit cleanly before you open a PR.
34+
35+
---
36+
37+
## Dependency Errors
38+
39+
### `npm install` fails with peer dependency conflicts
40+
41+
```
42+
npm error ERESOLVE unable to resolve dependency tree
43+
```
44+
45+
This project has known React Native peer dependency conflicts. Always install
46+
with:
47+
48+
```bash
49+
npm install --legacy-peer-deps
50+
```
51+
52+
A plain `npm install` (without the flag) is expected to fail — that's not a
53+
broken project, it's a missing flag.
54+
55+
### Multiple lock files
56+
57+
Run `npx expo-doctor` and you may see:
58+
59+
```
60+
✖ Check for lock file
61+
Multiple lock files detected (pnpm-lock.yaml, package-lock.json, bun.lock).
62+
This may result in unexpected behavior in CI environments, such as EAS
63+
Build, which infer the package manager from the lock file.
64+
```
65+
66+
Expo's CLI infers the package manager from whichever lock file it finds. If a
67+
stray `bun.lock` or `pnpm-lock.yaml` ends up in your working tree (for
68+
example, from running `bunx` or `pnpm install` once out of habit), Expo
69+
tooling can silently switch to that package manager instead of npm. If that
70+
package manager isn't installed, commands fail with something like:
71+
72+
```
73+
✖ Failed to install eslint@^9.0.0, eslint-config-expo@~10.0.0 with error: spawn bun ENOENT
74+
```
75+
76+
This project uses **npm**`package-lock.json` is the only lock file that
77+
should exist. If you see extra lock files in `git status`, delete the ones
78+
you didn't intentionally create and reinstall with npm.
79+
80+
### `postinstall` seems stuck or the app fails to build with an SDK error
81+
82+
The `postinstall` script builds the PocketPay SDK from a pinned source commit
83+
(it isn't published to npm), which takes longer than a typical install. Let
84+
it run to completion. If a build genuinely fails partway through:
85+
86+
```bash
87+
rm -rf node_modules
88+
npm install --legacy-peer-deps
89+
```
90+
91+
---
92+
93+
## TypeScript Errors (`npm run typecheck`)
94+
95+
`npm run typecheck` runs `tsc --noEmit` — no output is emitted, only type and
96+
syntax errors are reported. Read the **first** error in the output first;
97+
syntax errors (unbalanced braces, unclosed JSX tags) frequently cascade into
98+
dozens of unrelated-looking errors further down the file. Fixing the first
99+
one often clears most of the rest. Common shapes you'll see:
100+
101+
- `error TS2657: JSX expressions must have one parent element.` — a
102+
component returns multiple sibling elements without a single wrapping
103+
element or `<>...</>` fragment.
104+
- `error TS1005: '}' expected.` / `error TS17015: Expected corresponding
105+
closing tag for JSX fragment.` — a missing or extra closing brace/tag
106+
earlier in the file; scroll up from the reported line.
107+
108+
The TypeScript compiler reports the *symptom's* location, not always the
109+
*cause's* location — if an error looks nonsensical at the reported line,
110+
check the nearest unclosed brace or tag above it.
111+
112+
---
113+
114+
## Lint / Formatting (`npm run lint`)
115+
116+
This project doesn't have a separate `prettier`/`eslint` setup — linting goes
117+
through Expo's built-in wrapper, which uses `eslint-config-expo` under the
118+
hood:
119+
120+
```bash
121+
npm run lint
122+
```
123+
124+
- On a machine without ESLint configured yet, `expo lint` offers to install
125+
`eslint` and `eslint-config-expo` automatically. Let it — it only touches
126+
`devDependencies`.
127+
- Auto-fix what can be auto-fixed (the `--` is required so npm passes `--fix`
128+
through to `expo lint` instead of swallowing it as an npm flag):
129+
```bash
130+
npm run lint -- --fix
131+
```
132+
- If the auto-install step fails with `spawn bun ENOENT` (or a similar
133+
"package manager not found" error), see **Multiple lock files** above —
134+
Expo picked the wrong package manager because of a stray lock file.
135+
136+
---
137+
138+
## Test Failures (`npm test`)
139+
140+
`npm test` runs `jest --watchAll=false` once and exits. A few failure
141+
patterns show up repeatedly:
142+
143+
### `SyntaxError: Unexpected token 'export'`
144+
145+
```
146+
node_modules/some-package/dist/esm/some-package.mjs:8
147+
export { default as Foo } from './icons/foo.mjs';
148+
^^^^^^
149+
SyntaxError: Unexpected token 'export'
150+
```
151+
152+
Jest runs tests through Node, which doesn't understand ES module `export`
153+
syntax out of the box. This happens when a `node_modules` package ships an
154+
ESM build (`dist/esm/*.mjs`) and Jest's `transformIgnorePatterns` doesn't
155+
include it, so Jest tries to run the raw `.mjs` file instead of transforming
156+
it. It surfaces in any test that imports a component which imports the
157+
untransformed package (for example, an icon library like
158+
`lucide-react-native`).
159+
160+
**Fix:** add the offending package to the `transformIgnorePatterns` entry in
161+
the `"jest"` block of `package.json` so Jest transforms it instead of
162+
skipping it. If you're not sure which package is at fault, the file path in
163+
the error (`node_modules/<package>/...`) tells you.
164+
165+
### `Your test suite must contain at least one test`
166+
167+
```
168+
FAIL tests/SomeScreen.test.tsx
169+
● Test suite failed to run
170+
Your test suite must contain at least one test.
171+
```
172+
173+
A test file exists but has no `it(...)`/`test(...)` blocks — usually a
174+
placeholder file created before the tests were written, or every test inside
175+
was commented out. Either add at least one real test or delete the file; an
176+
empty test file left in the repo will fail CI every time.
177+
178+
### `Exceeded timeout of 5000 ms for a test`
179+
180+
Jest's default per-test timeout is 5 seconds. This usually means a promise
181+
never resolves — a mock that doesn't call back, or an `await` on something
182+
that's waiting on a real timer/network call that doesn't exist in the test
183+
environment. Check that every async dependency (Stellar SDK calls,
184+
`SecureStore`, timers) is mocked — see the patterns in `__mocks__/` and
185+
`src/services/__mocks__/`. Only raise the test's timeout
186+
(`it('...', async () => { ... }, 10000)`) once you've confirmed the test is
187+
legitimately slow rather than actually hung.
188+
189+
### Missing mocks for native/SDK modules
190+
191+
If a test throws while importing `expo-secure-store`, `expo-router`, or the
192+
Stellar SDK, check whether an existing mock under `__mocks__/` or
193+
`src/services/__mocks__/` already covers it before writing a new one — most
194+
native and SDK dependencies already have a project-level mock to reuse.
195+
196+
---
197+
198+
## Expo-Specific Setup Issues (`npx expo-doctor`)
199+
200+
`npx expo-doctor` runs a broader set of Expo/EAS-oriented health checks
201+
beyond what `tsc` and `jest` cover — config schema validity, native module
202+
compatibility, and package manager consistency:
203+
204+
```bash
205+
npx expo-doctor
206+
```
207+
208+
- **Multiple lock files** — see above.
209+
- **`Check Expo config (app.json/ app.config.js) schema` fails with `fetch
210+
failed`** — this check calls Expo's remote API to validate `app.json`
211+
against the current schema. In a sandboxed or offline environment without
212+
outbound network access, this check cannot run and will fail regardless of
213+
whether your config is valid. If every other check passes and you have no
214+
network access, this is expected — re-run it somewhere with internet
215+
access before relying on its result.
216+
- **Blank screen or a stale Metro bundler error** — clear the Metro cache:
217+
```bash
218+
npx expo start --clear
219+
```
220+
221+
---
222+
223+
## Clean Install ("Nuke It From Orbit")
224+
225+
When in doubt, or after switching branches with very different dependencies:
226+
227+
```bash
228+
rm -rf node_modules
229+
rm -f pnpm-lock.yaml bun.lock # keep only package-lock.json
230+
npm install --legacy-peer-deps
231+
npm run typecheck
232+
npm run lint
233+
npm test
234+
```
235+
236+
If all four still fail identically after a clean install, the problem is
237+
almost certainly in your changes rather than your environment.
238+
239+
---
240+
241+
## What Reviewers and Evaluators Expect
242+
243+
- All required checks pass on the PR — don't open a PR with known-failing
244+
checks and a promise to "fix it after."
245+
- If a check fails for a reason unrelated to your change (a pre-existing
246+
issue on `main`), say so explicitly in the PR description rather than
247+
silently leaving it red.
248+
- For GrantFox contract issues specifically, a green CI run is necessary but
249+
not sufficient — see the
250+
[Evaluation Readiness Checklist](evaluation-readiness-checklist.md) for the
251+
full bar before payment evaluation.

docs/mobile-onboarding-checklist.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ full details on any step, see [CONTRIBUTING.md](../CONTRIBUTING.md).
6868
computer are on the same network, and no VPN is interfering with the LAN
6969
connection
7070

71+
## Common CI Failures
72+
73+
If your PR's checks fail once you're up and running, don't guess — the
74+
[CI Troubleshooting Guide](ci-troubleshooting.md) covers the TypeScript,
75+
lint, test, and Expo-specific failures contributors hit most often, with the
76+
exact local command to reproduce each one.
77+
7178
## You're Ready When
7279

7380
- [ ] The app runs locally with no red error overlay

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"test": "jest --watchAll=false",
1111
"test:watch": "jest",
1212
"typecheck": "tsc --noEmit",
13+
"lint": "expo lint",
1314
"api:check": "node scripts/check-sdk-api.js",
1415
"api:update": "node scripts/check-sdk-api.js --update"
1516
},

0 commit comments

Comments
 (0)