What was the last working version?

A few years ago, I was afraid of updating the Ubuntu system, that our applications ran on. We chose the LTS (long-term support) versions of the OS releases so we wouldn’t have to do this too often. Essentially, we updated when we heard of new critical security updates or when we needed a new feature that was only available in a more recent version (think a Redis update or other services).

The most horrendous possible outcome of this update was the following: The server did not start anymore after rebooting it. Other very annoying outcomes included

  • the application did not start
  • data could not be loaded
  • the application did not work as expected (there was a bug somewhere)
  • etc.

In these cases you had to choose between three options:

  • Do nothing (this is always an option 😉)
  • Try to locate and fix the problem
  • Rollback to an earlier version

If you application has an error you can revert to an earlier version quite easily. You may have build artifacts that you deploy (think jar in Java-land). For Ruby on Rails apps you can rollback to an earlier release. Capistrano offers to keep ~5 releases (or more if you tell it to do so).

Sidenote: I also had situations where I ran out of releases to rollback to, because the error was there all the time—we just didn’t know about it!

If the problem is not inside your application but in the area surrounding it (the application server, external libraries, network stack etc.) could you rollback there? I know I couldn’t have.

These days I suggest to keep as much information under version control as possible. This includes all the external libraries you are using (package-lock.json, Gemfile.lock) as well as the configuration of your servers, your services and databases and their specific versions. Depending on your deployment setup it still might be hard to recreate a certain environment for your application given these configuration points. But at least you know which version worked. You know the specific versions of all services that worked.

Tools like Puppet, Chef, Ansible and, of course, Docker and Kubernetes make it way easier to (re)create environments today. But that does not free you of the responsibility to know which configuration to actually use. For that you still need proper configuration management.

I am preparing a workshop for a client about this topic. They noticed their needs and want to improve their situation. If this is something that you would be interested as well, then let me know. I could give you some things to read about it or ask the right question so you could figure things out on your own?

Keep everything in your repository

A few weeks ago I suggested that you should integrate the usage of Linters into your projects as a first step in monitoring and improving your code’s quality.

If you went that way (or if you are using Linters a longer time already) you most likely adjusted the given rules for your code. Many people start to use ESLint with ReactJS and the Airbnb ruleset. This is totally fine. I bet you didn’t like some of their rules, though. You adjusted them. And perhaps you commited the .eslintrc.yml to your repository? If you did so, that’s not bad.

I would kindly suggest one small change:

Create a new repository where you keep all your Linter configuration files (.eslintrc.yml, scss-lint.yml, .rubocop.yml etc.). As a next step you clone the new repository to your developers’ computers.

This makes it easier to use the rules in a new project. All projects will be consistent in which rules they use. Your team can cooperate on designing new rules (or changing existing ones) and everybody is only a git pull away from receiving the new rules.

If you want to get fancy, you can work with symlinks in your projects, so you never need to copy and paste the files. This adds a step to your CI workflow: You have to clone the linter-repo there as well. Otherwise your lint jobs cannot work properly.