DEV Community

Muhammad Hasbi
Muhammad Hasbi

Posted on

How to Integrate React Native CLI and Detox into CircleCI

My First Experience Integrating React Native with CircleCI
A couple of days ago (22/11/2024), I got a task to integrate our React Native development app with CircleCI. My principal engineer provided the initial configuration, and I thought, "This shouldn’t be too hard—I just need to plug in the config and make it work."

But when I tried running it, the tests failed.

Image description

Here’s the configuration I started with:

version: 2.1

orbs:
  node: circleci/node@5.2.0
  android: circleci/android@2.5.0
  rn: react-native-community/react-native@7.3.0
  ruby: circleci/ruby@2.1.1

commands:
  detox_build_android:
    steps:
      - android/restore-gradle-cache
      - run: |
          npm install -g detox-cli react-native-cli
          yarn android:detox:build:emu
      - android/save-gradle-cache
  create_env_file:
    steps:
      - run:
          name: Creating .env file
          command: |
            cat \<< EOF > .env
            APP_ID=$APP_ID
            <another_env_property>
            EOF
      - persist_to_workspace:
          root: .
          paths:
            - .env

jobs:
  detox_android:
    executor:
      name: android/android-machine
      resource-class: large
      tag: "2023.08.1"
    steps:
      - checkout
      - create_env_file
      - run:
          name: Cat .env File
          command: cat .env
      - run:
          name: Install dependencies
          command: yarn install --frozen-lockfile
      - run:
          name: Generate release.keystore
          command: echo "$RELEASE_KEYSTORE" | base64 --decode > android/app/release.keystore
      # - detox_build_android
      - rn/android_emulator_start:
          device_name: Pixel_5_API_33
      # - run:
      #     name: Set APK Path
      #     command: echo "APK_PATH=android/app/build/outputs/apk/release/app-release.apk" >> $BASH_ENV
      - run:
          name: Wait for Emulator to Fully Boot
          command: |
            adb wait-for-device
            adb shell getprop sys.boot_completed | grep 1 || sleep 5
            adb shell input keyevent 82
      - detox_build_android
      - run:
          name: Run Detox Tests
          command: detox test -c android.emu.release --loglevel verbose

workflows:
  test_and_distribute:
    jobs:
      - detox_android:
          filters:
            branches:
              only:
                - main
Enter fullscreen mode Exit fullscreen mode

A New Challenge
To be honest, I had never worked with anything related to CI/CD before, so this was my first experience—exciting, but also a little daunting! 😅

I dove into trial and error mode, trying everything I could think of. After what felt like 374 attempts, I decided to explore the documentation more thoroughly.

Image description

That’s when I stumbled upon a helpful blog post: React Native E2E Tests and Automatic Deploys (Detox + Fastlane + CircleCI).

This blog provided a lot of insight into the flow I needed to follow to get the tests running.

Debugging the Configuration
One key thing to note about CircleCI’s free plan is its limitations. For example, apps can only be run on Linux. If you need to test with iOS, you’ll have to upgrade to a paid plan.

After carefully reviewing the configuration provided by my engineer, I realized one critical step was missing: starting the Metro bundler.

I checked the CircleCI React Native documentation and found a specific command to run Metro. After adding this step to the config, everything finally worked smoothly! yay !

Image description

Image description

Image description

Image description

Image description

My Working Configuration
Here’s the configuration I used to run React Native CLI with Detox on CircleCI. Keep in mind that since I’m using the free plan, this setup only works for Android. To run tests on iOS, you’ll need to subscribe to a paid plan.

version: 2.1

orbs:
  rn: react-native-community/react-native@8.0.0
  android: circleci/android@3.0.2

commands:
  install_init:
    steps:
      - rn/yarn_install
      - run:
          name: Install Global CLI Tools
          command: |
            npm install -g detox-cli react-native-cli
            react-native --version

jobs:
  checking:
    executor:
      name: rn/linux_js
      node_version: '18.2'

    steps:
      - checkout
      - install_init
      - run:
          command: yarn checker // run linter, prettier, jest
      - persist_to_workspace:
          paths:
            - .
          root: .

  test_android:
    executor:
      name: android/android_machine
      resource_class: large
      tag: '2023.10.1'

    steps:
      - attach_workspace:
          at: .
      - rn/android_emulator_start:
          build_tools_version: '33.0.0'
          device_name: Pixel_5_API_33
          platform_version: android-33
      - install_init
      - rn/metro_start
      - run:
          name: Detox Test
          command: yarn detox:test:android -l verbose

workflows:
  e2e_test:
    jobs:
      - checking
      - rn/android_build:
          name: build_android
          build_image_version: 'v15.0'
          resource_class: large
          build_cache: false
          gradle_options: '-Xmx4g -XX:MaxMetaspaceSize=512m'
          build_type: debug
          requires:
            - checking
      - test_android:
          requires:
            - build_android
Enter fullscreen mode Exit fullscreen mode

Lessons Learned
This experience taught me the importance of reading the documentation thoroughly and not being afraid to experiment. CI/CD might seem intimidating at first, but once you understand the flow, it becomes manageable—even fun!

Top comments (0)