All jobs

Review Pull Requests on a React Native App

Yes. An agent checks out the React Native pull request, runs pnpm lint, type-check and test, and posts one review citing file and line.

Run this on RushIn a Project that has your repository.

What the agent does

The agent checks out the pull request and reads the package manager before the three commands. In an Expo app shaped like obytes/react-native-template-obytes, package.json is named obytesapp, packageManager is pnpm@10.12.3, and preinstall is npx only-allow pnpm. The lockfile is pnpm-lock.yaml. Runtime versions are expo ~54.0.32, expo-router ~6.0.22, react-native 0.81.5, @tanstack/react-query ^5.90.19 and zustand ^5.0.10. typescript is ^5.9.3, jest is ^29.7.0, eslint is ^9.39.2. Scripts the request names are lint as eslint ., type-check as tsc --noemit, and test as jest. check-all also runs lint:translations. e2e-test is maestro test .maestro/ with APP_ID=com.obytes.development, and it is not part of pnpm test.

pnpm lint, pnpm type-check and pnpm test run in that order in the sandbox. jest.config.js uses the jest-expo preset, matches spec and test files, maps @/ to src, and ignores a long transform list that includes react-native-reanimated, @shopify, zustand and moti. The committed tests are src/features/auth/components/login-form.test.tsx and four component tests under src/components/ui: select, input, button and checkbox. The review quotes all three commands. A lint failure and a Jest failure stay separate so a type error is not buried in a test log. The agent does not start Maestro, because the request does not ask for e2e-test and those flows need a built app.

The read focuses on re-renders, lists and platform splits, which is where this template hides cost. src/features/feed/feed-screen.tsx loads posts with usePosts, wraps renderItem in useCallback, and renders FlashList with keyExtractor set to item-${index} and ListEmptyComponent pointing at EmptyList. src/components/ui/list.tsx re-exports FlashList from @shopify/flash-list and memoizes EmptyList. src/components/ui/select.tsx sets List to FlashList when Platform.OS is web and to BottomSheetFlatList otherwise. src/components/ui/utils.tsx exports IS_IOS from Platform.OS === 'ios'. src/lib/i18n/utils.tsx branches on ios, android and web. .maestro/utils/hide-keyboard-ios.yaml taps the Return id, and hide-keyboard-android.yaml calls hideKeyboard. A new inline renderItem, an index key on a list that reorders, or an ios-only prop used on android is what the review cites.

One GitHub review collects the findings. Blocking is a list or hook change that the three commands do not catch: a keyExtractor of the index, a renderItem that closes over fresh state on every parent render, or a Platform.OS branch that drops a platform. A suggestion is a missing component test next to the five that exist, or a Maestro flow that was not updated when a testID moved. The review names the file and the line for each. No commits are pushed. The transcript keeps pnpm lint, tsc --noemit and jest as separate tool results.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Review the open pull request on this React Native repository. Check it out and install with pnpm (packageManager pnpm@10.12.3, preinstall only-allow pnpm). Run pnpm lint, pnpm type-check and pnpm test. Read the diff with src/features/feed/feed-screen.tsx, src/components/ui/list.tsx, src/components/ui/select.tsx and the Platform.OS branches in src/components/ui/utils.tsx and src/lib/i18n/utils.tsx. Pay attention to re-renders, list keys and platform-specific code. Do not run Maestro. Post one review that cites file and line for every finding, and include each command's result. Do not push commits.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app/pull/1"
    }
  ]
}
  1. Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
  2. Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
  3. Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

What comes back

What comes back is a review on the pull request and the three command logs on the session. The session read names the repository and the pull request. The review lists pnpm lint, pnpm type-check and pnpm test as three results, then findings with file and line. On a feed change it cites feed-screen.tsx, including the index keyExtractor and whether renderItem stayed inside useCallback. On a select change it cites the web FlashList versus BottomSheetFlatList split. The author's commits are the only commits on the branch.

A reviewer looks at whether a green Jest run is being asked to stand in for Maestro. The five component tests do not open the feed screen, and .maestro/app/tabs.yaml is a device flow the agent did not run. That limit belongs in the review, not a claim that the app launched on iOS. Artifacts are only files the agent produced. The usual record is the transcript: tool_use for each pnpm script and tool_result for its output. Read it from GET /o/{org}/sessions/{id}/messages after the turn, or follow GET /o/{org}/sessions/{id}/events while it runs.

Run it on every pull request opened

On pull_request.opened, POST this body with the pull request URL in resources. The sandbox clones that branch through the GitHub App, one repository per session. Use the delivery id as Idempotency-Key so a webhook retry does not start a second pnpm install. synchronize can send the same body with a new key when you want the new commits reviewed.

The API key webhook fires run.completed when the review is posted. Store webhook_secret from the PATCH that set webhook_url, and verify the signature on the raw body. Expo installs are large, and a key stops at max_concurrent in-progress runs, default 4, with 429 after that. Hold further pull requests until a session finishes rather than raising the burst.

The use case this job follows, with its automation and trigger: Review every pull request.

Why run it on Rush?

Lint, tsc and Jest on a React Native tree want the pnpm version in packageManager, and only-allow pnpm rejects npm. Doing that on a laptop ties up the working copy and mixes the pull request's node_modules with yours. The sandbox runs the three scripts on its own clone and keeps each log. You can close the laptop. The sandbox parks when the turn ends and a follow-up wakes the same install.

A diff read will not show that type-check is tsc --noemit, that Jest only has the five component tests, or that the feed list keys by index. Those facts are in the files and in the command output the review quotes. Parallel sessions review parallel pull requests without sharing a pnpm store on your machine, and the GitHub review is what the author answers.

Frequently asked questions

Does this run Maestro or build an iOS app?

No. pnpm test is Jest with the jest-expo preset. e2e-test shells out to Maestro and needs a built app id. The review says the device flows were not run. Ask for e2e-test in the input only when the sandbox image can run Maestro, and expect that command's own output in the review.

Will it upgrade Expo or touch app.json?

It does not push, so app config, lockfile and native projects stay as the pull request has them. A finding can name a version it read, such as react-native 0.81.5 or expo ~54.0.32, when the diff depends on that version. It does not bump packages to silence a lint rule.

pnpm test passed. Does that mean the feed list is fine?

It means the five tests Jest collects passed, plus lint and tsc if those passed too. login-form, select, input, button and checkbox do not render FeedScreen. A bad keyExtractor is a review finding from reading feed-screen.tsx, not something those tests assert.

How does it treat Platform.OS branches?

It reads them. select.tsx picks FlashList on web and BottomSheetFlatList elsewhere. utils.tsx defines IS_IOS. The i18n helper branches for ios, android and web. A change that edits one branch and not the others is cited at that line. The review does not execute an iOS simulator to prove the branch.

Can I skip type-check when I only care about Jest?

Put the commands you want in input. The template's check-all script runs lint, type-check, translation lint and test, and CI-shaped reviews should keep all three the request names. If you drop type-check, the review should say it was not run, so a green Jest line is not read as a green tsc.