Automate Build & Deploy for React production build with gitlab-ci to Linux base server (AWS)

Right now, as everyone wants to automate everything, this post will show you how you can automate the react build and deployment. I am using create-react-app getting started with react and assuming you have a similar setup.

Setup .gitlab-yml file for Gitlab Auto deploy

Deploy React Build with gitlab-ci

image: node:10

cache: 
    paths:
         node_modules/

This line defines the node version that should be used by the docker instance of shared gitlab-runner and the path defines to cache the node_modules dir.

before_script:
    - apt-get update -qq && apt install -y openssh-client openssh-server
    - mkdir -p ~/.ssh- echo -e "$SSH_PRIVATE_KEY" > ~/deploy.pem
    - chmod 400 ~/deploy.pem
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

The code in before_script runs before the actual execution. This is to install and setup pre-requisites for deployment like openssh. Also, as I am using AWS EC2 instance to host the project, I have a .pem file to logging in to server via ssh, which is stored in gitlab variables as SSH_PRIVATE_KEY and accessed by $SSH_PRIVATE_KEY in yaml file. So, I’m adding the public-key to a file and updating permission of the file as per AWS guidelines.

deploy_production:
    only:
        refs:
            - master
    stage: deploy
        environment: 
            name: production
        script:
            - npm install
            - REACT_APP_SERVER=production CI=true npm run build
            - scp -i ~/deploy.pem -r build/* $USER_NAME@$SERVER_IP:/var/www/html/provider

deploy_production & deploy_staging blocks are almost similar except deploy_production have all the setup for production build and master branch of react whereas deploy_staging have setup for staging build and staging branch. You can define any other branch you want in refs

Here's the whole .gitlab-ci.yml file:

image: node:10

cache:
  paths:
    - node_modules/

before_script:
  - apt-get update -qq && apt install -y openssh-client openssh-server
  - mkdir -p ~/.ssh     
  - echo -e "$SSH_PRIVATE_KEY" > ~/deploy.pem     
  - chmod 400 ~/deploy.pem     
  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

deploy_production:
  only:
    refs:
      - master
  stage: deploy
  environment: 
    name: production
  script:
    - npm install
    - REACT_APP_SERVER=production CI=true npm run build
    - scp -i ~/deploy.pem -r build/* $USER_NAME@$SERVER_IP:/var/www/html/provider

deploy_staging:
  only:
    refs:
      - staging
  stage: deploy
  environment: 
    name: staging
  script:
    - npm install
    - REACT_APP_SERVER=staging CI=false npm run build
    - scp -i ~/deploy.pem -r build/* $USER_NAME@$SERVER_IP:/var/www/html/staging-provider

Gitlab ci/cd has 3 stages: test, build & deploy, I have merged the build and deploy part in the deploy stage, but you can implement it separately.

The script block runs the essential script to make the project live. Here, for production, I set the environment variable CI to true that’ll consider any warning pops-up while building as error, so make sure there is no warning (or error of course) else you can set that to false as I did for staging.

At last, you need to define the dir path where you want to upload/copy the build

We are using scp command to sync the build folder to our server. Basically, it uploads the build folder to our server.

You can easily set up the variables mentioned in code (i.e. SSH_PRIVATE_KEY, USER_NAME, SERVER_IP) from your project’s CI/CD settings. Visit this link for reference.

Note: While setting up environment variables, if you want to use it for protected branches only (i.e master/production) remember to select that option.

After setting up the variables, just push or merge to the branch you’ve specified in yaml file and check the CI/CD Pipeline. It will assign the job to the shared gitlab-runner (Also, you can set up your own gitlab-runner on your server and you can use your own docker image too) and execute these commands.

Another thing is, if you're using Github Actions, the yaml file will mostly remain the same, you just need to update its location from root of your project to .github directory.

So, that's it, your react app is deployed to aws ec2 server. Reach out to me in case you catch any issue while setting up.

PS: This kind of setup can be achieved for a basic node and express.js app too, you just need to update some commands to run it. I'm planning to publish one more blog regarding this using docker.


Did you find this article valuable?

Support Maulik Sompura by becoming a sponsor. Any amount is appreciated!