Feb
3
Posted by:
Jon Henning
2/3/2009
Last post in this series we learned some basics of MSBuild, including the use of 3rd party tasks. We saw that by simply importing some other targets file we can extend the functionality available to our scripting language. The last two pieces to this puzzle happen to be solved by use of 3rd party plugins available on CodePlex: Deployment and Automating our Build.
Deployment
Every build we wish to publish can easily be published to our project page via the CodePlex MSBuild tasks. The first step is to import the CodePlex targets file into our script.
<Import Project="$(RootDir)\lib\MSBuildCodePlexTasks\CodePlex.WebServices.Client.Targets" Condition="'$(DeployToCodePlex)' == '1'" />
With our custom tasks imported, creating a new release is as simple as defining a new target and setting a bunch of properties.
<Target Name="DeployToCodePlex" Condition="$(DeployToCodePlex) == '1' and $(ConfigurationName)=='Release'" >
<CreateRelease
ProjectName="$(ProjectName)"
ReleaseName="v$(Major).$(Minor).$(Build).$(Revision) - Nightly"
IsDefaultRelease="$(IsDefaultRelease)"
ShowToPublic="$(ShowToPublic)"
ShowOnHomePage="$(ShowOnHomePage)"
Description="$(Description)"
ReleaseDate="$(ReleaseDate)"
ReleaseStatus="$(ReleaseStatus)"
Username="$(User)"
Password="$(Password)" />
Most of the properties mentioned here are pretty self-evident. What may not be is where they are defined. The fact that we are publishing our source code to the central server and it is this code that we are using to publish code, it probably is not a good idea to put our username and password directly into this script, or any script that gets uploaded to our source control. Instead, what I chose to do was create a file outside my folder structure that gets imported when it exists.
<Import Project="$(RootDir)\..\..\DNNWCNonDist.Targets" Condition="Exists('$(RootDir)\..\..\DNNWCNonDist.Targets')" />
This will allow your users who download your code to still run most of your build tasks, but will not give them rights to create a public release! The basics of this file are as follows.
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DeployDir>$(RootDir)\deploy</DeployDir>
<DeployToCodePlex>1</DeployToCodePlex>
<DeployToWebcontrolsSite>0</DeployToWebcontrolsSite>
<DotNetNukeDir>D:\dev\DotNetNuke\Core_Development\DotNetNuke_Cambrian\Website</DotNetNukeDir>
<WebSiteDir>$(RootDir)\website</WebSiteDir>
<!-- CodePlex Properties-->
<IsDefaultRelease>false</IsDefaultRelease>
<ShowToPublic>false</ShowToPublic>
<ShowOnHomePage>false</ShowOnHomePage>
<Description>Nightly Build</Description>
<ReleaseStatus>Planned</ReleaseStatus>
<User>******</User>
<Password>******</Password>
</PropertyGroup>
</Project>
With our release created it is now time to use another task to upload our files. First we need to define what files to use by creating an ItemGroup.
<ItemGroup>
<ReleaseFile Include="$(DeployDir)\WebControls.install.v$(Major).$(Minor).$(Build).$(Revision).zip">
<FileType>RuntimeBinary</FileType>
</ReleaseFile>
<ReleaseFile Include="$(DeployDir)\WebControls.source.v$(Major).$(Minor).$(Build).$(Revision).zip">
<FileType>SourceCode</FileType>
</ReleaseFile>
</ItemGroup>
We then use the UploadFiles task to cause our files to be uploaded.
<UploadFiles
ProjectName="$(ProjectName)"
ReleaseName="v$(Major).$(Minor).$(Build).$(Revision) - Nightly"
ReleaseFiles="@(ReleaseFile)"
Username="$(User)"
Password="$(Password)" />
Triggering an Automated Build
In order to completely automate our process, we need a piece of software to monitor our source code at some defined interval and pull down any changes, then simply initiate our build process. Since all of our deployment logic is encapsulated in our build script this is probably the easiest portion to configure. I chose to use CruiseControl.NET running locally to handle my builds mainly due to the fact that CodePlex offers a sourcecontrol block for us found here. If your new to CruiseControl.NET I suggest digging through their documentation. Once you have cruise installed simply follow the instructions on the CodePlex page: Copy 3 dlls into the CruiseControl.NET\Server folder and make sure you have the J# redistributable installed. Yes, I agree, requiring J# for a .NET plugable architecture like Cruise is a bit odd. To configure your project simply find the CruiseControl.NET Start menu entry and choose CruiseControl.NET Config to edit the xml file used in setting up your project.
<cruisecontrol>
<project>
<name>DotNetNuke_WebControls</name>
<triggers>
<intervalTrigger seconds="3000" buildCondition="IfModificationExists"/>
</triggers>
<workingDirectory>E:\dev\DotNetNuke\CodePlex\DotNetNuke.WebControls</workingDirectory>
<sourcecontrol type="codeplex">
<project>dnnwebcontrols</project>
<projectPath>/trunk</projectPath>
</sourcecontrol>
<tasks>
<msbuild>
<executable>C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>
<workingDirectory>E:\dev\DotNetNuke\CodePlex\DotNetNuke.WebControls\</workingDirectory>
<projectFile>DotNetNuke.WebControls.sln</projectFile>
<buildArgs>/noconsolelogger /p:Configuration=Release /v:diag</buildArgs>
<targets>Build</targets>
<timeout>3000</timeout>
<logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</msbuild>
</tasks>
</project>
</cruisecontrol>
With cruise you simply define an interval trigger to pull your sourcecode directory. I chose to only perform a build if a modification has taken place, which I believe is the default. The interaction with CodePlex is all handled by their plugin, simply specify the project name and path within the source control tree to pull and then launch a msbuild task passing in your solution file. You will notice that there is no secure information here. Instead it will be assumed that the DNNWCNonDist.Targets file, mentioned earlier, will be relatively located to the working directory. Without this file our builds will still work, they just won't be published.
Closing Thoughts
Obviously I could have spent a lot of time going into each of the details on how to customize your own build environment. I purposefully chose to address this series at a higher level, to try and give you a roadmap of where to start and what are the pieces you need to consider. Hopefully you found it helpful.
1 comment(s) so far...
Re: Getting Continuous Integration Working With CodePlex: Part III
jon, thanks for the great series of posts -i'll be setting up my own codeplex project soon and this will save me tons of time.
By cathal connolly on
2/4/2009
|