Nowadays, our development teams use Agile methodologies what means that we have accelerate our processes trying to deliver small chunks of functionalities to receive early and real feedback from users to continue iterating our ideas.
Now, we are an organization that follow and use Continuous Integration practices but, we are still missing something. We are not able to receive this feedback if it takes ages between our developers finishing their tasks and the code been deployed in to production where our users can use it. In addition, when a lot of changes or features are delivered at the same time, it makes more difficult to debug bugs on solve possible errors. For a long time, the deployment process has been seen as a risky process that requires a lot of preparation but, this needs to change if we want to be truly Agile.
Here it comes Continuous Delivery (CD). Continuous Delivery is a practice that tries to make tracking and deploying software trivial. The goal is to ship changes to our users early and often, multiple times a day if possible, to help us minimize the risk of releasing, and giving our developers the opportunity to get feedback as soon as possible.
As I have said before, we should have already a Continuous Integration environment to ensure that all changes pushed to the main repository are tested and ready to be deployed. Can it be done without a CI environment? Yes, probably, but more probably we are going to create a machine that it is just going to push our bugs faster to production increasing our risks.
Steps we need to take
Create a continuous delivery pipeline
The continuous delivery pipeline is a list of steps that happen every time our code changes till it finds its way to production. It includes building and testing the application as part of the CI process and extends it with the ability to deploy to and test staging and production environments.
With this we will achieve two things:
- Our code will be always ready to be deployed to production.
- Releasing changes will be as simple as clicking a button.
Create a staging environment
All of us, generally, have been writing code in some point in our lives, some of us still do it, some of us have evolve our careers but, something that I am sure all of us remember are these cases of “it worked on my machine…”. Configurations, differences in environments, networks… There are thousands of things that can be different and can go wrong, and probably it will go. No matter how many test we have locally, how many precautions we take, our local conditions are not going to be the same than our production conditions. For this reason we need an intermediate environment, the “staging” environment.
The “staging” environment does not need to support the same scale as our production environment but it should be as close as possible to the production configuration to ensure that the software is tested in similar conditions.
The “staging” environment should allow us to see things before it happen. If something is going to break, it should break in this environment. Using this environment, our release workflow should be similar to:
- Developers build and test locally a feature.
- Developers push their changes to the main repository where CI tests run automatically against their commits.
- If the build is green, the changes are released to the staging environment.
- Acceptance tests are run against the staging environments to make sure nothing is broken.
- Changes are now ready to be deployed to production.
An additional advantage is that it allows our QA team and product owners to verify the software works as intended before releasing to our users, and without requiring a special deployment or access to a local developer machine.
Automate our deployment
Or, we need to create a “green button” that once it has been pressed, without any other human intervention is going to deploy our code in staging or production.
We can start building some scripts that we run from our development machines and, after that, we can add them to a any CI platform.
There are many ways to deploy software, but there are common rules that maybe we can use as guidance:
- Version the deployment scripts with our code. That way we will be able to audit changes to our deployment configuration easily if necessary.
- Do not store passwords in our script. Instead, use environment variables that can be set before launching the deployment script.
- Use SSH keys when possible to access the deployment servers. They will allow us to connect to our servers without providing a password and will resist a brute force attack.
- Make sure that any build tools involved in the pipeline does not prompt for user input. Use a non-interactive mode or provide an option to automatically assume yes when installing dependencies.
- Test it, test it and test it again. Make sure everything deploys as expected, that nothing is missing no matter what kind of changes you are doing.
- Maybe, it is a good moment to write some smoke test, if you do not have it, to check if your machines are up an running.
Include data structure changes
Let’s face it, when our application changes the code is not the only thing changing. The data structures change too. And, we are not going to have a CD environment if this changes are not added to our automatic deployments.
First, create backups. No matter how good we are, how little is the change, something is going to fail in some point and we want to be able to restore the previous state of the application.
Second, there are multiple tool that can help manage data structure changes as code. Some frameworks bring their own to the table but, if not, we can find tools that fit our technologies and ideas. Just learn them and use them.
All together and the last detail, the CI server
Arriving here, we have set a CI environment with a CI server and we have a “button” to run our deployments, now, why not put everything together?
To do this, we just need to add a manual step in our pipeline to release (press the button) the code to our different environments.
Now, every time our code is merged and ready to production, following business needs, we just need to push the button and release. This give us a great control of our deployments. The only precaution we need to take is not to leave to many commits accumulated.