Streamlining Application Deployment with Heroku and Contentful

Speed up Deployment

We recently updated an application for a client and helped dramatically decrease the time it takes to deploy a change. It was taking upwards to 2 weeks to get through a full deployment the application and now a change can be made and deployed in a matter of minutes.

This application is built with Angular and uses a Ruby on Rails API which is hosted on Heroku.

Before the update the front end server was built on .Net and assets were served from a traditional CMS. Changes to the Angular applications were tested locally using a Node.js server to simulate the .Net server but had to be handed off to the .Net/CMS team to be implemented on their side, which could take considerable time and introduced the risk of error when being reimplemented.

The application was redesigned to use Ruby on Rails (on the same server as the API) to serve the HTML and host assets on Contentful, an awesome API based, headless CMS. The application runs on Heroku and auto deploys from GitHub to the development app after the Rails specs and Angular unit tests have all passed. The application is promoted to Staging and Production using Heroku Pipelines and deployment scripts keep Heroku and Contentful in sync.

Described below is the life cycle of this application from the developer machine to production.

The Application Architecture

First, let’s get an idea of the basic architecture.

High Level Overview

Angular

There are two Angular applications. The first, for login, registration and password management is served to unauthenticated users. The second, with the real functionality, is served to authenticated users. For security purposes only the minimum necessary functionality is served to unauthenticated users, which is why the applications are split up.

Ruby on Rails

Ruby on Rails is used to serve the HTML pages which then retrieve all of the assets and execute the JavaScript to initialize the Angular applications. The API, which communicates with Salesforce to send and retrieve data, is also hosted on this server.

Contentful

Contentful is used to host the actual assets such as the Angular applications, CSS, Images, Fonts etc., as well as translated content, from their CDN.

GitHub & Heroku

Git is used for version control and changes are pushed to GitHub. The Ruby on Rails applications are hosted on Heroku.

The Rest of the Architecture

There is quite a bit more to the back end as well but for the purposes of our discussion this info will cover us.

Development

Local Changes

A developer first starts by making their changes locally and running any necessary build scripts. Once the developer is happy with their changes they can commit those changes to Git.

GitHub to Heroku

Next, the developer pushes their changes to GitHub. Heroku is configured to use Automatic Deploys so every time a commit is made to the master branch in GitHub the changes are automatically deployed to the development application.

Deploy to Contentful

How Contentful is Used

For this application Contentful is not being used in the typical way. Normally a user would upload an asset to the CMS, check that it looks good, and then publish it. For this application Contentful is used to mirror assets are in the Git repository. This means every time changes are deployed to a Heroku application all of the assets in the corresponding Contentful space need to be updated.

Getting Files to Contentful

When uploading an asset, Contentful needs to be told about the file by giving it a name, description, and path from where it can be uploaded. Next Contentful is instructed to process the file, which means it will reach out to the given path and attempt to download the file.

Serving the Files

The Rails application has an endpoint which serves a file from the repository when Contentful requests it. The files are served from a location outside of the Rails Asset Pipeline. This ensures that the files, which should only be served to authenticated users, are not publicly available in the asset pipeline.

Heroku Deploy Hooks Add-on

Assets are served to Contentful from within the Rails application so the server must be fully deployed and running before the any files can be delivered. To ensure no files are sent before the server is up the free Heroku Deploy Hooks(HTTP) add-on was added. The add-on was configured to POST to an endpoint within the Rails application enqueuing a background job which ultimately deploys the assets to Contentful.

Deployment Script

The deployment script iterates over a list of files, updates file information in Contentful, and processes the new records.

The main CSS file is the last file that gets pushed to Contentful. When that file is served some pre-processing takes place, updating relative URLs (../images/background.png) to fully qualified URLs (https://cdn.contentful.com/path/to/background.png). Serving that file last ensures the fully qualified URLs for all other assets are up to date.

Visualize the Development Flow

Development Flow

Deploy to Staging and Beyond

Our Heroku applications are grouped together in a Heroku Pipeline. Once the application has been deployed to Development, pushing to Staging or Production is as simple as clicking the Promote to Staging or Promote to Production buttons to migrate the application and kick off the deployment of assets to the respective Contentful space.

Conclusion

With the above architecture and developer flow the deployment times can now be measured in, literally, minutes as opposed to the days or even weeks it used to take to deploy changes. After the changes have been committed to the git repository all code and assets are tied to that commit. Once pushed to GitHub and all unit tests pass the application is automatically deployed to Heroku. From there promotion to subsequent environments is done with the click of a button.