Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best practice for handling system-specific information under version control?

I'm new to version control, so I apologize if there is a well-known solution to this. For this problem in particular, I'm using git, but I'm curious about how to deal with this for all version control systems.

I'm developing a web application on a development server. I have defined the absolute path name to the web application (not the document root) in two places. On the production server, this path is different. I'm confused about how to deal with this.

I could either:

  1. Reconfigure the development server to share the same path as the production
  2. Edit the two occurrences each time production is updated.

I don't like #1 because I'd rather keep the application flexible for any future changes. I don't like #2 because if I start developing on a second development server with a third path, I would have to change this for every commit and update.

What is the best way to handle this? I thought of:

  1. Using custom keywords and variable expansion (such as setting the property $PATH$ in the version control properties and having it expanded in all the files). Git doesn't support this because it would be a huge performance hit.

  2. Using post-update and pre-commit hooks. Possibly the likely solution for git, but every time I looked at the status, it would report the two files as being changed. Not really clean.

  3. Pulling the path from a config file outside of version control. Then I would have to have the config file in the same location on all servers. Might as well just have the same path to begin with.

Is there an easy way to deal with this? Am I over thinking it?

like image 458
Joe Avatar asked Jan 07 '09 05:01

Joe


1 Answers

Do not EVER hard-code configuration data like file system paths and force multiple deployments to match. That is the dark side, where there is much SUFFERING.

I find it useful and easy to build my systems to support multiple configurations easily, and I routinely commit configuration files into source control side-by-side, but production's is obfuscated (no real passwords) and development's is templated (so a checkout can't overwrite a developer's configuration). The code is always packaged in a configuration-neutral manner--the same binary can be deployed anywhere.

Unfortunately, most language/development platforms do not readily support this (unlike Ruby on Rails). Therefore, you have to build it yourself, to varying degrees.

In general, the basic principle is to incorporate indirection into your configuration: specify not the configuration, but how to find the configuration, in your code. And generally invoke several indirections: user-specific, application-specific, machine-specific, environment-specific. Each should be found in a well-defined place/manner, and there should be a very-well-defined precedence among them (usually user over machine over application over environment). You will generally find that every configurable setting has a natural home in one location, but don't hard-code that dependency into your applications.

I find that it is VERY valuable to design applications to be able to report their configuration, and to verify it. In most cases, a missing or invalid configuration item should result in aborting the application. As much as possible, perform that verification (and abort) at startup = fail fast. Hard-code defaults only when they can reliably be used.

Abstract the configuration access so that most of the application has no idea where it comes from or how it is processed. I prefer to create Config classes that expose configurable settings as individual properties (strongly typed when relevant), then I "inject" them into application classes via IOC. Do not make all your application classes directly invoke the raw configuration framework of your chosen platform; abstraction is your friend.

In most enterprise-class (Fortune 500) organizations, no one sees the production (or even test) environment configurations except the admin team for that environment. Configuration files are never deployed in a release, they are hand-edited by the admin team. The relevant configuration files certainly never get checked into source control side-by-side with the code. The admin team may use source control, but it is their own private repository. Sarbanes-Oxley and similar regulations also tend to strictly forbid developers from having general access to (near-)production systems or any sensitive configuration data. Be mindful as you design your approach.

Enjoy.

like image 190
Rob Williams Avatar answered Nov 15 '22 10:11

Rob Williams