How to Distribute React Native Apps to Testers

React Native teams build once and test twice. You write a single codebase, but the moment you need to get a build onto a tester’s phone, you’re dealing with two platforms, two build systems, and two very different distribution headaches. The distribution step shouldn’t be the bottleneck that slows your release cycle.

Whether you’re running a bare React Native project or using Expo’s managed workflow, getting test builds into your team’s hands quickly is what separates teams that ship fast from teams stuck waiting on TestFlight review queues. In this guide, we’ll walk through building release artifacts from both workflows, uploading them for distribution, automating the process with CI/CD, and how the available tools stack up against each other.

Expo vs. Bare Workflow: Both Produce APK and IPA

Before we get into distribution, let’s clarify something: regardless of whether you’re using the bare React Native CLI or Expo’s managed workflow, the end result is the same, an .apk file for Android and an .ipa file for iOS. These are the standard binary formats that any distribution platform, including TestApp.io, can work with.

The difference is how you produce those files, not what you produce.

Building Release Artifacts: Bare Workflow

Android (APK)

For a bare React Native project, building a release APK is done through Gradle. From your project root:

cd android
./gradlew clean
./gradlew assembleRelease

Before this works, you need a signing keystore configured in android/app/build.gradle. If you haven’t set one up yet, generate it with:

keytool -genkeypair -v -storetype PKCS12 \
  -keystore my-upload-key.keystore \
  -alias my-key-alias -keyalg RSA \
  -keysize 2048 -validity 10000

Your signed APK will be at android/app/build/outputs/apk/release/app-release.apk.

iOS (IPA)

For iOS, you’ll need a Mac with Xcode installed. Open your .xcworkspace file:

open ios/YourApp.xcworkspace

Then:

  1. Set the active scheme to Release (Product → Scheme → Edit Scheme → set Build Configuration to Release).
  2. Select Any iOS Device (arm64) as the build target.
  3. Go to Product → Archive.
  4. Once the archive completes, click Distribute App and choose Ad Hoc or Development distribution to export an .ipa file.
⚠️
For tester distribution (not App Store), use an Ad Hoc or Development provisioning profile. Enterprise profiles work too if your organization has one. The IPA must be signed with a profile that includes your testers’ device UDIDs (for Ad Hoc).

For command-line builds (useful in CI), you can use xcodebuild:

xcodebuild -workspace ios/YourApp.xcworkspace \
  -scheme YourApp \
  -configuration Release \
  -archivePath build/YourApp.xcarchive \
  archive

xcodebuild -exportArchive \
  -archivePath build/YourApp.xcarchive \
  -exportPath build/ \
  -exportOptionsPlist ExportOptions.plist

Building Release Artifacts: Expo (EAS Build)

If you’re using Expo, EAS Build handles the compilation in the cloud, no local Android Studio or Xcode required for Android builds.

First, install the EAS CLI and configure your project:

npm install -g eas-cli
eas build:configure

To build installable binaries for tester distribution, set your eas.json build profile to use internal distribution:

{
  "build": {
    "preview": {
      "distribution": "internal",
      "android": {
        "buildType": "apk"
      },
      "ios": {
        "simulator": false
      }
    }
  }
}

Then build for both platforms:

eas build --profile preview --platform all

This produces an .apk for Android and an .ipa for iOS. Once the builds complete, download them from the EAS dashboard or CLI output.

ℹ️
Setting "distribution": "internal" tells EAS to produce an APK for Android and an ad-hoc signed IPA for iOS. This is exactly what you need for tester distribution outside the app stores.

Uploading to TestApp.io

Once you have your .apk and .ipa files, you have three ways to get them to your testers through TestApp.io:

1. Portal Upload (Manual)

The simplest approach: log into the TestApp.io Portal, navigate to your app, and drag-and-drop your build file. Your team gets notified instantly, and testers can install the build directly from their device’s browser, no app store review, no waiting.

2. CLI Upload (ta-cli)

For developers who prefer the command line, ta-cli lets you publish directly from your terminal:

ta-cli publish \
  --api_token YOUR_API_TOKEN \
  --app_id YOUR_APP_ID \
  --release both \
  --apk ./android/app/build/outputs/apk/release/app-release.apk \
  --ipa ./build/YourApp.ipa \
  --release_notes "Fixed login bug, updated onboarding flow" \
  --notify \
  --git_release_notes \
  --git_commit_id

Key flags:

  • --release: android, ios, or both
  • --apk / --ipa: Path to your build artifact
  • --release_notes: What changed in this build (up to 1,200 characters)
  • --notify: Automatically notify your team members
  • --git_release_notes: Append the latest git commit message to release notes
  • --git_commit_id: Include the git commit hash in release notes
  • --archive_latest_release: Automatically archive the previous release on upload

Generate your API token from Portal Settings → API Credentials.

3. CI/CD Integration (Automated)

This is where it gets powerful. Wire up your CI/CD pipeline to build and distribute on every push. No manual steps, no forgotten uploads, your testers always have the latest build.

CI/CD: GitHub Actions Workflow for React Native + TestApp.io

Here’s a complete GitHub Actions workflow that builds a React Native Android APK and uploads it to TestApp.io automatically:

Full setup guide: GitHub Actions setup guide

For iOS, you’d add a separate job running on macos-latest with the Xcode archive steps, or use Fastlane to simplify the iOS build and signing process.

💡
TestApp.io also integrates with Codemagic, Bitrise, CircleCI, and other CI providers. Check the GitHub Actions setup guide for the full reference.

Expo + EAS + GitHub Actions

If you’re using Expo, your workflow is even simpler since EAS Build handles the compilation remotely:

Full setup guide: GitHub Actions with Expo EAS guide

How TestApp.io Compares to the Alternatives

Let’s be real: there are other ways to get builds to testers. Here’s how they compare for React Native teams:

TestApp.io TestFlight Expo EAS Update
Android support ✅ APK upload ❌ iOS only ✅ JS-only OTA
iOS support ✅ IPA upload ✅ Full support ✅ JS-only OTA
Review required No Yes (first build per version) No
Native code changes ✅ Full binary ✅ Full binary ❌ JS bundle only
Setup complexity Low. upload and share Medium. Apple Developer account, provisioning Medium. Expo ecosystem required
CI/CD integration ✅ GitHub Actions, Fastlane, CLI ✅ Via Xcode / Fastlane ✅ Built-in EAS workflows
Team notifications ✅ Built-in (Slack, Teams, email) ❌ Manual or via App Store Connect ❌ Manual
Tester device management ✅ UDID collection + provisioning ✅ Via Apple Developer portal ❌ Not applicable (OTA)
Cost Free tier available. see pricing Requires $99/yr Apple Developer account Free tier + paid plans

A Note on CodePush

If you’re reading older React Native guides, you’ll see references to CodePush for over-the-air updates. CodePush is no longer available. Microsoft retired Visual Studio App Center on March 31, 2025, and CodePush went down with it. While Microsoft open-sourced the CodePush server for self-hosting, that’s a significant operational burden for most teams.

For OTA JavaScript bundle updates, Expo’s EAS Update is a solid alternative. But for distributing full native builds, which you need any time you change native modules, update React Native versions, or modify native configuration, you need a proper binary distribution tool.

Why Not Just Use TestFlight?

TestFlight is great for what it does, but it comes with friction for React Native teams:

  • iOS only. You still need a separate solution for Android. React Native teams need to test on both platforms.
  • Review delays. Your first build of each version goes through Apple’s review, which can take hours to days.
  • 90-day expiry. Builds expire after 90 days from upload.
  • Apple Developer account required. $99/year, and every tester needs to be invited through App Store Connect.
  • No built-in team notifications. You can’t automatically ping your Slack channel or Teams group when a new build is ready.

TestApp.io handles both platforms from one dashboard, with no review queue, instant installation links, and built-in notifications to Slack and Microsoft Teams.

Putting It All Together

Here’s the workflow that React Native teams use to eliminate distribution as a bottleneck:

  1. Develop in your React Native codebase as usual.
  2. Push to your main or develop branch.
  3. CI builds your APK and IPA automatically (GitHub Actions, Codemagic, or your CI of choice).
  4. ta-cli or the GitHub Action uploads the artifacts to TestApp.io.
  5. Testers get notified via Slack, Teams, or email and install the build in one tap.
  6. Feedback comes back fast, and you iterate on the next build.

No app store reviews. No waiting. No “can you re-send me the build?” messages in Slack.

Get Started

TestApp.io has a free tier that covers small teams, and setup takes about five minutes. Create your account, add your app, generate an API token, and you’re distributing.



If you’re already using CI/CD, add the GitHub Action or drop ta-cli into your pipeline script. Your testers will thank you.