* feat(ios): support explicit iOS simulator keychain reset
`settings clear-app-state` never touched keychain-backed credentials
(e.g. Firebase auth), so a customer's fresh-install reset via the CLI
left an app signed in when their in-app reset button did not (#2282).
simctl exposes no per-app keychain reset, only a whole-simulator one
(`simctl keychain <device> reset`), so this ships as a separate,
explicit `settings reset-keychain clear` command rather than folding
it into `clear-app-state` — callers opt in knowing the scope is the
whole simulator, not just the app under test.
Split the pre-existing `apps.test.ts` and `snapshot-handler.test.ts`
suites along the `app-settings.ts`/`snapshot-settings.ts` modules they
actually mirror, since both were already over the test-file-size
tripwire and could not grow further.
* fix(ios): reject extra reset-keychain arguments and add live-tested keychain fixture
settings reset-keychain clear <extra-arg> silently dropped the extra
argument in both the CLI reader and the direct-daemon parser, so a
caller expecting per-app scoping could get a whole-simulator wipe
without any signal something was off. Reject it instead in both
places, with tests proving no settings mutation happens.
Also add a small keychain-backed "auth" fixture to the test-app's
automation lab (expo-secure-store) so the settings reset-keychain
guarantee has a real regression surface: authenticate, verify the
credential survives clear-app-state and a plain relaunch, then verify
reset-keychain actually clears it. Validated live against a disposable
iOS simulator.
* fix(ci): stop a bare gradle.properties append from corrupting the last line
expo prebuild's generated android/gradle.properties has no trailing
newline, so `echo "org.gradle.jvmargs=-Xmx4g" >> gradle.properties`
appended directly onto its last line instead of a new one, producing
expo.inlineModules.watchedDirectories=[]org.gradle.jvmargs=-Xmx4g.
Gradle's JSON.parse of that property then fails at configure time,
before any real compilation runs -- the exact "Process 'command
'node'' finished with non-zero exit value 1" failure this branch hit
on Android Release and the Smoke Tests fixture-app fallback build.
This was a dormant bug: the Android build-cache job only runs on a
fingerprint miss, and no PR had changed the test-app's native
dependencies in a while. Adding expo-secure-store (#2282's keychain
fixture) was enough to trigger it. Reproduced locally against a clean
install with the exact CI script, confirmed the corrupted property,
and confirmed the printf-based fix builds cleanly (870/870 tasks).
Splits the test app's build caching by context instead of running one remote
cache for both.
Locally, `expo run:*` caches the native build on disk via the
expo-build-disk-cache provider, keyed by the Expo fingerprint. A second run with
no native change reuses the first build; a screen edit never rebuilds, because
Metro serves JS. This is the original ask — "next time we don't build unless
native changes" — and needs no token, no network, and no custom provider.
In CI, test-app-build-cache.yml builds a Release binary per platform when the
fingerprint has no artifact yet, and publishes it as a GitHub Actions artifact
named `fingerprint.<hash>.<platform>`. Release, not dev-client, so the JS bundle
is embedded and a consuming job needs no Metro. setup-fixture-app installs it by
downloading the artifact and refreshing the JS with @expo/repack-app, so keying
on the native-only fingerprint stays correct — a JS-only change reuses the same
native binary in seconds. It falls back to an inline build when no artifact
exists yet, so a caller is never left without an app.
Release removes the sharp edges the dev-client cache needed. Its simulator .app
is universal (x86_64+arm64) rather than the active-arch-only slice a debug build
emits, so no architecture tag. It links against the SDK but loading is gated by
the deployment target, which the fingerprint already covers, so no toolchain
tag. And the CLI only narrows *debug* builds to the device ABI, so a Release APK
spans every ABI without the undocumented --all-arch flag. The artifact name
collapses to fingerprint plus platform.
This deletes build-cache-provider.js entirely — with it goes the custom Expo
provider that had to reach GitHub from inside @expo/cli, and every workaround
that forced: the fetch-nodeshim User-Agent shim, the arch/Xcode identity, the
upload-intent handoff. CI now talks to the artifacts API with plain `gh api`
outside the patched fetch, and locally the disk cache never hits the network.
The fingerprint comes from @expo/fingerprint's own `fingerprint:generate` (no
--platform, matching what @expo/cli hashes). Gitignoring /ios and /android is
what makes it machine-independent: the library asks the VCS whether the platform
markers are ignored and, concluding CNG, skips hashing them — so a developer's
prebuild output and a fresh CI checkout agree.
conformance-differential consumes setup-fixture-app, so it gains
`permissions: actions: read` for the artifact lookup.
The artifact lookup is non-fatal: a query outage leaves the id empty and
falls through to an inline build like a miss does, rather than exiting the
composite under set -e and turning a cache blip into a caller failure.
test/scripts/setup-fixture-app-fallback-smoke.sh drives that step's real shell
against a failing gh and asserts source=build; ci.yml runs it.
* test: migrate test app to expo dev client
* docs: align test app device targeting
* docs: clarify dev client setup tradeoffs
* docs: remove stale sdk reference
* fix: resolve test-app dependabot alerts
The postcss/uuid overrides added in #464 stopped applying once test-app
ended up nested under the repo-root pnpm-workspace.yaml: pnpm only honors
overrides from a workspace root, so test-app's package.json `pnpm.overrides`
were silently ignored and the lockfile drifted back to vulnerable versions.
Move the overrides into a dedicated examples/test-app/pnpm-workspace.yaml so
test-app is its own pnpm root and the overrides are honored, and add scoped
overrides for the two remaining alerts:
- postcss 8.4.49 -> 8.5.12 (XSS in CSS stringify)
- uuid 7.0.3 -> 14.0.0 (missing buffer bounds check)
- ws@8 8.20.0 -> 8.21.0 (uninitialized memory disclosure)
- brace-expansion@5 5.0.5 -> 5.0.6 (ReDoS / max bypass)
ws and brace-expansion overrides are scoped to the vulnerable majors so the
non-vulnerable ws@7 / brace-expansion@1 copies in the tree are left untouched.
* chore: drop dead lodash-es override, document test-app workspace
- Remove the no-op `lodash-es` override from the root package.json (leftover
from #368). lodash-es is no longer in the dependency tree, so the override
resolved to nothing; regenerating the root lockfile is a no-op.
- Add a comment to examples/test-app/pnpm-workspace.yaml explaining why the
file exists, so it isn't "tidied away" and the override drift reintroduced.