Notes:
1. Need to know your way around msbuild
a. Property groups organize variables for your build.
b. ItemGroups organize files for you
c. Targets are where you scripts run
d. Use the MSBuild task to run the VS sln file
e. Get the msbuild community tasks package
2. Cleaning up is a pain – deleting files or removing directories via msbuild caused problems. Had to revert to using Exec and calling RMDIR to make sure things got deleted. Problem seemed to come from Tortoise. Deleting files in the svn directories caused errors.
3. ToolPath is important – I had trouble getting NUnit task to work. Added toolpath to point to the version of NUnit I’m using and then things worked fine.
4. Configuration of unit tests can be a pain because sometimes there is a fair amount of setup. While working in VS you don’t think about it because you have already gotten things work. When you move to an automated build in a separate environment you forget about all that setup work you did. In my case it was a separate configuration file that app settings referenced. I ended up having to run the project in the debugger and step in to see what the problem was. Seeing the problem was like “doh!”.
Usually I’m pretty good about making sure my projects have an automated build, but lately I’ve been pretty lazy. No excuses. I generally have found that projects are more successful when we have been disciplined about maintaining an automated build (doing continuous integration) . The investment in time has usually more than paid for itself.
In the past I pretty much hand rolled the build system using NANT and task scheduler. This go around I’m using MSBUILD and CruiseControl. A big bonus today is that there is a ton of good information and plenty of examples already available. Check these out:
What follows is my personal experience getting one of my projects set up and how I solved a few of the problems I encountered.
First, MSBuild is pretty easy and similar to nant with some nice extra features. The nicest feature of all is that Visual Studio will do 90% of the job for you. All CSProj files are already MSBuild files. Further, MsBuild will read VisualStudio’s sln files so the actual build step in your build just involves calling whatever VisualStudio provides you. You could do that with nant but you had to have VS installed on your build server (something I usually try to avoid).
Even with the VS provided project and solution files you’ll still want to do a little work in MSBuild to give yourself some control over the build process. For instance:
1. Cleanup from the last build
2. Create directories for the build
3. Get the latest code from your repository (SVN in my case)
4. Do the actual build
5. Run unit tests
6. Run FXCop
Visual studio gives you #4 and #7, the rest are up to you. In writing my script here are the problems I ran in to:
First, cleaning up my source code directory had problems. The Msbuild tasks all seemed to have problems. Deleting all the files caused errors when it went in to the svn directories inside the source code. My solution was to just use the Exec task and call RMDIR with the /s and /q parameters. That simply removed the directory trees specified and let me get on with the build.
The next issue was with the SVNCheckout task. Even though I use tortoise to talk to SVN for some reason my system didn’t have svn.exe where msbuild could find it. I ended up installing slik svn and using the ToolPath parameter to tell the msbuild SvnCheckout task where to find svn.exe.
The ToolPath parameter seems pretty important sense it looks like a lot of the MSBuild Contrib tasks have stuff hardcoded. Which also brings up a small complaint – when you install the msbuild contrib. tasks it doesn’t put anything in your start menu. Initially I couldn’t find any documentation because I assumed it would all be on the web-site. Nope. A friend clued me in and told me to look in the program files directory under MSBuild. There is a chm help file with some documentation. It is good enough, it answers some questions well enough to allow you to figure it out.
The next issue had to do with bit rot. I’m good about unit testing and one of my requirement for the build is to execute all of the unite tests. Only problem was that the unit tests needed some configuration files. These particular configuration files aren’t stored in SVN because they have passwords. What to do? I have encrypt/decrypt wrappers in my library so I did some quick coding to store the passwords as encrypted strings in the configuration file and then added them to the repository. The user is a test user with very limited rights, but being the paranoid type I don’t like the idea of leaving passwords around. Encrypted or not.
FxCop was the next problem. The fxcop task included in the contrib. packaged is hard coded to call an old version of fxcop. Gheysels’ weblog suggested just calling fxcop via the Exec command and that worked quite nicely.
At this point I have enough to begin moving my build script in to cruise control so and getting it configured to run every whenever somebody commits a change to the repository. However, I’m far from done. We’ll also want a build script that also deploys the finished product to the test server. I’d also like to add features like code coverage and other code analysis stuff so we can get more details about what we are doing.
Also, I really need to spend some time with FxCop because the way I’m running the policies now is insane. It complains about too much stuff. A lot of the things it complains about can be safely ignored. The only problem is that while you are busy ignoring the safe stuff you might also ignore the important stuff.
I still have a ton of work to do to get my build where I want it. Here is a list of things I’m going to add:
1. NCover – I want code coverage reports so I can see how well we are unit testing out code. I strong suspect an obvious inverse correlation between the number of bugs the get reported in test and production and how much code is actually tested by unit tests.
2. WIX – I want to generate MSIs for my projects so that we can have better control over deployment. Too many projects go to production expecting system admins to copy and configure things correctly. I’ve experienced enough all night deployments using the manual approach. Every time we switched to an automated process the deployment process magically became less painful.
3. Test and Staging build – All the build stuff to this point happens in development for development. I want to add additional builds that will handle taking the build results and putting them on to servers. This will require additional scripting and work but I think the effort will pay for itself in saved time. Just go to CC and force a test build and when you come back the test environment will be setup and ready with your latest and greatest code. Who wouldn’t like that?
Here is a list of sites I visited while ramping up on building my first scripts:
http://fgheysels.blogspot.com/2008/06/setting-up-continuous-integration.html
great two part article. The scripts he put together are simple and easy to understand. Not a lot of extra bells and whistles, but I see that as a feature not a bug. One annoyance is that his scripts are all jpegs so no copy paste action. I also couldn’t find a link so I could download a copy to look at.
http://weblogs.asp.net/omarzabir/archive/2008/10/06/asp-net-website-continuous-integration-deployment-using-cruisecontrol-net-subversion-msbuild-and-robocopy.aspx
Another great one. Little more thorough with more details. He also provides a copy of his script which is great because you can use it as the starting point for your own.
http://dotnet.org.za/cjlotz/archive/2007/04/04/part-1-continuous-integration-using-msbuild-cruisecontrol-net-fxcop-nunit-ncover-subversion.aspx
This has got to be the best one I found. It is actually too much but he covers everything you could want to do in an automated build system. He also does you a favor by offering the series of blog posts as a standalone PDF file and the actual build files he used