When I was an Intern at a large Global 500 company, my major responsibility is to deliver a Software Delivery process that uses the software engineering practice called Continuous Integration. In simple terms, I am responsible for a project to create and setup a Continuous Integration Build Server that will be used to “build” the company’s products.
During those days, when I hear the word “build” or “compile”, the first thing that comes into mind is to press the F5 button. Ever since I started programming, when someone asks me for a copy of my program or if I need to distribute the “binaries” of my program, all I do is press the F5 button to create an EXE (sometimes with a DLL), then browse to the output folder(Bin) and copy the binaries. Suffice to say, that is my “Software Delivery” process however crude it is.
In College, I got a little bit more sophisticated. My major projects are all carefully packaged in a very neat MSI installer — but that is just for the major projects. Most of my standalone tools are still made using the “Press F5 button to build” method.
So you can just imagine my horror when the Software Architect presented me my task on my first day at work. I don’t know anything about Software Delivery, more so Continuous Integration. What is more scary is that I am expected to deliver my output in just 240 hours (my Internship duration). But thru the continuous support of the said Software Architect, I somehow managed to cram the concept of Software Delivery and Continuous Integration in just 2 weeks. Also, this book helped a lot, too!
The build process that I created is quite simple and somewhat standard. However, there was a special requirement that the test harness be run on a different machine and that made the build process a little bit more complicated. This are the different stages of my build process:
- Clean-up: Before starting a new build, delete all the previous directories (Source codes, Artifacts, etc.)
- Fetch: Get the latest copy from the source code repository
- Build: Compile the different projects
- Archive: Tag the build then archive it
- Test: Run the unit tests, measure code coverage and perform static code analysis
- Feedback: Provide feedback by generating reports (with beautiful graphs!)
The build process will automatically check for any changes in the Source Code Repository every 15 minutes, if it detects any change in the code, it will automatically start the build process. That is one of the advantage of using Continuous Integration — there is no need for a costly “Integration” phase.
In my previous blog posts, I’ve mentioned that I am working on a certain product that will be shipped later this month. Well, that project is nearing its completion. We now have a “Beta” build for our product and it won’t be long before an official Release Candidate is available.
During our weekly status meeting, I brought up a concern regarding how we are building our Beta builds that are being sent to the Test Department. Our current Build Machine (which is physically located locally) also acts as our Development Machine. All of the development activities like bug fixing are being done on the Build Machine. If you are REALLY REALLY careful, this is fine but still, a little bit crazy. But since we are Software Developers, we are never too careful. We are programmers, we cause accidents.
So why is it important to have a dedicated build machine? Here’s why.
- Pristine – You want to keep the build machine as clean as possible to make sure that only the needed resources are being included in the build. If your build machine also acts as your development machine, keeping a pristine state is a very tough task. When I inspected our latest Beta build, I was shocked to see that there are *.pdb (debug) files included in the install image.
- Control - It is very important to control your Build Environment. All of your builds must be coming from a standard setup from a standard state. The keyword here is standard. This means that the “exact state” of the machine used in creating Build 001 should also be used in creating Build 002. When you use your Build Machine as a Development Machine, it is almost impossible to maintain this “exact state” every time for every build. When we were migrating our product from SQL 2000 to SQL 2005, we added the SQL2005 installer to our local build machine but somehow, someone forgot to add the SQL 2005 installer to the source code repository. When we tried building from a new build machine, the installer would no longer work.
- Reliability - All builds coming from the build machine must be Reliable. If you are using your Build Machine as a Development Machine, most often the not, your builds are coming from your local copy and not from the Source Code Repository. In most cases, this is okay. But in our case where the final build will be built using the official build machine (located in the US), this is a big problem. One of the problem that we encountered is that the local copy is not in sync with the repository copy. We are Humans, sometimes we forget to check-in our changes.
To solve the above problems (and since we don’t have any spare machines ), I used a Virtual Machine! Yes, I used a Virtual Machine as a Build Machine. After 3 days of fixing the build scripts and updating the unsync’d files, I was able to create a clean and working build from my VM Build Machine.
Virtual Machines are perfect as Build Machines. You can always maintain a pristine state by creating a snapshot of a freshly installed setup build environment and always building from there. Everytime that you need to create a build, you can just rollback to that pristine state. This feature of build machines gives you control over your build environment. Since you are always rolling back to a pristine state, you will then be forced to always fetch the latest copy from your source code repository! This means that you can be confident the builds coming out from your build machine is always reliable.
Before, I have no faith in our source code repository copy. As a result, I am always too anxious in making sure that I don’t break the local copy. There’s always that constant fear that the official copy from the Source Code Repository is broken or the official copy does not reflect the local “tested” copy. Now, I am always confident that anytime, anywhere in the company, we can always create a clean and reliable build that will work straigth from the repository. That feeling is very liberating!