CALL +44 (0)20 7183 3893
agile, geeky, and eccentric Dev Blog

Monday, December 12, 2011

Agile and Android, Part 3: Introducing Gitflow

This is a third in this series of blogposts which attempts to introduce you to how we attempt to follow agile best practices when developing Android applications.


At Cloudreach, we use the Git DVCS for version control, specifically with Github. While Git in itself is packed with goodness for reasons I won't go into (as so many others have already done so and spared me the hassle), the Git Flow branching model makes it all the sweeter.

The Git Flow branching model is a great way to ensure that your version control system tells any new developer on your team the story of how your team went about making releases. In essence, it can be represented using this diagram from Nvie, who designed Git Flow.

The Git Flow branching model: Reproduced from nvie.com

The Git Flow branching model consists of several branches, some of which are present both remotely and locally and some of which are presently only locally. The branches shared across all developers are the develop and master branches. In our cases, these are the branches we push to Github.

  • The develop branch represents the main line of development of the project, and contains commits made during the course of developing a release (i.e., during a given sprint as far as we are concerned). 
  • The master branch only contains releases; i.e., code that can be deployed to a staging, UAT, or production environment.
Git Flow allows us to organise our version control system along the lines of features, which aligns very well with our approach of using user stories, each of which represents a feature. Every time a developer starts a new user story, he should — after pulling from the develop branch to ensure that he is in sync with everybody else in the team — create a new feature branch. Feature branches typically take the form feature/STORY-ID. He then develops the feature on the feature branch and then merges it with the develop branch when he finishes the story. The develop branch is then pushed to any remotes we may have configured. We use feature branches to deal with not just user stories, but bugs and improvements dealt with during the course of a sprint.

When a sprint is finished, a release is made by merging the develop branch with the master branch and tagging the master branch. As mentioned earlier, the develop and master branches should be available to all the developers, as a result of which we typically push it to any remotes we may have.

If you end up needing to fix bugs with a previous release, you branch into a hotfix branch from the master branch, make the fixes necessary, release, and then merge back into the master branch.

Using the Git Flow executables
Doing all of the above with the tools Git provides you with out of the box can be a bit of a pain. However, Nvie provides us with executables that perform most of the voodoo under the hood for you. See the Installation Instructions on how to get Git Flow set up.

Before you start using Git Flow for your project, you need to initialise it. Go to the root directory of your project (the directory which contains the .git directory) and use git flow init.
 git flow init  
 Initialized empty Git repository in /***/***/AwesomeApp/.git/  
 No branches exist yet. Base branches must be created now.  
 Branch name for production releases: [master]   
 Branch name for "next release" development: [develop]   
 How to name your supporting branch prefixes?  
 Feature branches? [feature/]   
 Release branches? [release/]   
 Hotfix branches? [hotfix/]   
 Support branches? [support/]   
 Version tag prefix? []   
 [siddhu.warrier@realMac:/tmp/AwesomeApp ]$  

Now, if you were to start a user story, you need to use git flow feature start. This results in the creation of a feature/feature-name branch.

 [siddhu.warrier@realMac:~/Documents/workspace/AwesomeApp ]$git flow feature start AAP-1  
 Switched to a new branch 'feature/AAP-1'  
 Summary of actions:  
 - A new branch 'feature/AAP-1' was created, based on 'develop'  
 - You are now on branch 'feature/AAP-1'  
 Now, start committing on your feature. When done, use:  
    git flow feature finish AAP-1  

As you can see in the block above, run  git flow feature finish when you're done. This will result in the feature branch being deleted and all of the data being merged into the develop branch.
 [siddhu.warrier@realMac:~/Documents/workspace/AwesomeApp ]$git flow feature finish AAP-1  
 Switched to branch 'develop'  
 Already up-to-date.  
 Deleted branch feature/AAP-1 (was fd47bf8).  
 Summary of actions:  
 - The feature branch 'feature/AAP-1' was merged into 'develop'  
 - Feature branch 'feature/AAP-1' has been removed  
 - You are now on branch 'develop'  

Once you're done with all of your features, you will want to make a release. This, as described in the previous section, will result in all of the contents of the develop branch being merged into the master branch, followed by the addition of a tag in the master branch. You can start the process of a release using git flow release start when in the develop branch.
 [siddhu.warrier@realMac:~/Documents/workspace/AwesomeApp ]$git flow release start 0.1.0  
 Switched to a new branch 'release/0.1.0'  
 Summary of actions:  
 - A new branch 'release/0.1.0' was created, based on 'develop'  
 - You are now on branch 'release/0.1.0'  
 Follow-up actions:  
 - Bump the version number now!  
 - Start committing last-minute fixes in preparing your release  
 - When done, run:  
    git flow release finish '0.1.0'  


Now, make any changes you need to make before finalising your release. When you type git flow release finish, you will be prompted for a commit message, your release branch will be merged into your develop and master branches. You should see something like this:
 
[siddhu.warrier@realMac:~/Documents/workspace/AwesomeApp ]$git flow release finish 0.1.0
Summary of actions:  
 - Latest objects have been fetched from 'origin'  
 - Release branch has been merged into 'master'  
 - The release was tagged '0.1.0'  
 - Release branch has been back-merged into 'develop'  
 - Release branch 'release/0.1.0' has been deleted  


Now, bugs! Bugs are unavoidable, and sometimes they can happen after you have lovingly nourished a release you thought had no major show stoppers. Fixing bugs in the latest production release without affecting code for the next release that is in the works can be a nightmare at the best of times. This is where the hotfix branch, also discussed in the previous section, comes to the fore.
 [siddhu.warrier@realMac:~/Documents/workspace/AwesomeApp ]$git checkout master  
 Switched to branch 'master'  
 [siddhu.warrier@realMac:~/Documents/workspace/AwesomeApp ]$git flow hotfix start 0.1.1  
 Switched to a new branch 'hotfix/0.1.1'  
 Summary of actions:  
 - A new branch 'hotfix/0.1.1' was created, based on 'master'  
 - You are now on branch 'hotfix/0.1.1'  
 Follow-up actions:  
 - Bump the version number now!  
 - Start committing your hot fixes  
 - When done, run:  
    git flow hotfix finish '0.1.1'  
 [siddhu.warrier@realMac:~/Documents/workspace/AwesomeApp ]$  

When you finish the hotfix using git flow hotfix finish, the  hotfix branch is merged into master and back-merged into develop. The branch is then deleted.
 Summary of actions:  
 - Latest objects have been fetched from 'origin'  
 - Hotfix branch has been merged into 'master'  
 - The hotfix was tagged '0.1.1'  
 - Hotfix branch has been back-merged into 'develop'  
 - Hotfix branch 'hotfix/0.1.1' has been deleted  

To summarise
The Git Flow system has the following branches shared between developers,

  • develop
  • master
and the following branches are maintained only in the developer's local repository (and merged back into develop and/or master):
  • feature/*: Manage using git flow feature start/finish (branched from develop)
  • releases/*: Manage using git flow release start/finish (branched from develop)
  • hotfix/*: Manage using git flow hotfix start/finish (branched from master)

Agile and Android, Part 2: Introducing AwesomeApp

In the second of this series of blogposts where we attempt to show you how to build an Android app using Agile best practises, we shall introduce the example application we shall use for the rest of this series. This post shall lay the ground for the rest of the series by describing the example application we shall be working on for the rest of this series. 

We shall be describing this as a series of user stories because here in Cloudy Towers, we like Agile software development enough to fetishise it (not literally; we know fetishes can be unhealthy!). We cannot stop waxing eloquent about how agile allows us to focus on business value and continuous delivery, about how the sight of a wallboard can be nigh orgasmic... right, I’d better stop. Suffice to say that this is entirely representative of how we go about gathering requirements from our customers at the start of a development project.
Note: To understand more about epics and user stories, do take a look at Scott W. Ambler's excellent blogpost.

Our client is called Awesome Logistics Inc. Awesome Logistics wishes to build an Android application that monitor their AWS resources on the cloud called Awesome App (sorry, I’m not very creative). However, this is besides the point. For the purposes of this demonstration, let us consider a single epic.
As a user of Awesome App, I want to be authenticated on to the application so that unauthorised users cannot wreak havoc on our Amazon resources.
This epic is then split into the following stories
  1. As a user of Awesome App, I want to log in to the system using my Google Apps ID so that I do not have to remember multiple passwords*.
  2. As a user of Awesome App, I want to receive a warning if my Google Apps username or password are invalid.
  3. As a user of Awesome App, I should not be able to log in in the absence of an Internet connection so that I do not waste my time trying to log in.
  4. As a user of Awesome App, I do not want to log in again after I have logged in once so that I am not repeatedly prompted for my password.
In the rest of this series, we shall go through creating and mavenizing the project,  implementing our stories with Behaviour Driven Development using Robotium, and mocking on Android using android-mock.
*Please note that an alternative approach to use Google Apps authentication on Android is to use the Android AccountManager class, and this is often better for most users. However, for pedagogical purposes, we shall not take this approach.
Pontus is ready and waiting to answer your questions