DEV Community

Kirtish Patil
Kirtish Patil

Posted on

Creating a fully automated Multi-branch CI/CD pipeline for React

By Kirtish Patil · October 29, 2024

The development of React applications has been greatly facilitated by tools like Vite, which offers a faster development experience with hot module replacement and simpler configuration. However, the development experience doesn't end there. Running tests, checking for linting errors, and deploying to a staging environment to see how updates from developers work together can also take up considerable time for developers. Many companies still perform these processes manually, which can slow down the workflow.

In this article, we will create a multibranch CI/CD pipeline for a React application to automate the building, testing, and deployment processes using open source tools like Docker, Jenkins, and Ansible.

CI CD pipeline image

Index

  1. Step 1: Dockerizing the Application
  2. Step 2: Setting up Nexus
  3. Step 3: Setting up Jenkins
  4. Step 4: Creating the Pipeline
  5. Step 5: Ansible and Jenkinsfile Configuration

Step 1: Dockerizing the Application

In this pipeline, we will use Docker to containerize our application. This makes our application portable. Create a file named Dockerfile in the root of the project directory and paste the following code. This code is basically creating a multi-stage build where the first stage is the normal build process of a React application and the second stage involves copying the dist folder from the builder image to Nginx.

# Dockerfile

FROM node:alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build

FROM nginx:stable-alpine-perl
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 5000
CMD ["nginx", "-g", "daemon off;"]
Enter fullscreen mode Exit fullscreen mode

Nginx configuration:

server {
    listen 8080;
    server_name localhost;
    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /index.html;
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Setting up Nexus

Nexus is an open source artifact repository manager. We will use Nexus to store Docker image versions and use these images for deployment to staging and production environments.

  1. Create a VM/Droplet.
  2. Add your SSH key.
  3. Configure firewall rules.
  4. Install Java 8.
sudo apt install openjdk-8-jre-headless
sudo apt install openjdk-8-jdk-headless
java -version
Enter fullscreen mode Exit fullscreen mode
  1. Download and extract Nexus.
cd /opt
wget https://download.sonatype.com/nexus/3/latest-unix.tar.gz
tar -zxvf latest-unix.tar.gz
Enter fullscreen mode Exit fullscreen mode
  1. Create a nexus user.
  2. Change ownership of extracted folders.
  3. Configure run_as_user="nexus" in nexus.rc.
  4. Start Nexus and verify it is running.

Create a Docker hosted repository, create a dedicated user, assign permissions, and expose a connector on port 5000.

Step 3: Setting up Jenkins

Jenkins is an open source automation server that allows us to build CI/CD pipelines.

  1. SSH into the machine.
  2. Update the system.
  3. Install Docker.
  4. Pull jenkins/jenkins:lts.
  5. Run Jenkins in Docker.

Configure Docker-in-Docker and add:

{
  "insecure-registries": ["<NEXUS_REPO_URL>:5000"]
}
Enter fullscreen mode Exit fullscreen mode

Install these plugins:

  • Multibranch Scan Webhook Trigger
  • GitLab Plugin
  • NodeJS
  • Ansible

Restart Jenkins after installation.

Step 4: Creating the Pipeline

Create credentials for:

  1. GitLab access (gitlab-cred)
  2. Nexus repository access

Create a Multibranch Pipeline:

  1. Create a new Multibranch Pipeline.
  2. Add Git branch source.
  3. Point to the Jenkinsfile.
  4. Save the job.

Enable webhook scanning and configure GitLab webhooks:

<JENKINS_URL>/multibranch-webhook-trigger/invoke?token=gitlabtoken
Enter fullscreen mode Exit fullscreen mode

Step 5: Ansible and Jenkinsfile Configuration

Example when directive:

when {
    branch pattern:'feature/[a-z]*', comparator: "REGEXP"
}
Enter fullscreen mode Exit fullscreen mode

Jenkinsfile

pipeline {
    agent any

    environment {
        NEXUS_REPO_URL = 'http://<NEXUS>:5000/repository/docker-hosted/'
        DOCKER_IMAGE_VERSION = "1.0.0"
    }

    stages {
        stage("Checkout from SCM") {
            steps {
                git branch: env.GIT_BRANCH,
                    credentialsId: 'gitlab-cred',
                    url: 'https://gitlab.com/example/repo.git'
            }
        }

        stage("Testing the application") {
            steps {
                sh '''
                npm i
                npm run test
                '''
            }
        }

        stage("Building Docker Image") {
            steps {
                script {
                    dockerImage = docker.build("app:${DOCKER_IMAGE_VERSION}")
                }
            }
        }

        stage("Push Docker image to Nexus") {
            steps {
                script {
                    docker.withRegistry("${NEXUS_REPO_URL}", 'nexus-repo-cred') {
                        dockerImage.push()
                    }
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Ansible Setup

- name: Setup Docker
  hosts: staging
  become: yes
  tasks:
    - name: Install Docker
      snap:
        name: docker
        state: present
Enter fullscreen mode Exit fullscreen mode

Deployment

- name: Deploy Application
  hosts: staging
  become: yes
  tasks:
    - name: Pull Docker Image
      command: docker pull registry/app:1.0.0

    - name: Run Container
      command: docker run -d -p 8080:8080 registry/app:1.0.0
Enter fullscreen mode Exit fullscreen mode

Hosts File

[whiteboard_staging]
68.183.83.29 ansible_ssh_private_key_file=~/.ssh/id_rsa ansible_user=root
Enter fullscreen mode Exit fullscreen mode

Conclusion

Setting up a CI/CD pipeline for your React application helps automate testing, building, and deployment, making your workflow faster and more reliable. It ensures consistent code quality and quicker releases, allowing you to deliver better applications with less effort.

Top comments (0)