NOTE: At the time of writing, this article positions a product that is not yet generally available. Heroku provided prior permission to discuss this topic publicly.

The Heroku Platform as a Service (PaaS) has always had a strong focus on developer experience, a prime example being the launch of Pipelines in 2015.

A pipeline provides a highly visual way of managing the deployment stages in a continuous delivery workflow, covering development, staging and production.

alt text

Although Pipelines was a significant step forward for the developer experience, it did not inherently include any Continuous Integration capabilities. As a result, development teams were forced to setup and maintain a third-party solution, such as Jenkins CI, Travis CI, etc.

Since November, I have had access to a new feature (currently pre-release) known as Heroku CI. As the name indicates, Heroku CI embeds Continuous Integration into the continuous delivery workflow.

For those who are not familiar, Continuous Integration (CI) is the practice of continuously merging all developer working copies to a shared mainline. The rational for this approach is to reduce the risk of code integration issues by focusing on small pieces of effort, applied frequently. CI also promotes the use of proactive automated testing, security analysis and quality checks.

In short, I am a big advocate of CI (see my previous articles Architecture - CI and DevOps Automation) and therefore I am pleased to see this feature become a core part of Heroku.

How does Heroku CI work?

Just like Pipelines, Heroku CI is tightly embedded into the developer workflow, meaning the setup and maintenance is incredibly simple, relying on the platform and tight integration with GitHub to do all the heavy lifting.

Getting started (assuming Heroku CI is enabled in your org) is as simple as creating an “app.json” file (or “app-ci.json” in the pre-release) and storing it in your application repository.

The “app.json” file follows a manifest format and is where you specify your application dependencies and required configuration for CI. I would recommend becoming familiar with the app.json schema.

An example of the Heroku CI configuration within an “app.json” file can be found below:

  "name": "Example-App-JSON",  
  "description": "An example app.json.",  
  "keywords": [  
  "website": "",  
  "repository": "",  
  "success_url": "/",  
  "scripts": {  
    "test": "npm test"  
  "env": {  
    "API_TOKEN": {  
        "required": true  
        "required": true  
  "formation": {  
    "web": {  
        "quantity": "2",  
        "size": "Performance-M"  
  "image": "heroku/nodejs",  
  "addons": [  
  "buildpacks": [  
        "url": "heroku/nodejs"  

Once your “app.json” file has been created, enabling CI within Heroku is as simple as clicking the “Wait for CI to pass before deploy” button from the application “Deploy” tab.

alt text

Heroku will automatically look for the “app.json” file each time a commit is pushed to the connected GitHub repository. If your configured CI tasks complete successfully, the build will occur as normal. In the event of a failure, the developer will receive a notification, including the specific error message.

Heroku maintains all CI results in a new “Tests” tab, which can be found on the specific Pipeline. Here you can see a history of every build (pass and fail), including the specific test setup and results.

alt text

Similar to Pipelines, Heroku CI is tightly integrated with GitHub, meaning that the CI progress (real-time) and results are also shown within a Pull Request.

alt text

Internally, Heroku CI is completing the following seven steps for each build.

  1. CI App Provisioned - CI app created, Performance-M dyno used by default.
  2. Add-ons Provisioned - Not all add-ons will be supported by CI.
  3. Buildpacks Invoked - Officially supported buildpacks will be used be default.
  4. Tests Setup - Used to install any dependencies not installed by the buildpacks.
  5. Tests Executed - If tests exit with a zero status, the run is flagged as a success.
  6. Results Reported - Available in Heroku and accessible via GitHub.
  7. Cleanup - CI app deleted, any test runs over an hour are automatically terminated.

The specifics of your CI setup will likely differ per application. However, I’ve been testing with the following setup on Node applications. All automation tasks were configured using Gulp and the standard “package.json” file.


Overall I’ve been very impressed with Heroku CI!

It is very easy to setup and seamlessly integrates into the developer workflow. The actual test runs are lightning fast, with the output being easy to consume.

I also like the decentralize architecture, allowing development teams to configure their CI setup as required, without needing to interact with a central authority. This is similar to Travis CI and Circle CI, however Heroku CI includes a more robust security model.

My only concern would be the proprietary nature of Heroku CI. For example, if your team works across multiple development platforms (e.g. Heroku and CloudFoundry) you might decide to leverage a generic, open-source tool.

Finally, it is worth noting that Heroku CI also supports Apex and Lightning, which is part of the new Salesforce DX initiative. Longer-term, I anticipate the Heroku developer experience will be used as the foundation for This will not only improve the developer experience, but also provide consistency across the two platforms.