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