Setting up Umbraco correctly with MSBuild
April 30, 2009 4 Comments
I\’ve worked with MSBuild on previous projects and was introduced to this and the fullness of MSBuild by Alistair Deneys a few years ago on a very complicated project which required that little bit of automation to reduce the work load for developers.
He posted a great article on this blog which has some of the great features in which MSBuild can be used, but to go that little step further some times you need to actually separate out MSBuild tasks and the standard Project file as well as do different tasks based on the build conditions for this i supply the following solution. This is all just default behaviour but just helps in reducing those pesky repetitive tasks.
MSBuild allows a Visual Studio developer to perform various tasks on either Pre-Build, AfterBuild etc but sometimes all you want to do is migrate your code, controls, pages etc just to the location of where the umbraco website is actually being viewed from.
The requirements for this is quite simple provide a way for your custom pages, controls, xslt, dlls etc to be copied to a clean umbraco solution. This also means that if new developers are added to the project all they need to do is get the latest version from the provided source control solution, open the solution and simply build. This will then allow the developer to instantly be up to date on the current development solution.
Also there is a requirement to be able to easily update umbraco with a new version without having to crawl through pages code etc to see what has changed, it needs to be as simple as copy and paste. Please make sure you have read Alistairs blog on this as you are required to install an MSBuild Community Plugin but in this post i won\’t be doing any web.config changes as this has already be covered by Alistair.
For this to be as simple and easy to upgrade Umbraco for future changes, updates etc we have setup the base structure as such in the file system:
– Umbraco (contains a blank umbraco solution and IIS is pointing to this location)
– Project (contains your project that will be used for umbraco)
The reason we have separated this out in the following structure is because it allows us to have the Umbraco stored as a simple untouched version and is as simple as copying over new files from CodePlex and the system has been updated. To get this to work fully you need some way to copy over your project files over to the umbraco folder and this is where MSBuild comes into play.
Setting up MSBuild
To copy over the required files we have to have a solution and project already created with say a few xslt, usercontrol and dll files. We will assume you have the following structure under your project:
Now this is where we have to be a bit tricky what we need to do is create a new txt file but make sure you call it something like \”ImportOverride.Project\”, this will be used to house our MSBuild tasks for the project. When created make sure you click on the \”Save All\” button and not just \”Save\” we have to save the project file it self.
Now open up the project file \”UmbracoProject.csproj\” for this project in a simple text editor.
Scroll all the way down to the bottom where you will see the following lines:
<Import Project=\”$(MSBuildToolsPath)\\Microsoft.CSharp.targets\” />
<!– To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Replace all of this with the following:
<Import Project=\"$(MSBuildBinPath)\\Microsoft.CSharp.targets\" />
<Import Project=\"$(MSBuildExtensionsPath)\\Microsoft\\VisualStudio\\v9.0\\WebApplications\\Microsoft.WebApplication.targets\" Condition=\"\" />
<Import Project=\"ImportOverride.Project\" />
This now is pointing to our new .Project file so we now have made a small change to the Project but haven\’t caused it to balloon out and be uncontrollable.
Now save this and go back into Visual Studio you will be prompted to reload the project, reload it and if asked select \”normal mode\” so we get all the good stuff for MSBuild.
Open the ImportOverride.Project file and add the following data:
<?xml version=\”1.0\” encoding=\”utf-8\”?>
<Project ToolsVersion=\”3.5\” DefaultTargets=\”Build\” xmlns=\”http://schemas.microsoft.com/developer/msbuild/2003\”>
<PropertyGroup Condition=\”\’$(Configuration)\’ == \’Debug\’\”>
<PropertyGroup Condition=\”\’$(Configuration)\’ == \’Release\’\”>
<!– Copy web config over –>
<Copy SourceFiles=\”web.config\” DestinationFolder=\”$(BuildPath)\” SkipUnchangedFiles=\”true\” OverwriteReadOnlyFiles=\”true\” />
<!– xslt –>
<Output ItemName=\”XSLT\” TaskParameter=\”Include\” />
<Copy SourceFiles=\”@(XSLT)\” DestinationFiles=\”@(XSLT->\’$(BuildPath)\\%(relativedir)%(Filename)%(Extension)\’)\” SkipUnchangedFiles=\”true\” OverwriteReadOnlyFiles=\”true\” />
<!– user controls –>
<Output ItemName=\”UserControls\” TaskParameter=\”Include\” />
<Copy SourceFiles=\”@(UserControls)\” DestinationFiles=\”@(UserControls->\’$(BuildPath)\\%(relativedir)%(Filename)%(Extension)\’)\” SkipUnchangedFiles=\”true\” OverwriteReadOnlyFiles=\”true\” />
<!– dll files –>
<Output ItemName=\”BinItems\” TaskParameter=\”Include\” />
<Copy SourceFiles=\”@(BinItems)\” DestinationFolder=\”$(BuildPath)\\bin\” SkipUnchangedFiles=\”true\” OverwriteReadOnlyFiles=\”true\” />
<!– debug files (only available in debug mode) –>
<CreateItem Include=\”bin\\*.pdb\” Condition=\”\’$(Configuration)\’ == \’Debug\’\”>
<Output ItemName=\”debugItems\” TaskParameter=\”Include\” />
<Copy SourceFiles=\”@(debugItems)\” DestinationFolder=\”$(BuildPath)\\bin\” SkipUnchangedFiles=\”true\” Condition=\”\’$(Configuration)\’ == \’Debug\’\” OverwriteReadOnlyFiles=\”true\” />
Save the file, now this is the part which is a pain. When ever you make a change to this file you have to \”unload\” and \”reload\” the project for the changes to be taken across (Seems visual studio caches to project instance or something like that).
Once this has been done give build a go and see the results, if everything is setup correctly it should copy over all the files to the umbraco solution. If an update is added to Umbraco and this change is added to the Umbraco folder and checked into Source Control, then all that\’s required from developers is a Get Latest Version from the Umbraco folder and to build the project which will copy over your changed files.
As you can see it\’s actually quite easy to setup MSBuild and separate your external CMS from your code but what you have to remember that there is actually quite a lot and you can almost do anything so go out and have a play. I\’ll leave you on this note, notice in the.Project file we created it had two conditions \”Debug\” and \”Release\” well you can create your own say \”Release – Staging\” which could copy over the files directly to the staging environment or with a little playing around produce an update package. The possibilities are almost endless.