views:

417

answers:

2

I would like to accomplish two things during my build process:

  1. Run unit tests - I have a Test Project with my unit tests. I would like to run all of these tests on build and receive a notification if the build fails validation.
  2. Merge web.config files - I have 3 different environments with configuration details specific to each. I would like to generate the config file based on where the web application is being deployed.

I have looked over a few resources and nothing has stood out to me as the best solution for this scenario. Most of my searching revolved around the web.config portion of the goal, but if I am going to do that I'd like to accomplish the unit testing at the same time.

  • Scott Hanselman has a post about making multiple copies of the config file, creating custom configurations, and copying over the web.config with a batch file, aligning the configuration with the source. I don't like this solution since I have to have multiple versions of the same file and there is the chance one gets updated and another doesn't.

  • Using nAnt looks promising. From what I gather I would use a batch file as part of the build process. The replacing of {template} variables in the file template with variables in an xml file seems really straightforward to me, so I guess I lean towards this over MSBuild. My concern is environment configuration, multiple developers need to have the nant assemblies in the same location, so they should be checked into source control. That sounds ok with me.

  • I ran across CruiseControl which at first glance looks interesting, but seems like it will require a decent amount of learning.

I realize this is a pretty ambitious goal that will require some effort to get correct so I'd like to make a well informed decision before I choose a path. Any suggestions on what the easiest, cleanest way to get up and running with an automated build process with testing and file configuration would be appreciated, thank you.

+11  A: 

For starters, this isn't an ambitious goal, it's a common thing with well supported tools. So you're on the right track, and good on you for so clearly identifying your priorities.

Scripting

First off, Don't, if you can help it, use bat files. The bat scripting language is, well, horrible. There are many, many language constructs that are missing from it, and it is hard to do anything complicated at all. Experts can do quite a lot of stuff with bat, but my experience with bat scripts in build systems is that they are universally unmaintainable.

You will want to write a number of OS level scripts to put all this together, but you want a solid programming language to do it in. Recommendations include:

  1. Powershell
  2. Python
  3. Bash (i.e. cygwin)

nAnt is a fine tool for managing your build steps. The fact that the config xml gets checked in, branched, merged, diffed with all the rest is a huge advantage.

Make and Scons are also good tools.

A couple of notes about these scripts. They should have clean output and good error messages. I mean great error messages. You can't spend too much time writing build scripts that give good error messages. Seriously. Also, manage your OS error codes carefully, and make sure that each build command raises an error code if it fails. All of the CI servers will use this to red flag a failed build. If you fail on step 2, but don't raise an error code until step 10, it's very hard to debug.

Unit Tests

Yes, they should be part of your build. Nowadays there exists a unit test framework for every programming language under the sun, and they all run off the command line. So pick whichever one looks best and you're on your way.

Continuous Integration

Once you get your build process to a point where you can sit down to a command shell and get a Full Build, from Soup to Nuts (i.e. from source code to shippable), then it's time to look at what they call a continuous integration tool/server. Cruise Control is a good one, so are Hudson and Buildbot. I've used them all, they're fine, pick one and go with it. Once you get going, they're not that hard to learn, and they manage a lot of the notification stuff you were asking for. The main thing to keep in mind is that they are all for the execution and reporting of command line arguments (more or less)

When you structure your build process, remember that it consists of four basic steps:

  1. Getting code out of the repository
  2. Pre-build; updating version numbers and so on
  3. Compiling/building
  4. Post-build; packaging; zipping up build products, making .iso images and the like
  5. Publishing: moving the build products to someplace where people can find them (in your case a web server)

Config Files

If you have your config management down to one file, take a bow. This will pay you big dividends. You say that you don't want to maintain three different files. Can you identify a set of rules that would transform one base file into the three files to publish? If so, then you can write a script that does that transform for you during the packaging phase. Remember when I said "Don't use bat files?" This is the kind of thing that bat files are terrible at, and these kinds of tasks always find their way into build systems.

Conclusion

Finally, remember that the point to all of this is to:

a. Make sure there are no manual steps between submitting code and delivering a product. People are terrible at that sort of thing. They make mistakes, they don't work weekends all the time, stuff like that.

b. Give developers rapid and full, concrete feedback that what they submitted will work.

Good luck!

Sean Cavanagh
A: 

For your desire to merge web.config files, I recommend the process described in http://blog.jpboodhoo.com/NAntStarterSeries.aspx

Basically, you have a single xml file, called local.properties.xml in this case, that has all the values that change per environment. This is the one file that would be different in each environment. You remove web.config from source control. You have a web.config.template file that contains the common web.config structure and add that to source control. You use Nant's built-in ability to copy files and do variable substitution through filterchain to dynamically generate your web.config file during the build process.

User