DEV Community

Cover image for QuickStart example on how to build CI/CD using CircleCI for monorepo
Tran Minh Tri
Tran Minh Tri

Posted on

QuickStart example on how to build CI/CD using CircleCI for monorepo

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

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
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

Image description

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

Top comments (0)