Automating your React Native library's build process
Tags: react, reactnative, actionshackathon, github
Published: 2020-09-15 10:10:24

In my [last blog post](https://dev.to/dani_akash_/getting-started-with-your-react-native-library-3c3a), I explained about the tools we will be using for your react native library. We are now going to automate the build process.

All open-source Github repositories have free Github Actions available with which we can automate most of our workflows. I'll be using Github Actions throughout the automation process. 

The library's build consists of the following items ﹣
- Linting
- Running Tests
- Publishing the test coverage
- Publishing the example app to expo
- Publishing the stories to chromatic
- Publish the storybook which contains documentation as a static site

You can find my build workflow in the [.github/workflows/build.yml](https://github.com/react-native-toolkit/react-native-better-image/blob/master/.github/workflows/build.yml) file of my [react-native-better-image](https://github.com/react-native-toolkit/react-native-better-image) project. This is how the build process should look like ﹣

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/o0kep5llpseapcik3fme.png)

## When to trigger the workflow
I wanted the build workflow to ensure the master branch is always stable. Hence it will run on all the pushes to master. But it will not run for tags, as I have planned another release workflow for this

```yml
name: build
on:
  push:
    branches:
      - master
    tags:
      - '!*' # Do not execute on tags
    paths:
      - example/*
      - src/*
      - test/*
      - __tests__/*
      - '*.json'
      - yarn.lock
      - .github/**/*.yml
```
## Linting
Since we are using [react-native-community/bob](https://github.com/react-native-community/bob) in our project, we can run both lint & typescript scripts in the `package.json` file which is enough to complete the lint process

```yml
  lint:
    name: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - uses: actions/setup-node@master
        with:
          node-version: 12.x
      - run: npx yarn bootstrap
      - run: npx yarn typescript
      - run: npx yarn lint
```
## Testing & Coverage
For displaying the test coverage, I decided to use [code climate for open source projects](https://codeclimate.com/oss/). They also have a nice action available at [paambaati/codeclimate-action](https://github.com/paambaati/codeclimate-action).

Code climate checks your code for best practices and provides you with maintainability metrics. Along with that, you'll also get code coverage reports. Once you setup code climate you can add their badges to your repo that gives everyone a live code quality score ﹣

[![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/9czp25bmkrhieeljgqpc.png)](https://github.com/react-native-toolkit/rex-state)

The following configuration is used for running tests ﹣

```yml
  test:
    strategy:
      matrix:
        platform: [ubuntu-latest, macOS-latest]
        node: ['12.x']
    name: test/node ${{ matrix.node }}/${{ matrix.platform }}
    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@master
      - uses: actions/setup-node@master
        with:
          node-version: ${{ matrix.node }}
      - run: npx yarn bootstrap
      - run: npx yarn test
```

Once both linting & testing jobs are completed, you have to push your code coverage to code climate. Following their [docs](https://docs.codeclimate.com/docs/github-actions-test-coverage) you need to create a [secret](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets) in your repository with name `CC_TEST_REPORTER_ID` after which add the following configuration

```yml
  coverage:
    needs: [test, lint]
    name: coverage
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - uses: actions/setup-node@master
        with:
          node-version: 12.x
      - run: npx yarn bootstrap
      - uses: paambaati/codeclimate-action@v2.5.3
        env:
          CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
        with:
          coverageCommand: npx yarn test --coverage
          debug: true
```
## Publish example app to expo
Publish should also happen after the lint & test jobs. This time we will be using the [expo/expo-github-action](https://github.com/expo/expo-github-action). As per the action's [docs](https://github.com/expo/expo-github-action), you'll have to add your expo username & password to your repo's secrets under the name `EXPO_CLI_USERNAME` & `EXPO_CLI_PASSWORD`.

> If you have an organization, you can add it under the [organization secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-an-organization) and share it with all your repositories!

The first step to publish is to run `yarn bootstrap` command. However, the next step `expo run` should run inside the `example` directory. For this we will use the `working-directory` config

```yml
  publish:
    needs: [test, lint]
    name: Publish example app to Expo 🚀
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v1
        with:
          node-version: 12.x
      - uses: expo/expo-github-action@v5
        with:
          expo-version: 3.x
          expo-username: ${{ secrets.EXPO_CLI_USERNAME }}
          expo-password: ${{ secrets.EXPO_CLI_PASSWORD }}
      - run: npx yarn bootstrap
      - working-directory: example
        run: expo publish
```
You'll get a published page for your library's example app. You can check out for the page of my react-native-better-image library's [example app](https://expo.io/@daniakash/react-native-better-image-example).

## Publish stories to chromatic
Similar to expo, chromatic also have a GitHub action available in [chromaui/action](https://github.com/chromaui/action). You have to create a new project in chromatic and get your project token. Then add it to your repository's secrets under the name `CHROMATIC_PROJECT_TOKEN`

We need to run chromatic action inside the example directory since our storybook lives in this directory. The chromaui/action didn't have an option to run it inside a specific directory. So I had to manually add the following script in my example app's `package.json` file ﹣
```json
"chromatic": "npx chromatic"
```
Then added the following workflow configuration which manually runs chromatic ﹣
```yml
  chromatic:
    needs: [test, lint]
    name: Publish storybook to chromatic 🧪
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v1
        with:
          node-version: 12.x
      - run: npx yarn bootstrap
      - run: npx yarn chromatic
        working-directory: example
        env:
          CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
```
## Publish storybook as a static site
I used Netlify to publish my storybook as a static site. I was initially planning to use GH Pages, but I needed the 1-click rollback & Deploy Previews offered by [netlify](https://www.netlify.com/github-pages-vs-netlify/). I installed the [Netlify app](https://github.com/apps/netlify) which automatically takes care of the building the repo & deploy previews so I didn't have to write any actions config.

If you are interested to use GitHub pages for your library, you can use the [Deploy to GitHub Pages](https://github.com/marketplace/actions/deploy-to-github-pages) action for this purpose.

You can also try [Netlify CLI](https://cli.netlify.com/) if you want to configure deploys with netlify through GitHub Actions.

This build workflow is actively used in two of my libraries [rex-state](https://github.com/react-native-toolkit/rex-state) & [react-native-better-image](https://github.com/react-native-toolkit/react-native-better-image)

In the [next blog](https://dev.to/dani_akash_/automating-the-review-process-of-your-react-native-library-s-prs-4457) post, I'll explain how to set up the review workflow!