CICD for React Native - Android and iOS
Tags: reactnative, cicd, android, ios
Published: 2023-01-11 05:33:27

When creating a React Native application, it soon becomes evident that generating an APK each time a change is made becomes really tedious. Coupled with the fact that you need to Archive the build on Xcode and Distribute to Appstore for either publishing on Testflight or Appstore.

I used two different approaches for auto deployment on both platforms but both are trigger on pushing to a particular branch.

While in development, I use the `dev` branch as the active branch all changes are merged into

- For Android, I decided to go with `GitHub Actions` that then pushes the app to `Firebase App Distribution` and notification sent out to the testers via email
- For iOS, `XCode Cloud` did the job for me which is published to Testflight automatically and notification sent out to the users via push notification and email

Let's get right in


## Android using GitHub Action and Firebase App Distribution
1. Create a `.github/workflows` folder in the root of the project
2. Create a `build.yml` file inside the `.github/workflows`

![build.yml creation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p71ftd3tbf6xeptcrhgw.png)

3. Add the code below. Pretty self explanatory and the name explains each action

```
name: Build And Deploy App To Firebase Distribution

on:
  push:
    branches:
      - dev

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: set up JDK 1.8
        uses: actions/setup-java@v3
        with:
          distribution: temurin
          java-version: 11
      - name: Setup Android SDK
        uses: android-actions/setup-android@v2
      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2
      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: echo "::set-output name=dir::$(yarn cache dir)"
      - name: Restore node_modules from cache
        uses: actions/cache@v2
        id: yarn-cache
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - name: Install dependencies
        run: yarn install
      - name: Make Gradlew Executable
        run: cd android && chmod +x ./gradlew
      - name: build release
        run: cd android && ./gradlew clean && ./gradlew assembleRelease --no-daemon
      - name: Upload artifact to Firebase App Distribution
        uses: wzieba/Firebase-Distribution-Github-Action@v1
        with:
          appId: ${{secrets.FIREBASE_APP_ID}}
          token: ${{secrets.FIREBASE_TOKEN}}
          groups: test-group
          file: android/app/build/outputs/apk/release/app-universal-release.apk
```
4. You'll need to specify the FIREBASE_APP_ID and FIREBASE_TOKEN gotten from Firebase when setting up Firebase App distribution

![GitHub Secret](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wjfo8yz0etetllz3nrqk.png)

5. Once that is done and you push, the CICD should kick in. The progress and result can be accessed under the `Actions` tab.

![GitHub Action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ibcvcd3f20umdukruiu0.png)

#### Some debugging tips
- try to run `cd android && ./gradlew clean && ./gradlew assembleRelease` locally first and ensure it's successful
- The GitHub Action event will point out what is wrong if the build fails for you to debug and fix

## iOS using XCode and Testflight
1. Create a `.ci_scripts` folder in `/ios` folder of your project
2. Create a `ci_post_clone.sh` file inside the `.github/workflows`

![iOS folder structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w5e7l48612ev0k8b389s.png)

3. Paste this code in `ci_post_clone.sh` file

```
#!/bin/sh

export HOMEBREW_NO_INSTALL_CLEANUP=TRUE
brew install cocoapods
# have to add node yourself
brew install node@16
# link it to the path
brew link node@16

brew install yarn

# Install dependencies you manage with CocoaPods.
yarn
pod install
# the sed command from RN cant find the file... so we have to run it ourselves
sed -i -e  $'s/ && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0)//' /Volumes/workspace/repository/ios/Pods/RCT-Folly/folly/portability/Time.h
```

**OPTIONAL**: Add this to your `Info.plist` file to resolve the encryption dialog check required before publishing an app to Testflight

```
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
```

4. Push to the github branch you want to use for deployment. In my case `dev`

5. Launch Xcode and go to `Product` and Select `Xcode Cloud`
6. Follow the prompt and connect Xcode cloud to your GitHub project, specifying the `dev` branch or whatever branch you are working on
7. The remaining work will be done on the Appstore connect interface. Will update this article with those additional steps later on

Let me know if you have any questions.

Voila