React Native GitHub Actions Workflow Template
Last updated
This is a working .github/workflows/ci.yml for a React Native app. A fast JavaScript job runs lint, type check and Jest on every push. A second job builds the Android app with Gradle caching. iOS is covered in the variants because it needs macOS.
The workflow
name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
js:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint
- run: npx tsc --noEmit
- run: npm test -- --ci --maxWorkers=2
android:
needs: js
runs-on: ubuntu-latest
timeout-minutes: 40
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- run: npm ci
- run: ./gradlew assembleDebug --no-daemon
working-directory: android
What the non-obvious parts do
- Two jobs on purpose. The JavaScript checks finish in minutes and catch most mistakes. The Android build is slower, so it waits for them with
needs: js. cache: npmcaches npm downloads keyed onpackage-lock.json. See caching npm. If you use Yarn or pnpm, change the cache option and install command; see Yarn and pnpm.--ci --maxWorkers=2makes Jest fail on obsolete snapshots instead of writing them, and limits workers so memory use stays predictable. RaisemaxWorkerson bigger machines.npm cibefore Gradle. The Android build reads native modules fromnode_modules, so install JavaScript dependencies first.working-directory: androidruns the wrapper where thegradlewfile lives.setup-gradlecaches Gradle dependencies and the wrapper. Onlymainsaves the cache, to avoid many near-duplicate entries. Details in Gradle caching.- Debug build.
assembleDebugneeds no signing keys, so it is safe on pull requests.
Variants
iOS on macOS
ios:
needs: js
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: bundle install && bundle exec pod install
working-directory: ios
- run: xcodebuild -workspace App.xcworkspace -scheme App -configuration Debug -sdk iphonesimulator build CODE_SIGNING_ALLOWED=NO
working-directory: ios
Replace App with your workspace and scheme. macOS minutes cost several times Linux minutes, so run this on main or on labelled pull requests. See macOS runners for iOS CI and speed up Xcode builds.
Expo and EAS
For Expo projects, run npx expo-doctor and Jest here, and let EAS Build handle native builds.
End-to-end tests
Detox or Maestro need emulators and are slow. Run them nightly or shard them; see test sharding.
Release builds
Decode signing keys from secrets at build time and upload the APK or AAB as an artifact.
Run it on faster machines
Android Gradle builds use every core and are the longest step. Change one line on each Linux job:
runs-on: [self-hosted, Linux, compiler-ci]
The job runs on a fresh 8 vCPU machine from compiler.dev, with fallback to your original runner. macOS is in early access. See speed up React Native on GitHub Actions and pricing.
FAQ
Do I need Watchman?
No, not for Jest in CI. Use --watchman=false if Jest warns about it.
Why is my Android build so slow the first time?
Gradle downloads dependencies and compiles native code. Caches fix later runs.
Can I build iOS on Linux?
No. iOS builds need macOS and Xcode.
Should I run Metro bundling in CI?
Only for release builds. For checks, lint, types and Jest are enough.
Related
- Speed Up React Native in GitHub ActionsSpeed up React Native CI in GitHub Actions: Gradle, CocoaPods and Metro caching, JS checks on Linux, and keeping macOS minutes to a minimum.
- .NET GitHub Actions Workflow TemplateCopy-paste GitHub Actions CI for .NET with NuGet caching, restore, build and test steps, a SQL Server service option, concurrency and permissions.
- Django GitHub Actions Workflow TemplateCopy-paste GitHub Actions CI for Django with a Postgres service container, pip caching, migrations check and tests, plus concurrency and permissions.
- Docker Build GitHub Actions Workflow TemplateCopy-paste GitHub Actions workflow to build Docker images with Buildx, GitHub cache layers and a push to GHCR on main, with minimal permissions.