QuickStart example on how to build CI/CD using CircleCI for monorepo
Tags: circleci, node, monorepo
Published: 2024-01-07 08:23:32

Hello friends 😄, this is a quick-start example of how to build CI/CD pipelines using CircleCI and Monorepo. This guide will give you an example right out of the box so you can copy it and change it to fit your needs.

> **By all means, please don't treat this as a guide but as an example. Me/myself has to struggle a lot to set up this to work with CircleCI with Monorepobut it is not perfect and I'm not an expert on this topic.**

_**Initial Problem:**_ Build pipelines for a project inside a Monorepo.

_**What you can get from this quickstart guide:**_

- How to set up CircleCI for Monorepo
- Full examples by code on how to set up them line by line
- How to trigger a job manually with CircleCI

_**Context:**_

This is what my folder structure looks like for Monorepo

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mko5uevwu9g9jn7749pz.PNG)

This is a CircleCI example of how to set up pipelines for a BackEnd project inside a Monorepo that requires 4 different stages including `build` / `test` / `deploy_to_dev_env` / `deploy_to_prod_env`

Enough chitchat. Let's get to the code

_**Codes:**_

At the `root level` of Monorepo, you need to have folder `.circleci/config.yml`

```
version: 2.1

setup: true

orbs:
  path-filtering: circleci/path-filtering@1.0.0

workflows:
  Setup:
    jobs:
      - path-filtering/filter:
          base-revision: master
          config-path: ./BackEnd/config.yml
          mapping: |
            BackEnd/.* run-backend-jobs true
```

Inside `BackEnd` project ( one of the project of Monorepo that you want to setup pipelines ), we have `config.yml` at the root level of `BackEnd`

```
version: 2.1

orbs:
  node: circleci/node@5.2.0

parameters:
  run-backend-jobs:
    type: boolean
    default: false

jobs:
  BE_build:
    executor:
      name: node/default
      tag: "18.16"
    steps:
      - checkout
      - run:
          command: |
            cd BackEnd
            node --version
            npm install
            npm run build
  BE_unit_test:
    executor:
      name: node/default
    steps:
      - checkout
      - run:
          command: |
            cd BackEnd
            node --version
            npm install
            npm run build
            npm run test:ci
  BE_deploy_dev:
    machine:
      image: ubuntu-2004:current
    resource_class: medium
    environment:
      ENV: dev
    steps:
      - run:
          name: Deploy Introspection's BackEnd to Dev Environment
          command: |
            response=$(curl -s -w "%{http_code}" -o response.txt $DEPLOY_DEV_URI)
            response_code=${response:(-3)}
            if [ $response_code -eq 200 ]; then
              echo "Deployment to dev env successful!"
              cat response.txt  # Print the response body
            else
              echo "Deployment to dev env failed with response code: $response_code"
              cat response.txt  # Print the response body
              exit 1
            fi
  BE_deploy_prod:
    machine:
      image: ubuntu-2004:current
    resource_class: medium
    environment:
      ENV: prod
    steps:
      - run:
          name: Deploy Introspection's BackEnd to PROD Environment
          command: |
            response=$(curl -s -w "%{http_code}" -o response.txt $DEPLOY_PROD_URI)
            response_code=${response:(-3)}
            if [ $response_code -eq 200 ]; then
              echo "Deployment to production successful!"
              cat response.txt  # Print the response body
            else
              echo "Deployment to production failed with response code: $response_code"
              cat response.txt  # Print the response body
              exit 1
            fi

workflows:
  BackEnd:
    when: << pipeline.parameters.run-backend-jobs >>
    jobs:
      - BE_build
      - BE_unit_test:
          requires:
            - BE_build
      - request_manual_approve_before_deploy_to_dev:
          type: approval
          requires:
            - BE_build
            - BE_unit_test
      - BE_deploy_dev:
          requires:
            - request_manual_approve_before_deploy_to_dev
          filters:
            branches:
              only: master
      - request_manual_approve_before_deploy_to_prod:
          type: approval
          requires:
            - BE_deploy_dev
      - BE_deploy_prod:
          requires:
            - request_manual_approve_before_deploy_to_prod
          filters:
            branches:
              only: master

```

Now for this example above, many things won't fit your need like the fact that I'm using `Render` as the deployment service, and the jobs that I have for my BackEnd `workflows`. 

What you really need to keep in mind is whatever is under `command: |` is the script that you can run locally to deploy your project so you just need to figure that block out yourself and insert that block into there to make it work for you.

There is also a quick example of how to manually approve a job on CircleCI to make it run like the example below ( This block of code below is inside `workflows` of the block of code above ):
```
      - request_manual_approve_before_deploy_to_dev:
          type: approval
          requires:
            - BE_build
            - BE_unit_test
      - BE_deploy_dev:
          requires:
            - request_manual_approve_before_deploy_to_dev
          filters:
            branches:
              only: master
```

With all of that, hopefully, you have something like this in your `CircleCI` as well :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d4xip4gb4snbfr0p6n3e.PNG)

> **Now this is far from perfect but you can even work on circle.ci/config.yml in the root config to work out what changes happen on what project inside Monorepo to trigger that project pipelines only. I haven't actually figured it out yet but if do please feel free to even comment on the solution below for everyone to check it out.**

I hope this post helps you on your journey to test out CircleCI and start building pipelines for your own projects. A full-on example can be viewed here line by line through https://github.com/Tris-909/Introspection