CI/CD Pipeline with CircleCI and Heroku
Tags: circleci, heroku
Published: 2021-10-02 18:13:42

##Introduction to CircleCI
![circleci](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xtqukhd368foaidnf9k9.png) 
 
[CircleCI](https://circleci.com) is one of the greatest CI/CD platforms that helps a single developer or small team can quickly set up. CircleCI can be really flexible from a simple pipeline with build, test, and deploy to a complex one with caching, docker layer, and so on.

After authenticating CircleCI with Github and register our repository, every integration will trigger the jobs. For a **Free** plan, CircleCI provides us up to **2500 credits per week**, I can try a lot of fun with that much.


##Introduction to Heroku
![heroku1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kxnc179jpg03hnvp7nqb.png)
[Heroku](https://www.heroku.com) is a cloud service that allows developers to build and manage web services without getting headaches about configuration servers. We just need to focus on developing our product and let the other things for Heroku. Unlike other cloud services, Heroku computes bills by `dynos`, which is a kind of a virtual machine that can auto-scale up or down depending on the size of our product.

The biggest advantage of Heroku is Free within 550h per month, but still provides numerous addons like Database, SSL, and so on. Besides, it also supports Nodejs, Python, Java, Go, .... Heroku will be a great choice to test an idea, or hosting a small website, for me, I host my portfolio there.

##Make it work
###Authenticate CircleCI with GitHub
-  First of all, we need to have a **pipeline config in our repository**, otherwise, CircleCI won't allow us to go further. This [documenttation](https://circleci.com/docs/) will help to config our own pipeline. Once finishing the pipeline in the directory `.circleci/config.yml` and pushing it to GitHub, we are ready to go. I will show you my pipeline below.

-  After [sign up](https://circleci.com/signup/) CircleCI by Github account, we can see all repositories listed out in the middle panel. By clicking **set up project**, CircleCI will scan the pipeline config in the repository, because we have already done the first step, it will let us go, otherwise, the guard will ask us to create one. **set up project** will be toggled to **unfollow project**, if the scanning is successful, and CircleCI will lead us to a dashboard of the project.
 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7b8nq6awkg8i9n832und.png)
 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ppylyssmdpvywhha09oi.png)

Now, we can try to commit a small change. In case the pipeline is triggered, **congratulation!**

_Note:_ CircleCI editor supports pretty well for creating, as well as debugging pipelines. I always use it, and I hope that it also can help you.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rlr7qr76jr49zcjlp0po.png)

###Authenticate Heroku with GitHub, and CircleCI
-  From the top right corner, we can access **account setting** by clicking our avatars, then come to **Applications > Third-party Services**. This step just helps Heroku can interact with GitHub, but not each repository.

![Capture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rx4krkzoy1pe7fxqh2jt.PNG)

-  Every time we create a new app, we need to choose **Deployment method**, this way will help Heroku can use GitHub as a **Version Control**. There are 2 more steps needed to be done:
    -  **App connected to GitHub:** reach to the repository that we want to deploy
    -  **Automatic deploys:** For every integration to the chosen branch, the new code will be deployed. In case we have already had CI for the app, we tick the option **Wait for CI to pass before deploy**. And don't forget to **Enable Automatic Deploys**.
-  After a lot of configuration, let click on **Deploy Branch** in the **Manual deploy** session. To validate it is successful or not, we can check the status of the deployment appeared here. If successful, the **Environments** session of the repository on **GitHub** will list out the Heroku app name.
![Capture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vf65v60y0fdzbwei8le0.PNG)

-  To let CircleCI pipeline can deploy to Heroku, we need to 2 things, they are:
    -  **API Key:** This key is really important and we'd better let no one know it. With the key, authenticated CircleCI pipelines can process deployment to Heroku. In **Project Settings**, We can set it by adding a new **Environment Variables** with key name **HEROKU_API_KEY**, and the value will be placed in **Account Settings > Account > API Key**.
    -  **App name:** This key is the target app name needed to be deployed.

![Capture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/of2fvgh4yxpc1h0sghav.PNG)
 
###Config pipeline
Below is pipeline for CircleCI and NodeJS platform to deploy to Heroku.
```
orbs:
  node: circleci/node@4.1.0
  heroku: circleci/heroku@1.2.6

version: 2.1

commands:
  deploy-command:
    parameters:
      BRANCH:
        type: string
      HEROKU_APP_NAME:
        type: string
    steps:
      - run: heroku config:set YARN_PRODUCTION=false -a <<parameters.HEROKU_APP_NAME>>
      - heroku/deploy-via-git:
          app-name: <<parameters.HEROKU_APP_NAME>>
          branch: <<parameters.BRANCH>>

jobs:
  test:
    executor: node/default
    steps:
      - checkout
      - node/install-packages:
          cache-path: ~/project/node_modules
          override-ci-command: npm install
      - run: npm test

  deploy:
    executor: heroku/default
    steps:
      - checkout
      - heroku/install

      - when:
          condition:
            equal: [master, << pipeline.git.branch >>]
          steps:
            - deploy-command:
                HEROKU_APP_NAME: production-server
                BRANCH: master

      - when:
          condition:
            equal: [staging, << pipeline.git.branch >>]
          steps:
            - deploy-command:
                HEROKU_APP_NAME: staging-server
                BRANCH: staging

      - when:
          condition:
            equal: [develop, << pipeline.git.branch >>]
          steps:
            - deploy-command:
                HEROKU_APP_NAME: develop-server
                BRANCH: develop

workflows:
  heroku_deploy:
    jobs:
      - test

      - deploy:
          requires:
            - test
          filters:
            branches:
              only:
                - master
                - develop
                - staging
```
For every integration, the pipeline will run 2 jobs, test for all branches, and deploy for just branch master, develop, and staging. The jobs are applied to feature branches gonna be shown in **Pull Request**.
 
There are 4 parts that I think you need to notice:
-  **orbs:** This session is where we declare "modules", like in `npm` in case we use Javascript. By adding orbs, we are free to use the commands inside. 
-  **commands:** we define reusable commands, and they are called by **jobs**.
-  **jobs:** we define what they will do for each job, they may call commands on **orbs** or **commands session**.
-  **workflows:** **jobs** will be called here, followed by the arrangement from top to bottom. Besides, we can require another successful running job, and which branch will be applied for the job. 
As you can see in the figures below, the branch `feature/demo` is just required to pass the test job. In case the job is failed, the developers need to fix it before merging, That helps us save develop branch by preventing potential bugs. It's looked cool, right?

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i6snk7fs59o0vjbr2qn1.png)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ut4pdestlq81rmgj71p1.png)

_Let merge develop branch to staging branch, which are required successful both jobs_
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8anujw0j1okkd4vbsewh.png)
 
[Paypal](https://paypal.me/DantisMai).

_I hope that this post helps you have some idea for your pipeline. I am really happy to receive your feedback on this article. Thanks for your precious time reading this._