GitHub Actions CI/CD for React app hosted in GitHub Pages
Tags: react, cicd, githubactions, github
Published: 2023-04-12 04:13:55

---
title: GitHub Actions CI/CD for React app hosted in GitHub Pages
published: true
date: 2023-04-12 03:57:12 UTC
tags: react, cicd, githubactions, github
canonical_url: https://blog.vishnuprasaath.dev/github-actions-cicd-react
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hr6s1wjyaaybqgep1kjz.png
---

Let's create a simple GitHub Actions workflow that I use on my projects with React.

This workflow created on [GitHub Actions](https://github.com/features/actions) will take care of automatically building and deploying the app on [GitHub Pages](https://pages.github.com/). Can add testing and linting if needed. We will be triggering this workflow on every push event on the **main/master branch**.

Consider going over my prev [blog-post](https://dev.to/pvishnuprasaath/host-react-app-in-github-pages-35p9) on setting up your React app hosting on GitHub Pages.

## Configure React App

A tiny bit of configuration is required on the React app side.

Add the below `homepage` property to your `package.json` file.

```
For free GitHub user site, add this: 
"homepage": "https://{username}.github.io"

If you own a domain, add this:
"homepage": "https://mydomainname.com"

```

![img1](https://cdn.hashnode.com/res/hashnode/image/upload/v1681030015020/bc19bfff-fb70-457e-b0ff-6a0e5a2ab97d.png?auto=compress,format&format=webp)

Add both **predeploy** and **deploy** property scripts to the `package.json` as below

```
"predeploy": "npm run build",
"deploy": "gh-pages -d build"

```

![img2](https://cdn.hashnode.com/res/hashnode/image/upload/v1681030290187/7fb123aa-6a9a-4864-9b67-b36cba2bbbf1.png?auto=compress,format&format=webp)

* * *

## Getting Started with GitHub Actions WorkFlow

First, create a `workflow.yml` file inside `.github\workflows` dir

![img3](https://cdn.hashnode.com/res/hashnode/image/upload/v1681236230142/0966325b-62b7-495c-b6b6-dcc088fd1c48.png)

The complete workflow is as below:

```
name: Build and Deploy

on:
  push:
    branches: ["main"]

permissions:
  contents: write

jobs:
  build-deploy:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18.x]

    steps:
    - name: Checkout
      uses: actions/checkout@v3
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        cache: "npm"
    - name: Install Packages
      run: npm ci
    - name: Build
      run: npm run build
    #- name: Test
    # run: npm test
    - name: Deploy🚀
      uses: JamesIves/github-pages-deploy-action@v4
      with:
        branch: gh-pages
        folder: build

```

Let's understand each field put up here.

The `on` section describes the **events** which should trigger the job. In this workflow we want the jobs to be triggered whenever someone does a `push` into the `main` branch.

```
on:
  push:
    branches: ["main"]

```

Our job needs write access to modify files in the `gh-pages` branch. The final build files are pushed into the gh-pages branch of your repo. Using GitHub Secrets can also help achieve the same result.

```
permissions:
  contents: write

```

Let's get into the interesting section of defining the actual **job** to be executed. _build-deploy_ is the user-defined name for the job.

We need to mention the type of **runner** on which the job needs to be executed. Pick `ubuntu-latest`.

```
jobs:
  build-deploy:
    runs-on: ubuntu-latest

```

When we want the same job to be executed on multiple variants of the node version, we can use the `strategy matrix`. Here we will stick to just 1 node version.

```
strategy:
  matrix:
    node-version: [18.x]

```

The first step in any job is to **checkout** the repo at that particular instance. This ensures we have the latest code base for the further process.

```
- name: Checkout
  uses: actions/checkout@v3

```

Set up **Node.js** on the freshly brought-up runner. To optimize the workflow execution we can **cache** the npm packages.

```
 - name: Use Node.js ${{ matrix.node-version }}
   uses: actions/setup-node@v3
   with:
     node-version: ${{ matrix.node-version }}
     cache: "npm"

```

Then we instruct the job to perform `npm ci`, `npm run build`, `npm test`. This covers the **Build** and **Test** phase.

```
- name: Install Packages
  run: npm ci
- name: Build
  run: npm run build
- name: Test
  run: npm test

```

Finally, it's time to **deploy** and give life to the app. We will use the popular `JamesIves/github-pages-deploy-action@v4` action for deploying straight into the gh-pages. Specify the **branch name** on where the built files will be pushed to. Also, mention the **source dir** from where to find the built files. In our case, `npm run build` will dump files into the `./build` dir.

```
- name: Deploy 🚀
  uses: JamesIves/github-pages-deploy-action@v4
  with:
    branch: gh-pages
    folder: build

```

In the **Actions** tab, we can see the execution status and log.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681271645127/d1988253-0749-41c4-a1e4-2a68cb25d8aa.png)

## References

- [https://github.com/features/actions](https://github.com/features/actions)

- [https://pages.github.com/](https://pages.github.com/)

- [https://create-react-app.dev/docs/deployment#github-pages](https://create-react-app.dev/docs/deployment#github-pages)

- [https://help.github.com/pt/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows](https://help.github.com/pt/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows)

- [https://github.com/actions/cache](https://github.com/actions/cache)