I am working on a product that has been developed by multiple developers over the years.
The product is built on
- PHP
- jQuery
- Angular
- Bootstrap
The product has different modules separated by directories in the server. These modules are individual repositories in my BitBucket as well.
Fortunately, all the modules use the same database. In a code level, the configurations such as Database name, URLs (to access APIs, assets that point to the other folders in the server) are hard-coded.
We have 4 instances (dev, production, abc, abcdev). The hard-coded configurations are different for each instance. I have implemented Git very recently and have pushed all the code into the server.
The scope is to maintain a single repository and have different branches for the different instances. Since the values are hard-coded at so many places, merging between the branches would be very difficult
The way I feel I should be handling it is, to create another module named config
, add presumably a json
file that would have the URLs, database related information in it.
This file would obviously be different for each branch and this file would not be changed in the branches. Though this is all in theory, how do I go about implement it? Or are there any other better ways to handle this scenario? Any feedback would be appreciated! Thanks!
First, move all your config options into a configuration file (or files). Use a language agnostic format such as JSON or YAML.
Put the config file/directory at the top of the source tree where it's easy to find.
A single repo is good. Different branches are not. Managing many long-lived branches rapidly gets complex.
Instead have a single long-lived branch, probably
master
. Use feature branches to isolate development and have them QA'd before they're allowed to merge intomaster
. That waymaster
is always ready to go. Deploy directly frommaster
.Here's what that might look like. Each letter is a commit. Each
[branch]
is a branch head.This shows two completed features,
D - E
andI - J
, have already passed QA and been merged intomaster
. Since QA has already been done on the feature branches,master
is deployed to production. There are two open feature branches, each of which periodically runsgit rebase master
so they are up to date with the latest fully tested code.Notice there are no direct commits to
master
, it only changes via a feature branch merge. This meansmaster
is always tested, reliable, and ready to deploy. Individual features in progress don't interfere with each other and can rely on a stablemaster
branch; if something breaks they know it's because of their work, not because someone broke the dev branch.But what about the different configs?
Having the same config file be different in different branches is a great way to get conflicts and people accidentally overwriting the config with test and development info.
It's simpler to have one set of config files which has configurations for all the different contexts, plus a default for them to share.
For example, your database config might look like the following in YAML.
This uses YAML anchors and aliases to do the overlays,
<<: *default
says to include the node marked with&default
. This eliminates a lot of redundancy between the various contexts.Have your app choose the environment from an environment variable, or guess it from context.
This is how Rails does it, multiple configuration files, each with configuration sections for each context.
The next step is to take production secrets out of the source code and put them into environment variables. Secrets are things like passwords and API keys. Then when your production systems are started, they're started with those environment variables set. This is how cloud hosting sites such as Heroku do it.
Alternatively you can hard code the production secrets in your config files, but encrypted. Then supply the decryption key via an environment variable. This means you only need one environment variable for production, which might be simpler if you're migrating an old system. This is how TravisCI does it.
It might be a bunch of work, depending on how your existing system and workflow are currently set up, but this is a very successful pattern.
12 factor apps is a opinionated guideline for building modern, maintainable and scalable applications.
Related to configuration it tells you to keep it on the environment. The recommended approach is to use environment variables.