Building consistently

June 8, 2011

Last evening my friend told me a cool project automation story. Some guys came over to him:

-“Igor, our maven build fails. It works on my machine but doesn’t work on his.”
-“You don’t need me. Just make sure you have the same environment.”
-“I’m telling you, the environment is the same. We purged the local repo on both machines. The svn revision is the same. This is witchcraft and you need to exorcise our build”
-“Ok, tell what mvn -v says”
-“3.0.2”
-“Downgrade to maven 2 and stay happy”

Apparently, all team members use maven 2 and the build is not yet ready to upgrade the build client. Lessons learned:

  • It’s easy to build your legend in a big company. Find a problem some guys are struggling with for past few hours. Then fix it in 5 seconds.
  • It’s easy to fix this ultimate timeless IT problem “it works on my machine but not on his”. There’s a difference in environment and you simply have to keep looking until you find it. Just like the find-5-differences game.
  • It’s worth all the money to have an environment that is consistent by design. If developers in a single team work on consistent environments it is heaps easier to tackle many problems. Here’s how you can implement this pattern with this nice build tool called Gradle:

The wrapper feature is something I underestimated at the time when I started using Gradle a couple of years ago. I thought that the main purpose of the wrapper was to enable running build on environments that did not have Gradle installed. The feature was not very interesting to me because on my environments Gradle was already installed. It was sometime later I discovered the most important edge the wrapper gives. It helps a lot to be few steps ahead towards consistent environments. Suffice to say, if you use the Gradle wrapper you will never, ever face the problem I described at the beginning. Every developer will be using the same version of the build tool giving better, more reliable build environment in your team. I’m never tired of promoting patterns that increase reproducibility of the builds. That’s what I require from the build: consistent results for given VCS version regardless of the environment.

More over, the gradle wrapper makes it easy to upgrade the build environments for every developer. You update the version in your gradle/wrapper/gradle-wrapper.properties file and next time a developer updates his working copy, he will use the newly blessed version of the build tool.

Gradle wrapper is just one of the ways. You can achieve similar results using other build tools if you are creative enough :) I remember years ago I was helping a team that had notorious problems with the build stability. After one of the retrospectives the team decided that *entire* environment would be versioned. They’ve created a VCS root for stuff like jdk, maven, plugins. They’ve even kept separate local maven repo for their project. All those efforts to minimize the random build failures and lengthy debugging sessions caused by inconsistent dev environments. That may sound extreme, nevertheless that’s how the team attempted to solve the problem.

Design your build environment so that it is easy to keep it consistent across the team members. You’ll notice you’ll smile more :)

Build consistently every day. Peace.