Your builds and deployments should be standardized
In this blog post I would like to discuss about standardized builds and deployments.
I was surprised to see that many developers think that this only applies to big companies. I disagree with this view and I argue that you should start to standardize your development pipeline from the start even if you are a developer doing personal projects on the side.
What do I mean by standardized builds?
I mean that all projects should be built, tested, deployed the same way. You shouldn't have to think about those aspects for each project. These steps should be defined globally and each new project needs to follow the same set of rules.
Why it matters
- Automation: you should automate a lot of things and the build and deployment pipeline is the most important and the first aspect to automate. Standardized procedures will definitely help for that.
- Repeatable builds over time: you might know how to build your project now but time will pass, you will move to new servers, you will upgrade your environments and you will have new tools. Standardized procedures means that it will be easier to maintain old projects.
- Start new projects fast: there are so many new ideas to experiment. You will want to be efficient at starting new projects. Having this standardization means that you don't have to waste time figuring out the packaging part of project. The goal is to be able to start and deploy a new (empty) project in less than 10 minutes.
What should the standardization include?
This can include as many items as you want but here is a list of common items you might want to include:
- How to build? (including dependencies)
- How to deploy?
- How to test? (Unit test, integration tests,...)
How to do it?
There are many ways to deal with this and it will probably depend on the technology stack that you use. That said I would like to share some aspects that I think you should take into account.
There are basically 3 parts for this: your code (NodeJS, Java,...), the automation tools (Jenkins, Ansible,...) , your running production engine (Docker, Cloud services,...). You don't want each part to be too dependent on the others. You think you won't change those technology stacks anytime soon but you might often want to optimize part of those regularly, so you don't want to have to spend time migrating old projects all the time.
My recommendation is to define some standardized entry points (these would be like interfaces), then your code would implement those interfaces and the tools would call them. Those interfaces might scripts (all projects should have the same set of scripts) or another option that I use is to use NPM's package.json (even for non-NodeJS projects).
Let's consider the following deployment steps:
- Building the project:
- The code itself should contain the logic that will build the project (dependencies, compilation,... )
- The automation tool will call the build command and just wait for the output (the output should be the same for all projects)
- Running containers
- The automation tool should be the one launching your app in a container. This should be done similarly for all applications but you don't wand to store application specific settings at the automation level
- I recommend to store specific configuration inside the application code itself. For example the image definition, Swarm/Kubernetes specific configuration.
- Tests:
- Similarly to the build, I think that your code should have the detailed procedure to perform the tests. This way you can test locally or on your build server.
- There should be some standardized outputs for your automation tool however. Those tools should know if tests succeed or fail or even be able to handle the test report.
Side Notes:
If you use scripts you might have a common part and a specialised part. You might want to manage those with shared submodules
Personally I use the following submodule in almost all of my own projects: https://github.com/DidierHoarau/docker-packaging