Skip to main content

Our git workflow

In my current gig in ABC Active Memory (https://activememory.com/) we have put together a git workflow which works really well for us, so I decided I would write about it here so that others could benefit.

The things you need to have in place though are Continuous Deployment (http://en.wikipedia.org/wiki/Continuous_delivery), Test Driven Development (http://en.wikipedia.org/wiki/Test-driven_development), Agile (http://en.wikipedia.org/wiki/Agile_software_development) and the desire to keep releasing small independent incremental features without any one of them blocking each other.

Branches

So the key is branches (obviously). We have 2 main branches which are shared by everyone, and every new feature takes place in a feature branch. 

Our 2 shared branches are 
  • acceptance
  • master

Feature branch

When we start a new feature, we do all the work in our feature branch which we cut from master. Our feature branches are named by ticket number (i.e. 575-add-invoice-to-order) so that they can reference our JIRA tickets (though any ticketing system will do) and we can keep track of them.

If you have been working on a feature branch for a long time, it is worth occasionally rebasing or merging from integration to keep it fresh. 

Acceptance

When we think the feature is ready for the business owner to inspect, we merge it into acceptance and once this build is green, we deploy it to the acceptance server for the business owner to look at and (hopefully) accept. If for some reason the business owner needs some changes, we do them in our feature branch and then re-integrate into acceptance and then redeploy. Rinse and repeat until accepted.

Periodically, we will wipe the acceptance branch (when there are no pending stories in it) and re-cut it from master to weed out any stories that never get accepted (due to changing business needs).

Integration

Once the feature has been accepted, we merge it from our feature branch into master. Never merge acceptance into master as it may have other unaccepted stories in it.

Once master is green, deploy it to the staging server to test the actual build. Once the feature is checked on staging, we deploy to our production servers and do another feature check. Master should be deployed as soon as it is ready (i.e. don't let it hang around).

No downtime releases

We strive for no downtime releases most of the time, but occasionally we will need some scheduled downtime. If the feature one is working on does need downtime, we normally hold off on merging it into master until about an hour before deployment and we make sure everyone knows about it (it's quite rare though). We even deploy migrations without downtime provided we are only adding fields or tables (renames do require downtime unfortunately).

Advantages

So what advantages do we get from this workflow? Well, mainly, none of us are blocking each other. All of us can release without having to worry about the state of our coworkers' stories/features. Some features take longer to get accepted than others and it gives the business owners more time to examine a feature before accepting it.

Downsides

The downsides are minimal once you get used to the flow, but there is a little bit of complexity to take on when you first get on board. There is a lot of merging going on and sometimes you might have to fix merge errors twice (once in acceptance and once in master).

The other downside is if your feature does actually have dependencies on another feature then you need to wait for it to get integrated before you start working. It is possible, if you can't wait, to cut from the other feature branch instead of master, but it is not a risk free approach (especially if the first feature gets cut or rejected or delayed).

This flow also works best if all your developers are full stack or vertical, rather than horizontal. It is the case in our team that some of us are more geared towards the front end and some of us are geared towards the back end. We normally get around this either by sharing the feature branch or else by doing code reviews.

Summary

In summary, our git workflow is the following
  1. Feature branches for all new features
  2. Merge feature branch into acceptance and deploy on acceptance server for the business owner to accept
  3. Merge feature branch into master and make sure build is green.
  4. Deploy on staging and manually check
  5. Deploy to production and manually check

Additionally

  1. Hotfixes are done on master deployed ASAP
  2. acceptance is periodically deleted and re-cut from master



Comments

Popular posts from this blog

Freezing Gems

What is a gem and why would you want to freeze it?

In Ruby, there are times when you want to access pieces of functionality that other people of written (3rd party libraries) and you normally have 2 options. You can install a plug in or install a gem. Normally the method you use is determined by which ever is made available by the author.

Gems are installed on the host machine and are pretty handy when you want to run things in the command line or else across lots of projects, but their downside is that if you use a gem in a Rails project there is no automatic publishing mechanism when you deploy your site. You will need to log onto the remote host machine and install the gem manually.

Plugins are specific to Rails and are similar to gems in that they are also 3rd party libraries. However they are associated with your Rails project as opposed to your machine so they will get posted to the server on a regular deploy.

Freezing a gem is the process of transforming a gem into a plug in. Essen…

Unit/Functional Testing RubyAMF

One of my current projects is using RubyAMF to communicate with Flash (http://rubyforge.org/projects/rubyamf/). On the whole this is really nice because it allows you to transfer Ruby objects directly to ActionScript ones (as opposed to translating the object into XML, sending the XML and then recreating the object in ActionScript).
However, Rails does not provide a built in transport mechanism for AMF, so we cannot run functional testing directly on the data call (as we could for an XML or HTML transport layer). This is a show stopper for a lot of people (Rails w/o Unit testing = a big mess of trouble when something goes wrong).
We can though serve both the HTML and the AMF formats depending on the request format. This means that we can test the object instantiation logic and make sure there are no errors in the controllers (though we cannot check the actual format of the data being served). In the controller, instead of rendering AMF alone, do the following respond_to do |format|

Comparing Rails' Active Record Pattern with Phoenix/Elixir/Ecto

Rails has a very well established Active Record pattern for dealing with the database. You have an Active Record model which maps to the database table, the schema of the model comes directly from the database schema and you place your model specific methods on the Active Record model. This file is also where you set your model relationships (e.g. has_many, has_one, belongs_to). Your instance of the model has all the methods built in.

In Ecto/Phoenix it's a little different. First of all, the database schema doesn't automatically map to the "model". In fact we don't really have models (as Elixir is a functional paradigm). What happens in one file in Rails, happens in essentially two (or more). You have a schema file (where you have to list out all the attributes and relationships). Using the schema file, your "instance" is essentially a data structure (with no methods on it). If you want to transform the data on your struct, you would use a context modu…