React Native iOS Pipeline
Issue #12876 - CI/CD implementation tracking
Apple's tightly integrated mobile platform demands strict code signing and provisioning before anything reaches a device. This guide walks the full KBVE pipeline — certificates and profiles, GitHub secrets, CI/CD on macOS runners, local build testing, and the shared Apple setup that UE5 iOS builds reuse.
Certificates, provisioning profiles, and the Team ID are shared infrastructure — complete the Apple Developer setup once and reuse the same credentials across React Native, UE5, and future frameworks.
On this page
Apple Developer prerequisites, development and distribution certificates, and the three flavors of provisioning profile.
GitHub Actions on macOS runners — unsigned simulator builds, signed IPAs, keychain import, and exportOptions.plist.
Certificate not found, profile mismatches, signing errors, and CocoaPods cache fixes.
UnrealBuildTool and RunUAT reuse the same Apple credentials — with bigger binaries and precompiled Metal shaders.
Start here
iOS development requires a macOS environment and enrollment in the Apple Developer Program ($99/year) to deploy applications to physical devices and distribute through the App Store. This guide covers code signing, provisioning profiles, CI/CD setup, and best practices for building iOS applications at KBVE.
Jump to code signing, GitHub secrets, the CI/CD workflow, troubleshooting, or UE5 iOS builds.
Our React Native iOS applications use Expo for streamlined development and deployment workflows, with custom native modules when needed for advanced features.
Certificates & profiles
Apple’s code signing system ensures app integrity and prevents unauthorized modifications. All iOS apps must be signed before deployment to devices or the App Store.
Apple Developer Account
Development Environment
xcode-select --installsudo gem install cocoapodsBundle Identifier
com.kbve.appiOS App Development Certificate
Used for testing on physical devices during development.
# Generate via Xcode (automatic)# Or manually via Keychain Access → Certificate Assistant → Request from CA
# Export as .p12 (for CI/CD)# Keychain Access → Right-click certificate → ExportApple Distribution Certificate
Required for App Store and ad-hoc distribution.
# Generate via Apple Developer portal or Xcode# Export as .p12 file with password for GitHub secrets
# Export to base64 for GitHub Actionsbase64 -i certificate.p12 | pbcopyProvisioning profiles link certificates, app IDs, and device UDIDs together.
| Type | Use Case | Device Registration |
|---|---|---|
| Development | Testing on registered devices | Required |
| Ad Hoc | Beta testing outside TestFlight | Required (max 100 devices) |
| App Store | App Store distribution | Not required |
# Export provisioning profile to base64base64 -i profile.mobileprovision | pbcopySecure credentials
Add these secrets to your repository for CI/CD workflows.
| Secret Name | Description | How to Generate |
|---|---|---|
APPLE_CERT_DATA | Base64-encoded .p12 certificate | base64 -i certificate.p12 | pbcopy |
APPLE_CERT_PASSWORD | Password for .p12 file | Set when exporting certificate |
PROVISIONING_PROFILE_DATA | Base64-encoded .mobileprovision | base64 -i profile.mobileprovision | pbcopy |
Automated builds
Our React Native iOS builds use GitHub Actions with macOS runners.
Located at .github/workflows/ci-react-native-ios.yml
For development and CI testing (no certificates required)
# Trigger via GitHub Actions# task: build# skip_signing: trueProduces unsigned simulator build (x86_64) for testing purposes.
For device testing and App Store distribution
# Requires GitHub secrets configured# task: build# skip_signing: falseProduces signed IPA for TestFlight or App Store submission.
Verify macOS runner environment
# task: mac-setupValidates Xcode, Node.js, CocoaPods installation.
Packaging the IPA
The exportOptions.plist file controls how the IPA is packaged.
exportOptions.plist Template:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict> <key>method</key> <string>app-store</string> <key>teamID</key> <string>YOUR_TEAM_ID</string> <key>uploadBitcode</key> <false/> <key>compileBitcode</key> <false/> <key>uploadSymbols</key> <true/> <key>signingStyle</key> <string>manual</string> <key>provisioningProfiles</key> <dict> <key>com.kbve.app</key> <string>YOUR_PROVISIONING_PROFILE_NAME</string> </dict></dict></plist>Actions internals
- name: Import signing certificate env: APPLE_CERT_DATA: ${{ secrets.APPLE_CERT_DATA }} APPLE_CERT_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }} run: | # Create temporary keychain KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db KEYCHAIN_PASSWORD=$(uuidgen)
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH security set-keychain-settings -lut 21600 $KEYCHAIN_PATH security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# Import certificate echo "$APPLE_CERT_DATA" | base64 --decode > certificate.p12 security import certificate.p12 \ -P "$APPLE_CERT_PASSWORD" \ -A \ -t cert \ -f pkcs12 \ -k $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH- name: Install provisioning profile env: PROVISIONING_PROFILE_DATA: ${{ secrets.PROVISIONING_PROFILE_DATA }} run: | mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles echo "$PROVISIONING_PROFILE_DATA" | base64 --decode > \ ~/Library/MobileDevice/Provisioning\ Profiles/profile.mobileprovision- name: Build signed app run: | xcodebuild \ -workspace *.xcworkspace \ -scheme "kbvereactnative" \ -configuration Release \ -sdk iphoneos \ -archivePath ./build/App.xcarchive \ archive
xcodebuild \ -exportArchive \ -archivePath ./build/App.xcarchive \ -exportPath ./build \ -exportOptionsPlist exportOptions.plistVerify locally
Verify builds work locally before pushing to CI/CD.
# Navigate to React Native appcd apps/kbve/kbve-react-native
# Generate iOS native projectnpx expo prebuild --platform ios --clean
# Install CocoaPods dependenciescd iospod install
# Build for simulator (unsigned)xcodebuild \ -workspace *.xcworkspace \ -scheme kbvereactnative \ -configuration Release \ -sdk iphonesimulator \ build
# Build for device (requires signing)xcodebuild \ -workspace *.xcworkspace \ -scheme kbvereactnative \ -configuration Release \ -sdk iphoneos \ -archivePath ./build/App.xcarchive \ archiveWhen builds break
Symptoms: errSecInternalComponent or certificate errors during build
Solutions:
APPLE_CERT_DATA is valid base64APPLE_CERT_PASSWORDSymptoms: No profiles for 'com.kbve.app' were found
Solutions:
com.kbve.appSymptoms: Code signing is required for product type 'Application'
Solutions:
Symptoms: pod install fails or missing native modules
Solutions:
# Clear CocoaPods cachecd iospod cache clean --allrm -rf Pods Podfile.lock
# Reinstallpod install --repo-updateSame Apple, bigger binary
KBVE also builds iOS applications using Unreal Engine 5. The UE5 iOS pipeline shares the same Apple Developer infrastructure (certificates, provisioning profiles, Team ID) as React Native builds.
Key Differences from React Native:
GenerateProjectFiles.sh or UE5 EditorThe UE5 iOS CI/CD pipeline is currently under development. See Issue #12875 for tracking.
Planned Tasks:
Shared Infrastructure:
Both React Native and UE5 iOS builds use the same:
APPLE_CERT_DATA, APPLE_CERT_PASSWORD)PROVISIONING_PROFILE_DATA)# Generate Xcode project from .uproject# (Run on macOS with UE5 installed)/Path/To/UE_5.X/Engine/Build/BatchFiles/Mac/GenerateProjectFiles.sh \ -project="/Path/To/YourProject.uproject" \ -platforms=iOS
# Build via UnrealBuildTool/Path/To/UE_5.X/Engine/Build/BatchFiles/RunUBT.sh \ YourProjectEditor iOS Development \ -project="/Path/To/YourProject.uproject"
# Package for distribution/Path/To/UE_5.X/Engine/Build/BatchFiles/RunUAT.sh BuildCookRun \ -project="/Path/To/YourProject.uproject" \ -platform=iOS \ -clientconfig=Shipping \ -cook -stage -archive -packageGet shipping
Enroll in Apple Developer Program
Generate Certificates
Create Provisioning Profile
com.kbve.appConfigure GitHub Secrets
APPLE_CERT_DATA, APPLE_CERT_PASSWORD, PROVISIONING_PROFILE_DATAexportOptions.plist with Team ID and profile nameTest Build Workflow
skip_signing: true first (unsigned)skip_signing: false (signed)Optional: Setup Fastlane
matchQuestions
A macOS machine with Xcode, and enrollment in the Apple Developer Program at $99/year. Membership is required to test on physical devices and distribute through the App Store. You also need a signing certificate, a provisioning profile, and a unique bundle identifier such as com.kbve.app.
A signing certificate proves your identity to Apple and signs the app binary. A provisioning profile links that certificate, the app ID, and (for development/ad-hoc) allowed device UDIDs, authorizing where the app can run. App Store profiles do not need device registration.
Store the .p12 certificate and .mobileprovision profile as base64 GitHub secrets, then in the workflow create a temporary keychain, import the decoded certificate, install the profile, and build with xcodebuild archive plus exportArchive using an exportOptions.plist. Never commit certificates to the repo.
Yes. A simulator build for the iphonesimulator SDK does not require signing, so CI can produce an unsigned x86_64 build for testing. Signing is only required for device installs, TestFlight, and App Store submission using the iphoneos SDK.
Yes. UE5 iOS builds reuse the same Apple Developer certificates, provisioning profiles, and Team ID as React Native builds. The difference is the build system — UE5 uses UnrealBuildTool and RunUAT instead of xcodebuild directly, and produces larger binaries with precompiled Metal shaders.