Using MSBuild to create a deployment zip

Automated builds are one of the core fundamental musts for software development. However, your build doesn’t just have to build the solution and execute your unit tests. For IronEditor, my build also creates two zip files. One zip is the output from the build for archiving purposes, the second is my deployment zip – the zip which actually gets pushed up to CodePlex containing only the files required by the application. In this post, I will cover how you can get MSBuild to zip your build output.

To use zipping functionality within your build scripts, you need to use the MSBuild Community Tasks which is a great collection of MSBuild extensions and a must if you are using MSBuild.

In order to zip your files, you need to specify which files you want to zip. In the script below, I create an ItemGroup called ZipFiles, this includes all the subdirectories (**) and files (*.*) from my Release directory which is my build output folder. I also specify that this group should not include any other zip files. I then create a Builds directory if it doesn’t already exist. Finally, I use the Zip task, passing in my ZipFiles ItemGroup which the task uses to know which files to include.


 
     
     
 

 
         WorkingDirectory=”$(BuildDir)Release”
       ZipFileName=”$(BuildDir)BuildsIronEditor-Build-$(Version).zip”
       ZipLevel=”9″ />

The most important property is the WorkingDirectory, this is the root directory where all the files you want to exist live. If you don’t have this set correctly, you will have the additional directories in your zip file which are navigated in order to get to your actual files and just looks rubbish.

My deployment zip also looks very similar and is executed after the above target. The only different is that I individually specify which files and directories to include. For some directories, such as Config, I still include all sub-directories and files it contains as they will all be relevant and required.


 
     
     
     
     
     
     
     
     
     
     
     
 

 
         WorkingDirectory=”$(BuildDir)Release”
       ZipFileName=”$(BuildDir)BuildsIronEditor-$(Version).zip”
       ZipLevel=”9″ />

One thing which tripped me up was that while my ItemGroup was created within a target, it actually has global scope. As such, you need to call the two groups within the two different targets something different.

Once my script has executed, I have two zip files created – one containing everything, the other ready to be released on CodePlex.

image

Technorati Tags: ,

Overriding MSBuild variables via command line options

While working on a build script for the Pex Extensions project, I wanted to be able to specify the version of Pex which the project was built against for use within the AssemblyInfo and file names. This build script is being executed manually in order to create all the zip files to upload but I didn’t want to have to manually edit the script to set the value. I wanted to provide the version when I executed MSBuild via the command line as a command line argument.

After a bit of searching on MSDN, I found that you can override any variables created within the PropertyGroup. At the top of your build script, you generally define your variables within the PropertyGroup to specify paths, versions etc. Within my build script, my PropertyGroup looked like this:


    $(MSBuildProjectDirectory)
    0.6

Using the /p: command line switch, I can override the PexVersion property by executing the script as follows:

> msbuild Pex.msbuild /p:PexVersion=0.6.30728.0

If I forget to set the argument, the value set within the script will be used.

Technorati Tags:

Continuous Integration Builds for CodePlex Projects

As many of you might be aware, I maintain the IronEditor project on CodePlex.  I like CodePlex, I find the wiki and issue tracking to be useful, but I find the directory structure and searchablity of projects on the site to be most useful. However, the one thing which I wish it could offer, and this goes for Google Project Hosting as well, is a continuous integration server. I would like to know that after I have pushed my changes to CodePlex, that it does actually compile.

As I’ve posted before, I run TeamCity on my home machine as it is free and easy to configure. As TeamCity can connect to Team Foundation Server (what CodePlex runs under the covers), I decided I would just be able to connect to the CodePlex servers and threat it like any normal source control system.

Sadly, I was wrong. When I tried to connect, I found the following (extremely helpful) error:

image

If anyone knows the reason why this failed, please leave a comment.

However, all is not lost! CodePlex have created the SVNBridge, a small application which runs on your local machine, or in this case your CC server. This translates all SVN commands into TFS commands, the result is that you can connect to CodePlex using SVN clients, one of which is TeamCity!

Connecting TeamCity via SVNBridge to CodePlex

SVNBridge is a single executable. It lives in the system tray and listens for communications on a particular port, in my case 8081.

image

In order to connect to SVNBridge, and as such your CodePlex project you must use a particular URL.  The URL is your SVNBridgeAddress/YourCodePlexServer/YourProject

For example, IronEditor lives on tfs03.codeplex.com and in order for me to connect via the bridge my URL would be:

http://localhost:8081/tfs03.codeplex.com/IronEditor

With my setup, I simple wanted to be able to click run and TeamCity go off, download the latest code from TFS, build my solution and execute my unit tests again just to be sure I haven’t broken anything (or in my case simply forgot to upload the latest code changes).

In order to connect TeamCity to CodePlex, you simply need to use the Subversion VCS settings and point it at your SVNBridge. Below, are my settings for IronEditor. The username and password you need to use to connect are your website login details.

image

On TeamCity’s dashboard, I now have my new CodePlex build along with my local IronEditor build, both run the IronEditor.build MSBuild script, they just pull the sources from different locations. After I have pushed my changes to CodePlex, I manually click run, and off it goes. The reason I don’t have it manually checking is because it’s rare I push changes to codeplex and as such I’m happy to be in control of when it happens.

image

TeamCity is now happily talking to my CodePlex repository, building as and when asked. If you happen to have a spare server, or a windows home server, then you could run this setup from there, have it automatically check for modifications with all the developers on your project benefiting.

Technorati Tags: , , ,

MSBuild – Build Visual Studio 2008 solution and execute Unit Tests

Previously, I have spoke about how you can update your AssemblyInfo file using MSBuild. However, I haven’t spoken about the very basics – how to build a Visual Studio solution and execute your unit tests.

MSBuild is a very interesting build scripting language, out of the box it includes a set of standard tasks which you can use based on your requirements, such as creating a directory or copying a file in order to correctly build your project. I also take advantage of the MSBuild community task project, while it hasn’t been updated in a while, the tasks work perfectly.

Below is the basic MSBuild script.


DefaultTargets=”Test” xmlns=”
http://schemas.microsoft.com/developer/msbuild/2003″>
 
   
       
        <MSBuild Projects=”TeamCityBlogExample.sln” Properties=”Configuration=Release” />
   

    DependsOnTargets=”Build”>
       
        <NUnit Assemblies=”TeamCityBlogExample.TestsbinReleaseTeamCityBlogExample.Tests.dll”
               ContinueOnError=”false”
               ToolPath=”C:Program FilesTestDriven.NET 2.0NUnit2.4″ 
               OutputXmlFile=”NUnitResults.xml” />
   

Within the project section at the top, I set the default target to Test. This is the target which will be executed first, the Test target then has a DependsOnTarget attribute which enforces that the build must be done before we test.

On line 3, I import a reference to the MSBuild community tasks so I can access all of the custom tasks included – such as NUnit.  Next I define my build target, within this I define the solution I want to build and the configuration. To execute my unit tests, I use the NUnit task from the community task project, this takes a list of all the assemblies which we need to run, define if a test fails wether it should fail the build and finally tell it where NUnit lives on the local machine.

Now, the script can be executed by a build system, such as CCNet or TeamCity, or from the command line using the msbuild.exe