SugarCRM - Git Version Control Strategy

Posted on Mon 10 November 2014 in SugarCRM

git-logo I've found SugarCRM an utter pain to work with in terms of version control for a number of reasons, but the most annoying is simply that certain critical elements of the SugarCRM configuration are stored on the database.

Over time I've worked out a system that circumvents this and I've managed to create a very useful gitflow based workflow.

I won't go over what gitflow is or does, there's a great explanation here and if you need a more visual explanation this cheatsheet is a terrific reference.

Example Problem

Say you're in the middle of developing a new feature in SugarCRM. You've used something like.

git flow feature start mynewfeature

Someone realises a new urgent fix is required to go live now, you're not going to want to deploy your half implemented feature along with the new urgent fix. That's okay, you're using git flow. So you'd commit your half finished feature. Then create a hotfix, like

git flow hotfix start mynewfix

The problem is that you've made a bunch of changes to the sugarcrm database, specifically fields_meta_data. Even if you swap branches the fields_meta_data won't update back to the master branch, which is where the new hotfix will create it's branch from. What you need is a way to keep fields_meta_data in sync with the branch you're currently working on.

The Solution - Git Hooks

Using git hooks you can automatically run commands when certain events occur. The two hooks of interest to us are pre-commit and post-checkout.

Tracking all database changes

What pre-commit does is run everytime you commit code. So, if you could dump your fields_meta_data everytime a commit is made, you can be sure your branch is tracking all database changes you're making via the studio. So in .git/hooks/pre-commit add code that looks like so:

#!/bin/bash
rm databases/fields_meta_data.sql
mysqldump -u root -p --extended-insert=FALSE --skip-dump-date sugarcrm fields_meta_data  > databases/fields_meta_data.sql
git add databases/fields_meta_data.sql

Note that I'm not compressing these database dumps, they should stay in plaintext with each line representing a database insert. The reason for that is when it comes time to merge two branches, say you've made changes to studio in a master branch and also to a feature branch you wish to release, you can merge the fields_meta_data in with branched changes very easily via any mergetool.

Keep Sugar up to date with your branch

Finally when you swap between branches you'll want to automatically apply that branches fields_meta_data because your likely to forget to do this step. So say your swapping from a feature branch to master. You'll want to revert your studio changes back to where master was. You can do this in the post checkout git hook. So in .git/hooks/post-checkout add something like this:

#!/bin/bash
echo 'Importing this branches field meta data'
mysql -u root -p sugarcrm  < databases/fields_meta_data.sql

This will automatically execute your fields_meta_data database dump on your SugarCRM install.

Deploying

In the end, whether a hotfix or a feature it'll always get merged to master when I'm deploying. So what I tend to do is finish my release/hotfix, merge to master then apply a data sync to fields_meta_data on live so I can manually review the db changes before deploying. Navicat has a really nice tool to handle this.

Going further

As you can see all I've written is two simple bash scripts and they've made my Sugar workflow much cleaner. You could go far further than this, a few examples I can think of would be to track db changes on the saved_reports table or have the scripts automatically run a command line variant of the Quick Repair/Rebuild. The other thing could be to track the entire structure of the SugarCRM database if you felt like it, but since all db fields are tracked via fields_meta_data I thought this wasn't necessary but I'm sure there's ton of other things you could add to make your development life easier.

Let me know if you think of anything!