Skip to content

test(expo): check native module specs against the shipped binary surface - #10284

Open
mikepitre wants to merge 4 commits into
mainfrom
test/expo-native-contract
Open

mikepitre wants to merge 4 commits into
mainfrom
test/expo-native-contract

Conversation

@mikepitre

@mikepitre mikepitre commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Description

An Expo app can get new JavaScript over the air while the user keeps the app they installed from the store. So our new JS often runs on top of an older native build. If the JS calls a native function that build doesn't have, or passes it a different number of arguments, the app breaks. #8920 and #9373 both did this.

This adds a test that catches it before merge. It covers @clerk/expo-native-components, @clerk/expo-google-signin and @clerk/expo-biometrics on iOS and Android.

For each native function, the test looks at the Swift and Kotlin code in every stable release of that package, read from its git tag, and checks:

  • A function every release has must keep the same number of arguments. To change it, add a new function next to it.
  • A function some release lacks must be optional (?) in the TypeScript spec, so callers have to check for it first.
  • The spec matches the Swift and Kotlin code on this branch.

For example, #9373 needed to pass proxyUrl to native. Adding a third argument to configure breaks every app built on an older release, and the test now fails on it. What it does instead is keep configure and add an optional configureWithOptions:

if (ClerkExpo.configureWithOptions) {
  await ClerkExpo.configureWithOptions(publishableKey, token, { proxyUrl })
} else {
  await ClerkExpo.configure(publishableKey, token)
}

Adding a brand new native function works the same way: mark it ? in the spec and call it with ?..

Nothing needs updating after a release, because the test reads the tags each time it runs. CI now fetches those tags. If one is missing, the test fails and prints the git fetch command for it.

Run against the code from #8920 and #9373, the test fails and names the releases each change would break. It passes on this branch.

This also fixes stale paths in packages/expo/AGENTS.md, which still pointed at native code that moved into the three packages above. expo-passkeys isn't covered: it has no typed spec, and its iOS and Android functions differ on purpose.

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

🤖 Generated with Claude Code

mikepitre and others added 2 commits October 16, 2026 15:17
…hipped binary surface

The shipped surface in shipped-native-api.json comes from the latest
release tags. Regenerate it with
node packages/expo/scripts/generate-shipped-native-api.mjs after a release.

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

vercel Bot commented Oct 16, 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 16, 2026 8:03pm UTC
swingset Ready Ready Preview Oct 16, 2026 8:03pm UTC

Request Review

@changeset-bot

changeset-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9356b1e

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

@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository YAML (base), Organization UI (inherited)
  • Review profile: ASSERTIVE
  • Plan: Team
  • Run ID: 588f8a10-fe65-4ea3-b1ab-0b13772663f7
📥 Commits

Reviewing files that changed from the base of the PR and between 2e01895 and 9356b1e.

📒 Files selected for processing: 2
  • packages/expo/src/specs/__tests__/nativeContract.test.ts
  • packages/expo/src/specs/__tests__/nativeModuleContract.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.

📝 Walkthrough

The changes add utilities that parse native function declarations and TypeScript specs, then compare them with current native implementations and source from matching release tags. A parameterized test checks each configured module. The CI workflow fetches matching release tags before unit tests run. The native-code guidance scope and a changeset file also change.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 9356b

No actionable issue remains from the reviewed release-tag checks; the change is mergeable after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description clearly explains the native module contract tests, the covered Expo packages, the compatibility checks, and the CI tag-fetch changes.
Title check Passed The title concisely and accurately describes the main change: testing Expo native module specs against the shipped native binary surface.
  • Fix all pre-merge checks with AI
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@pkg-pr-new

pkg-pr-new Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@10284

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@10284

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@10284

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@10284

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@10284

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@10284

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@10284

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@10284

@clerk/expo-biometrics

npm i https://pkg.pr.new/@clerk/expo-biometrics@10284

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@10284

@clerk/expo-native-components

npm i https://pkg.pr.new/@clerk/expo-native-components@10284

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@10284

@clerk/express

npm i https://pkg.pr.new/@clerk/express@10284

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@10284

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@10284

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@10284

@clerk/mosaic

npm i https://pkg.pr.new/@clerk/mosaic@10284

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@10284

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@10284

@clerk/react

npm i https://pkg.pr.new/@clerk/react@10284

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@10284

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@10284

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@10284

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@10284

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@10284

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@10284

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@10284

commit: 9356b1e

The contract test now reads each native module from the latest
@clerk/expo-native-components, @clerk/expo-google-signin and
@clerk/expo-biometrics release tag with git, instead of a committed
JSON snapshot that had to be regenerated after every release. If a tag
is missing, the test fails and prints the git fetch command for it.

The unit-test job checks out with depth 1 and no tags, so it now
fetches those tags shallowly before the tests run.

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

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-10-16T20:05:56.043Z

Summary

Metric Count
Packages analyzed 20
Packages with changes 0
🔴 Breaking changes 0
🟡 Non-breaking changes 0
🟢 Additions 0

No API Changes Detected

All packages have stable APIs with no detected changes.


Report generated by Break Check

Last ran on 9356b1e.

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

This branch was successfully deployed

2 active deployments
Preview – swingset — 9356b1e1 Deployed Oct 16, 2026 by vercel[bot]
Preview – clerk-js-sandbox — 9356b1e1 Deployed Oct 16, 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