How to Set Up CI/CD for an Expo React Native Application Using GitHub Actions

CI/CD is one of the most important practices of XP. Setting this up from the beginning helps identify and fix issues earlier, leading to faster time to market. At Saeloun, we ensure it’s established at the project’s start.

Let’s set up a CI/CD for an Expo React Native application. We’ll first configure the Continuous Integration (CI) process to run on each branch and then set up Continuous Deployment (CD) for the ‘develop’ or ‘main’ branch to create builds for the latest changes merged into these branches.

Continuous Integration

Using GitHub Actions, create a ci.yml file inside the .github/workflows folder at the project’s root. Define the workflow’s name and the action that triggers it:

name: CI
on: push

Workflows consist of jobs. Add a job named lint-and-test to lint the code and run test cases. Specify the machine type to process the job:

jobs:
  lint-and-test:
    runs-on: ubuntu-latest

Jobs comprise a series of steps. Add steps to cache and install node modules, then run lint and test cases. The final ci.yml file should look like this:

name: CI
on: [push]

jobs:
  lint-and-test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Find yarn cache location
        id: yarn-cache
        run: echo "::set-output name=dir::$(yarn cache dir)"

      - name: JS package cache
        uses: actions/cache@v1
        with:
          path: ${{ steps.yarn-cache.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-

      - name: Install Node Modules
        run: yarn install

      - name: Run Lint
        run: yarn lint

      - name: Run tests
        run: yarn test

After adding this file and pushing the code, GitHub Actions will run the workflow. You can view the results in the GitHub Actions tab.

Continuous Deployment

For Continuous Deployment, first create an EXPO_TOKEN from expo.dev and add it to the GitHub project’s settings to allow GitHub Actions to create a build.

Next, create the eas.json file in the project root. This file specifies different profiles for creating builds in various environments. For example, a preview profile for development builds. It also defines the packaging type, credentialsSource to sign the build, and the distribution channel.

In this case, credentialsSource is set to remote, meaning Expo will automatically create the credentials to sign the app:

{
  "cli": {
    "version": ">= 0.52.0"
  },
  "build": {
    "preview": {
      "distribution": "internal",
      "android": {
        "buildType": "apk"
      },
      "credentialsSource": "remote"
    },
    "production": {}
  },
  "submit": {
    "production": {}
  }
}

Now, create a cd.yml file inside the .github/workflows folder at the project’s root. Define the workflow’s name and the action, along with the branch name that triggers the workflow:

name: build
on:
  push:
    branches:
      - develop

Add the build job with ubuntu-latest as the runner machine. Include steps to fetch EXPO_TOKEN from the project’s settings, set environment variables, install Expo, cache and install node modules, and finally, create a build. The final cd.yml should look like this:

name: build
on:
  push:
    branches:
      - develop

jobs:
  build:
    name: EAS build
    runs-on: ubuntu-latest
    steps:
      - name: Check for EXPO_TOKEN
        run: |
          if [ -z "${{ secrets.EXPO_TOKEN }}" ]; then
            echo "You must provide an EXPO_TOKEN secret linked to this project's Expo account in this repo's secrets.
            Learn more: https://docs.expo.dev/eas-update/github-actions"
            exit 1
          fi

      - name: "Set ENV"
        run: echo "$(BASE_URL)"
        env:
          BASE_URL: https://exampleapp.com

      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Setup Node
        uses: actions/setup-node@v2
        with:
          node-version: 16.x
          cache: yarn

Leave a Reply

Your email address will not be published. Required fields are marked *