Continuous Integration work flow

This post is based on the Continuous Integration lessons of James Shore: Let's Code: Test Driven Javascript online tutorial. The method in question has been published with kind permission of James Shore. By the way, the post is just a summary, for more details watch the videos, they are worth it.

Continuous Integration work flow

Continuous Integration means that you always have a known-good integrated code on the integration machine, and when you make changes on code on your developer machine, you must make sure that if you merge this changes with the integrated code, it will be also known-good.

Continuous Integration principles:

  • integrate frequently

  • integrated code is known-good

The continuous integration method

  1. Set up the version control system for Continuous Integration

  2. Make sure your build is ok

  3. Test integration on your developer machine (get the integrated code and merge locally)

  4. If it fails, go back to build

  5. Merge your changes on integration machine, but in test environment

  6. If it fails, go back to build

  7. Merge your changes with the integrated code

Continuous Integration in detail:

1. Set up the version control system for Continuous Integration

This method uses Git for version controlling, and assumes that you have installed Git. There is some useful references for Git below at the sources. You have to make at least two repositories; one on your development machine, and one on the integration machine. For the sake of simplicity my 'development machine' will be a folder inside my project folder, and the 'integration machine' will be an other folder. The method is the same when you apply it on two or more separate machine (e.g. your integration machine is on a server).

(It is highly recommended to create some build automation for your build. I wrote a post about basic automation with Grunt, check it out if you hadn't done yet.)

on integration machine

  • create or copy a repository on the integration machine

    Let's assume we just now begin the project, and haven't have any repository. Then in the integration machine (here, in the integration folder) create a new repository:

$ git init  
Initialized empty Git repository in /User/continuous-integration/integration-machine/.git/

Let's create a readme file so as to not to be empty the library, and commit it:

$ > README.md
$ git add .
$ git commit -m "initial commit"
[master (root-commit) 06f6356] initial commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README.md
  • create integration branch, and one branch for each developer

$ git branch integration
$ git branch developer1
$ git branch developer2
  • switch to the integration branch
$ git checkout integration
Switched to branch 'integration'

on developer machine

  • switch to developer machine (here: developer1 folder), and clone integration repository (git clone integration-machine-path developer-machine-path)
$ git clone ../integration-machine/ .
Cloning into '.'...
done.
  • switch to the developer1 branch
$ git checkout developer1
Branch developer1 set up to track remote branch developer1 from origin by rebasing.
Switched to a new branch 'developer1'

2. Integrate locally

  • make sure your build is clean (run your build automation if you have, or check your build in other way)

  • commit your changes

$ git add .
$ git commit -m "description of changes"
(such many lines here)
  • pull the latest known-good code from the integration machine, integration branch
$ git pull origin integration
From /User/continuous-integration/developer1/../integration-machine
 * branch            integration -> FETCH_HEAD
Current branch developer1 is up to date.
  • make sure that build is clean

  • if it doesn't, fix problems, and commit your changes

3. Push to developer branch on integration machine

$ git push origin developer1

4. Switch to integration machine, and promote known-good code to integration machine

  • checkout your developer branch
$ git checkout developer1
Switched to branch 'developer1'
  • merge with integration branch
$ git merge integration --ff-only
Already up-to-date.
  • run the build on integration machine and make sure it is ok

  • if the build fails, go back and fix the build, then integrate locally again

  • switch back to the integration branch

$ git checkout integration
Switched to branch 'integration'
  • merge your code
$ git merge developer1 --no-ff --log
(first appears your default text editor to make commit notes, after saving it so many lines again)

And now on the integration machine the integration branch contains your changes, and this integration has been checked locally, and tested int the integration machine, before finally merged.

Merge conflicts

If there are more developers, merge conflicts can occur. We merged three times during the process:

  • at first, when we integrated locally. If a merge conflict happened, you have to solve it, and integrate locally again.

  • secondly, when we integrated on the integration machine, on the developer branch. If a merge conflict happened (because an other developer integrated before you), you have to fix the build, and integrate locally again.

  • for the third time, when we integrated on the integration machine, on the integration branch. Theoretically, merge conflict may happen, if an other developer have the possibility to integrate just before us. If you sit physically at the integration machine, there is no problem. But if you merge remotely, I think that in some way you have to prevent integrations for the brief time while the integration is being tested.



comments powered by Disqus