DEV Community

Dantis Mai
Dantis Mai

Posted on • Updated on

CI/CD Pipeline with CircleCI and Heroku

Introduction to CircleCI


CircleCI 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

Heroku 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 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 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.



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.


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.


  • 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.

  • 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.


Config pipeline

Below is pipeline for CircleCI and NodeJS platform to deploy to Heroku.

  node: circleci/node@4.1.0
  heroku: circleci/heroku@1.2.6

version: 2.1

        type: string
        type: string
      - 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>>

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

    executor: heroku/default
      - checkout
      - heroku/install

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

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

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

      - test

      - deploy:
            - test
                - master
                - develop
                - staging
Enter fullscreen mode Exit fullscreen mode

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?



Let merge develop branch to staging branch, which are required successful both jobs


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.

Top comments (0)