Automated deployment is a crucial part of development for every application. Without it, a lot of time is wasted and we end up generating problems that would not otherwise have existed. What are the aims of every deployment process (whether Ember, Rails or anything else)? Simply - to be fast, reliable and simple.
The gist of our old deployment process is illustrated in the following diagram:
During deployment, Capistrano enters the server, pulls the repository, runs the ember build command and eventually copies the output to the nginx root directory. Nginx then serves the index.html file and assets without any proxies (typical for Rails apps).
The pros and cons of Capistrano based deployment
So what are main advantages of this process? First, it’s very stable and reliable. I have over a year of experience with this process. I’ve seen hundreds of deployments and I know what can go wrong and how to fix it. However, I hate the monolithicity of this process. We cannot easily interfere with the life-cycle of deployment and we cannot do anything special during the deployment without diving into the Ruby code of Capistrano’s tasks. Last, but not least, even if we do, it won’t be usable by the community.
Our new deployment process, based on ember-cli-deploy
Our new deployment process is based on ember-cli-deploy, which I first heard about during EmberCamp (you can read my recap of the event here). It was clear that we needed to check out this process and try to automate it as much as possible, to see if it would work with our requirements (Netguru is running over 40 projects simultaneously and many of them are using Ember.js on the frontend, with at least two deployable stages - staging and production).
On the other hand, we are currently in the process of moving our deployment flow to Docker. Therefore, my task required not only checking out ember-cli-deploy but also to fit it into our default Docker process. Here’s what I came up with:
Asynchronously, API is being run on the other Docker container and is serving the index.html uploaded to Redis on our application domain. Thus, we can easily perform A/B testing of Ember app revisions, and serve a revision based on some query param, or use the last one by default. These two applications can be deployed completely asynchronously and without coupling.
The pros and cons of ember-cli-deploy
First of all, we now have assets on our S3 instances by default, regardless of whether it’s the staging or production environment. We are using a well documented and community supported pipeline which lets us opt into its life cycle with ease and control. We can take advantage of a wide range of add-ons (S3, Redis, gzipping, etc.) and write our own which can be shared back with the community. Actually, speaking of which, you can take a look at ember-cli-deploy-rollbar, which I’ve already developed :)
What are the disadvantages? I have no production and long-term experience with it. Using it will be a learning process, which may lead to some surprises. Additionally, it is a little bit more complex (from my point of view) but due to its advantages, I cannot resist using it :)
I should note that we have not used this process in a commercial application yet. I have been playing with it on internal applications and right now we are on track to apply it to commercial and production apps. I feel that, thanks to ember-cli-deploy, we will have more control over our deployment process. For example, the addon I developed eventually let us use the full power of Rollbar by uploading the source maps directly to this service without uploading them to the public production environment.
How are you handling automated deployment of Ember apps? Is it similar or completely different? If you have any questions about our process, or would like to know more about config files or anything else - let me know in the comments!