Skip to main content
cd ../blog
React NativeCI/CDFastlane

Shipping React Native to both stores with Fastlane and GitHub Actions

By Emeka OkezieMay 2, 20261 min read16 views

Manual React Native releases are where momentum goes to die: bump the version, build locally, wait, upload, fix signing, repeat. Here's the pipeline that automated it away.

One lane per platform

Fastlane describes each release as a lane. Keep them boring and repeatable:

fastlane/Fastfile
platform :ios do
  lane :beta do
    setup_ci
    match(type: "appstore", readonly: true)
    build_app(scheme: "App")
    upload_to_testflight(skip_waiting_for_build_processing: true)
  end
end

Wire it to CI

GitHub Actions runs the lane on every tagged commit, so a release is just a git tag:

.github/workflows/release.yml
on:
  push:
    tags: ["v*"]
 
jobs:
  ios:
    runs-on: macos-14
    steps:
      - uses: actions/checkout@v4
      - run: bundle install
      - run: bundle exec fastlane ios beta
        env:
          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}

The gotchas that cost me a day

  • Signing: use match to keep certificates in a private git repo. Never wrestle Xcode signing in CI.
  • Version codes: derive them from the run number so builds never collide.
  • Caching: cache CocoaPods and Gradle, or every run pays the full install tax.

Tag, push, walk away. Releases went from a dreaded afternoon to a 12-minute pipeline.