Have you ever tried to build a new development project without the support of a version control system? It sucks.
We’ve all done it, though. It’s where we start as developers. The software development learning curve is steep enough without having to tack on a Git or Mercurial tutorial as well, so we tend to get a crash course in FTP and learn about version control a little later.
This project management wild west should be a temporary state, however. A professional project should never be passed around via USB drives and FTP transfers. Without a version control system, there is no developer accountability and an obvious smell to the project that alludes to bigger architectural and design issues.
But once you start utilizing a version control system to safely manage your project, what then? Sure, it helps keep developers accountable, and ensures quality backups, but what about deployments?
Release management is where we start to find differing opinions. I’ve worked on projects that have had wildly different deployment workflows. From pulling down repository changes directly on production servers to copying release-ready code to production servers, I have seen it all.
My personal opinion is that if you are managing your own production servers, it is best to leave them ignorant of a version control system. While it is fairly common to simply do a git pull on the production server, this approach is insecure and unsustainable as your development team grows.
The safest and most reliable deployment method I’ve had experience with is atomic deployments. Atomicity is a concept that describes a transaction that either completes successfully, or doesn’t happen at all. This is ideal for deployments because if your deployment workflow fails at any point along the way, the production environment is unaffected. Unit tests, uploading and building code, and cleaning up artifacts should all happen in a safe environment that is only released to the end user if it all completes successfully.
While there are a lot of tools that can be used to accomplish atomic deployments (Heroku, DeployBot, Wercker, etc), the central piece involved with each one of them is that they are all backed by a version control system. This is important for a few reasons, the primary reason being that there is always a record of the state the code was in for each and every release.
The more documentation, processes, and planning you have around your deployment workflow, the safer it will be. A version control system gives you the power to quickly and easily roll your production services back to various states of being with little more than a couple keystrokes or mouse clicks. This centralized system also normalizes the process for every single developer on a project, which means that what I deploy is no different than what you deploy.
Another benefit of version control systems is that integrating with multiple third-party services is as simple as sharing your private repository. A centralized repository can be shared with distinct services that handle everything from unit test coverage analysis to release management, automatically and with little overhead.
Unfortunately, there is one major drawback of version control systems, and that’s the management of private data. While it is technically possible to add passwords, API keys, and encryption keys to a repository, it is a really bad idea, even if it is privately hosted. The reason for this is that the likelihood of a breach increases for every developer on the project, and every third-party service that consumes your repository.
All it takes is for one of your developer’s accounts to get hacked in order to compromise the entire organization. This isn’t a theoretical issue, either; it has happened to many companies before. While you can enforce two-factor authentication within your organization, not every service offers it, and not everyone bothers to set it up.
While keeping secure information out of your repository can be incredibly inconvenient, there are a lot of services that provide options that mitigate the pain. Heroku is a great example of this. Environment variables can be managed directly from within the Heroku dashboard; for non-Heroku hosted applications, environment variables can still be managed at the operating system level, or even the application level through the use of one of the many dotenv packages available.
When utilized properly, or even improperly, utilizing a private repository on a version control system is one of the most useful things you can do for a project. There’s nothing like the feeling you get from being able to understand what is happening with your project, when it is happening, and why.