Skip to content

test(expo): add the Expo host of the e2e tests, their CI, and the verify-clerk-expo skill - #10237

Draft
mikepitre wants to merge 35 commits into
mike/expo-verify-r2-shared-corefrom
mike/expo-verify-r3-expo-host
Draft

mikepitre wants to merge 35 commits into
mike/expo-verify-r2-shared-corefrom
mike/expo-verify-r3-expo-host

Conversation

@mikepitre

@mikepitre mikepitre commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Description

This is the third of four pull requests that replace the eleven of stack #10100. It sits on #10236, and #10238 sits on it. It holds the parts of #10087, #10090, and #10131 that are this repository's own, apart from the e2e tests in #10236, with the edits of #10219 to #10230 already in them.

With this pull request, integration/expo-native/bin/control-clerk-expo runs. It builds the expo-native fixture from #10235, takes a simulator or an emulator, creates a Clerk development application for the worktree, runs the e2e tests from #10236, and keeps a video, screenshots, and logs of each run. On a machine that cannot run the device, it borrows one on a GitHub Actions runner. CI runs every e2e test on both platforms for a pull request that is ready for review.

The first four commits are in reading order. The last two answer a review: a session builds natively when uncommitted changes touch the root pnpm-lock.yaml, and a test pins when a session fetches kept builds. Paths that begin src/, bin/, or test/ are inside integration/expo-native/.

Commit Lines What it adds
1. The Expo host 1,943 src/host.ts answers what the shared core asks of a platform. src/fixture.ts builds the fixture as a Debug dev client for a device on this machine, or as a Release app with its JS inside for a runner. src/native-build.ts keys a native build on what decides it, and puts new JS into a kept build. src/freshness.ts checks that the build of packages/expo is not older than its sources. src/platform/session-device.ts is the device recipe of a borrowed session. Also the package README.md.
2. The workflows 608 verify-e2e.yml runs every e2e test on iOS and Android. verify-remote.yml runs one borrowed-device session. bin/fetch-native-build.sh and bin/boot-ios-simulators.sh are steps that both use.
3. The unit tests 2,201 The tests of commits 1 and 2. Three of them read the workflow files. test/remote-contract.test.ts (315 lines) is a copy from clerk-ios.
4. The skill 964 .claude/skills/verify-clerk-expo/, its Cursor symlink, and the Verifying changes sections of AGENTS.md and packages/expo/AGENTS.md.

To review, read .claude/skills/verify-clerk-expo/SKILL.md first for what the CLI does, then src/host.ts, src/fixture.ts, and src/native-build.ts, then the two workflows. Apart from remote-contract.test.ts, nothing here is copied or generated. The five changesets are the empty ones that the old pull requests carried. No published package changes.

What needs attention:

  • verify-e2e.yml starts on a pull request to main that changes the package, the fixture, or an Expo package, and by hand. A draft, a pull request from a fork, and a repository without the secret get a notice and no device job. The device job runs the pull request's code with contents: read, actions: read, and pull-requests: write, and gives MOBILE_VERIFICATION_PLATFORM_API_KEY only to the steps that call up, run, and down. It uploads evidence only when the CLI found no secret value in the run.
  • verify-e2e.yml keeps the native app it built as an artifact for seven days, named by its native fingerprint. A later job, or a session, takes one only from a run of the same branch of this repository, never from a fork. Artifacts of this repository are public, so a session stores none of its own.
  • verify-remote.yml starts only by workflow_dispatch, which needs write access. It uses no secret, and its jobs have contents: read, with actions: read added for the session job. A session builds the pushed commit, or that commit with the uncommitted changes to the app sources that the CLI sends as one patch. Every route of its tunnel needs a bearer token that the CLI made. The tunnel is a Cloudflare quick tunnel, so Cloudflare can read the traffic, which includes sign-in tickets for test users of an application that down deletes.
  • src/native-build.ts exports the JS from the checkout, compiles it with the fixture's hermesc, and puts it in a copy of a kept app. The build fails unless the app then holds exactly that bundle.

npm test in integration/expo-native/ passes 837 of 837 on this branch, and npm run typecheck is clean. verify-e2e run 38611002410, started by hand on #10238 before those two commits, passed 17 of 17 tests on iOS and 15 of 15 on Android.

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other: test tooling

🤖 Generated with Claude Code

mikepitre and others added 4 commits October 14, 2026 13:52
src/host.ts tells the shared core how to build the expo-native fixture, install it, and launch
it on a simulator or an emulator, on this machine or on a borrowed CI runner. src/native-build.ts
keys a native build on what decides it and puts new JS into a kept build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o a session

verify-e2e.yml runs every e2e test on an iOS simulator and an Android emulator for a pull
request that is ready for review. verify-remote.yml boots one device on a runner for a session
that a developer or an agent starts by workflow_dispatch. Both take a native build that an
earlier run of the same branch kept, through bin/fetch-native-build.sh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
.claude/skills/verify-clerk-expo/ is the instructions an agent or a developer reads to prove a
@clerk/expo change on a device, and .cursor/skills/verify-clerk-expo links to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 26540ea

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
clerk-js-sandbox Ready Ready Preview Oct 15, 2026 5:14am UTC
swingset Ready Ready Preview Oct 15, 2026 5:14am UTC

Request Review

@coderabbitai

coderabbitai Bot commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@mikepitre
mikepitre added this pull request to stack #10239 October 14, 2026 17:56
mikepitre and others added 2 commits October 14, 2026 14:40
…kfile

The config plugins of the workspace packages load @expo/config-plugins from the workspace
install, which the root pnpm-lock.yaml resolves. A session patch that changed only that
lockfile kept the native fingerprint and the native project key, so the session put a new
bundle in a native build that an older @expo/config-plugins generated. The root lockfile now
counts as a native input while it differs from HEAD. A committed lockfile still does not, so
the native builds that runs of a branch keep are found as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d profile dismissal

The feature map said Expo has no organization UI. That holds for the
native components only, since @clerk/expo/web exports the clerk-js
organization components. On Android the UserProfileView dismisses
itself when the user goes away, not the UserButton.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mikepitre and others added 2 commits October 14, 2026 21:26
The Evidence text told a remote session to attach without --before for
a change already pushed. A second session started on a pushed branch at
the base commit makes that before run, and attach --before takes it. The
text now gives those steps, copies the settings file with a committed
spec for the before run, and says that attach pairs a missing screenshot
with the failure screenshot of its own test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mikepitre and others added 2 commits October 14, 2026 21:50
On a Mac, plain `up` picks the local backend, so the remote before-run
steps now pass --backend remote to both `up` calls, as the run that
proved these steps did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mikepitre and others added 2 commits October 15, 2026 00:23
mikepitre and others added 2 commits October 15, 2026 01:09
…ds ffmpeg

The engine's `settle` never paced a spec's actions, so the skill no
longer says that a run holds 0.7 s after each action. It names the two
pauses there are, the 0.6 s before `host.tap` and `host.fill` and the
2 s at the end of a `host.evidence` block, and says to tap with
`host.tap` inside a block. Setup and the remote machine needs now say
that `attach --video` cuts with ffmpeg and posts the whole video
without it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch was successfully deployed

2 active deployments
Preview – swingset — 26540ea5 Deployed Oct 15, 2026 by vercel[bot]
Preview – clerk-js-sandbox — 26540ea5 Deployed Oct 15, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant