Last week I wrote about why I automated server provisioning for Groceryx. Today I want to share with why it is important to have automated deployment process of your app even if you a one-man shop. By the app in this blog post I mean the backend part of your app, one that is deployed on your server.
Let start with the first reason - time. You might think that the time you spent on automating is not worth it cause you'd deploy not so often and your deployment process is very simple so it'd be better doing it manually. Well, it might be so at first glance, but let me assure you that your deployment process will get more complicated thus taking more of your time. The frequency of your deploys will go up. Think of hot fix releases, multiple iterations to get things right.
The second reason came to me as a surprise. The thing is there will be times when you don't do any deployments. Think switching to a different project for a while, going on a vacation, etc. When your deployment process gets quite complicated consisting of a dozen of steps you just forget about some of them or mess one of them. Our memory fails us. In my case, I took a few month of the project and when I came back, and I needed to deploy a new version with a simple fix I found that I simply forget what the steps are. I was very grateful to have a complete process automated.
Having dealt with "why" let's figure out "how". Anything is better than nothing. Even a bash script on your server is better than deploying manually. Given my successful experience with Ansible I've decided to use it for deployment as well although it seemed that a "simple" script might do the job. Let's start with my playbook:
A few highlights on why it's better than a bash script. First, Ansible playbook is idempotent. You mostly describe the target state rather than a process how to there. It does not matter if it's first/initial deployment or 10th it gets done with the same playbook. The only thing I assume is that the server is provisioned (e.g., all needed services are installed and configured with relevant playbooks). Variables in double curly braces are defined in the environment file along with server's IPs. As it often happens you need to reload/restart some services after some steps. That's when
notify action come in handy. It gets executed only if the step produced some changes to the state of the server. Like in the first step ("Ensure vendor path exists")
uwsgi will be restarted only if a file path does not exist. Also, see that restarting
uwsgi also triggers other actions (reload
celery and run post-deployment hook).
There is one thing you might be tempted with even if you have automated the deployment process. When you need some additional action that you will run only once (like installing or configuring some service). You might want just to do it manually one time and don't bother with adding it to the playbook. It will break your process sometime in the future (think running playbook on a new server). I urge you not to cut a corner here and spend time adding it to the playbook.