Be Nice to Sysadmins, Add a version.txt to Your App

One best practice that I rarely see used by companies is a version file that denotes what is currently in Production. Let's step back a bit and use a real-life situation.

A company released a new version of their Web application to Production from master (using the git-flow model). Some hours go by and its now late into the night when the application fails. Unfortunately, all of the developers are now at home and only the poor operator (who is on-call support) is left wondering what happened. The software didn't fail in the test environment, what could possibly have gone wrong.

Operators and sysadmins (including DBAs) typically know little to no details about the workings of a Web application. Only developers know the inner-workings of any piece of software written and deployed inside a company. How that software works in various environments depends on so many working pieces. The best way that anyone can begin to troubleshoot the problem is to eliminate all the variables that occurred when the software progressed from testing to Production.

The first variable that needs to be eliminated when troubleshooting is, "Is the same piece of software installed in Production that was testing in the Staging environment?" Often, it is difficult or impossible for an operator, let alone a developer, to determine this.

This can be remedied by using a version.txt file that is installed after the code is downloaded to the system, but before the application server is restarted. This file contains the revision number that is reported by the version control system.

With Git, this is as simple as using the following command:

git log -n 1 --pretty=format:%H > version.txt

In my case, when I am using Git to download a new version of software to a server, I use the following handler in my Ansible scripts.

---
# handlers/main.yml
- name: add hash marker file
  shell: >
    git log -n 1 --pretty=format:%H > version.txt
  args:
    chdir: "{{ app_code_home_dir }}/public"
  sudo: yes
  sudo_user: "{{ app_user_name }}"

This is simple, easy and displays the full Git commit hash to the caller. What's more, it can be integrated into reporting tools with a simple curl/wget command.

$ curl http://example.com/version.txt
0f21cec66519e9ece83467b9ca94a4b20100fa9e

Additional Nginx Configuration

If you are like me and use Nginx to front a back-end application server, you will need to add a new configuration line to allow requests for version.txt to reach the outside world.

server {
  ...
  location ~* ^/version.txt {
  }
  ...
}