A CI/CD Pipeline for React Native: EAS, GitHub Actions, and Fastlane
A React Native CI/CD pipeline for 2026: checks on every pull request, preview builds, and store releases with EAS Workflows, GitHub Actions or Fastlane.
Full-Stack, Mobile & AI Engineer
Most React Native teams start with releases done by hand: someone runs a build on their laptop, uploads it, fills in forms and hopes nothing was forgotten. It works until that person is on holiday, or until the day a release goes out with the wrong environment variables.
A React Native CI/CD pipeline makes every release the same boring sequence: checks on every pull request, a preview build for testers, a production build and submission when you tag a release, and over-the-air updates for small fixes. Here's how to set one up with Expo's EAS Workflows, with GitHub Actions, or with Fastlane for bare projects.
Key takeaways
- Every pull request should run type checks, linting and unit tests. That alone catches most broken builds.
- Merging to main should produce something testers can install: a preview build or an over-the-air update to a preview channel.
- Tagging a release should build, sign and submit to both stores automatically.
- EAS Workflows runs builds, submissions and updates from YAML files in your repo; GitHub Actions can drive the same steps; Fastlane suits bare projects with their own build machines.
- Keep secrets in the CI system, never in the repository: Expo token, App Store Connect API key, Google service account.
The pipeline, stage by stage
| Trigger | What runs | Output |
|---|---|---|
| Pull request | Type check, lint, unit tests, optionally E2E on key flows | Pass or fail on the PR |
Merge to main | Preview build or OTA update to the preview channel | Testers install or receive the change |
Release tag (e.g. v1.4.0) | Production builds for iOS and Android, then store submission | Builds in TestFlight and Play Console |
| JavaScript-only hotfix | OTA update to the production channel, as a percentage rollout | Fix live without a store review |
| After release | Crash and performance monitoring | Alerts if crash rate rises |
Option 1: EAS Workflows
EAS Workflows lives in your repository under .eas/workflows/ and runs on Expo's infrastructure, so build and submit steps don't need any other CI. Link your GitHub repository to the EAS project, then add a workflow:
# .eas/workflows/release.yml
name: Release to stores
on:
push:
branches: ['main']
jobs:
build_ios:
type: build
params:
platform: ios
profile: production
build_android:
type: build
params:
platform: android
profile: production
submit_ios:
needs: [build_ios]
type: submit
params:
build_id: ${{ needs.build_ios.outputs.build_id }}
submit_android:
needs: [build_android]
type: submit
params:
build_id: ${{ needs.build_android.outputs.build_id }}You can also run a workflow on demand with eas workflow:run .eas/workflows/release.yml. A separate workflow with a job of type: update and a branch parameter can publish over-the-air updates to a preview channel on every merge.
Option 2: GitHub Actions
If your checks already run in GitHub Actions, add the EAS CLI with Expo's official action and drive builds and updates from there:
# .github/workflows/ci.yml
name: CI
on:
pull_request:
push:
branches: [main]
jobs:
checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npx tsc --noEmit
- run: npx eslint .
- run: npx jest --ci
preview-update:
if: github.ref == 'refs/heads/main'
needs: checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- run: npm ci
- run: eas update --branch preview --message "${{ github.sha }}" --non-interactiveFor store releases, add a job on tag pushes that runs eas build --platform all --profile production --auto-submit --non-interactive. The builds still run on Expo's servers; GitHub Actions just starts them.
Option 3: Fastlane for bare projects
If you maintain the native projects yourself and build on your own macOS runners, Fastlane automates signing (match), building (gym for iOS, Gradle tasks for Android) and uploading (pilot to TestFlight, supply to Google Play). It's more setup and more maintenance, but gives complete control over the build environment.
From the field: My release work covers EAS Build, Submit and Update, plus Fastlane with GitHub Actions where a project needs its own pipeline, phased rollouts and crash triage in Sentry. The choice of tool matters less than the rule behind it: no release should depend on one person's laptop.
Which option to choose
| Situation | Best fit |
|---|---|
| Expo project, small team, wants the least setup | EAS Workflows |
| Existing GitHub Actions checks and conventions | GitHub Actions starting EAS builds and updates |
| Bare project with custom native build steps | Fastlane on macOS runners (optionally with EAS for some parts) |
| Strict rule that code never leaves company infrastructure | Fastlane or local EAS builds on self-hosted runners |
GitLab CI and Jenkins
The pipeline doesn't change with the CI product; the runners do. Linux runners are enough for linting, tests and anything that hands builds to EAS with an EXPO_TOKEN. Building iOS yourself needs macOS: GitLab offers hosted macOS runners on its paid tiers, and Jenkins needs your own Mac agents. A common GitLab or Jenkins setup runs checks on Linux and calls eas build --non-interactive --no-wait for the native builds, which avoids maintaining Macs at all.
React Native CI/CD tools compared
| Tool | What it's best at |
|---|---|
| EAS Workflows | Expo projects; builds, updates, submissions and Maestro tests in one place |
| GitHub Actions | Checks and orchestration for code already on GitHub |
| GitLab CI | The same, for GitLab, with hosted macOS runners on paid tiers |
| Bitrise, Codemagic | Mobile-focused hosted CI with macOS machines and signing helpers |
| Jenkins | Full control on your own infrastructure, at the cost of maintaining it |
| Fastlane | Not a CI service: the scripting layer for signing, builds and uploads inside any of the above |
What to test, and where
Not every check belongs on every commit. A practical split:
| Stage | Tests | Why there |
|---|---|---|
| Every pull request | Type check, lint, unit tests, component tests | Fast (a few minutes), catches most breakage |
| Merge to main | Build a preview app; optionally E2E tests with Maestro on key flows | Slower, but proves the app actually launches |
| Before a store release | Full E2E suite on real or cloud devices, manual smoke test on a release build | Highest confidence where it matters most |
Keep the pull-request stage under ten minutes. If it gets slower, developers stop waiting for it, and the pipeline stops protecting you.
Branches, tags and release notes
A simple convention keeps the pipeline predictable:
mainis always releasable. Feature work merges through pull requests with green checks.- Every merge to
mainupdates the preview channel, so testers always have the latest build or update. - A version tag starts a store release, for example
v1.4.0. The tag names the version, and EAS remote versioning handles build numbers. - Release notes come from merged pull requests, written for users, not as a raw commit log.
- Hotfixes branch from the release tag, get a patch version (
v1.4.1), and ship either over the air or as a new build, depending on whether native code changed.
The point isn't the exact naming. It's that anyone on the team can answer "what's in this release, and how did it get to users?" without asking the one person who usually ships.
Secrets you'll need
- Expo access token (
EXPO_TOKEN) for any CI that runs the EAS CLI. - App Store Connect API key for submitting iOS builds without a password and two-factor prompt.
- Google Play service account key (JSON) with release permissions on your app.
- Environment variables for each profile, stored as EAS environment variables or CI secrets, not committed to the repo.
FAQ
What is the best CI/CD for React Native?
For Expo projects, EAS Workflows is the simplest complete option, because builds, store submission and over-the-air updates run in one place. GitHub Actions is a good choice when you already use it for checks. Fastlane suits bare projects that build on their own macOS machines.
Can GitHub Actions build iOS apps for React Native?
Yes, either by starting EAS builds (which run on Expo's macOS machines) or by building directly on GitHub's macOS runners with Xcode and Fastlane. Starting EAS builds is simpler; macOS runners give more control at higher cost and setup effort.
How do I automate App Store and Google Play submission?
Use EAS Submit, either as a submit job in an EAS workflow or with --auto-submit on the build command, authenticated with an App Store Connect API key and a Google Play service account. Fastlane's pilot and supply do the same for bare pipelines.
Should every merge create a new store build?
No. Store builds are best for native changes and planned releases. For JavaScript-only changes, an over-the-air update to a preview channel is faster for testers, and a percentage rollout to production is the safest way to ship small fixes.
Next steps
If your releases still depend on someone's laptop, I can set up a pipeline that checks every pull request and ships to both stores from a tag. Get in touch, or see my services.
Sources
- Get started with EAS Workflows, Expo
- EAS Workflows syntax, Expo
- expo-github-action, Expo on GitHub
- EAS Submit, Expo
- Fastlane documentation, Fastlane
Related
EAS Update in Production: Channels, Runtime Versions, Rollbacks
Run EAS Update safely in production: channels and branches, runtime versions, percentage rollouts, rollbacks, pricing, and fixes when updates don't arrive.
App Store Rejection Reasons in 2026, and How to Fix Each One
Apple rejected 2.09M submissions in 2025. The App Store rejection reasons that come up most, what each guideline means, and how to fix them fast.
The App Store and Google Play Pre-Submission Checklist (2026)
A copyable App Store and Google Play submission checklist for 2026: build, access, privacy, payments, listing and launch-day steps, in order.
