ASP.NET website Continuous Integration+Deployment using CruiseControl.NET, Subversion, MSBuild and Robocopy

You can setup continuous integration and automated deployment
for your web application using CruiseControl.NET, Subversion,
MSBuild and Robocopy. I will show you how you can automatically
build the entire solution, email build report to developers and QA,
deploy latest code in IIS all using CruiseControl.NET every N
minutes.

First get the following:

You will learn how I have configured Continuous Integration and
Deployment for my open source AJAX Portal project "http://www.Dropthings.com">www.Dropthings.com. The code is
hosted at CodePlex. When some developer makes a commit,
CruiseControl downloads the latest code, builds the entire
solution, emails build report and then deploys the latest web site
to IIS 6.0.

After installing CruiseControl.NET, go to "text-decoration:underline;">Programs -> Cruise Control ->
CruiseControl.NET Config
.

Now keep copying and pasting the following XML blocks and make
sure you understand each block and make necessary changes:

"border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:94.58%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, 'Courier New', courier, monospace;height:301px;background-color:#f4f4f4;">
"padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, 'Courier New', courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">

   1: <cruisecontrol>

   2:     <project name="Dropthings" queue="DropthingsQueue" queuePriority="1">

   3:         

   7:         <workingDirectory>d:ccdropthingscodetrunkworkingDirectory>

   8:         

   9:         <artifactDirectory>d:ccdropthingsartifactartifactDirectory>

  10:         <category>Dropthingscategory>

  11:         

  12:         <webURL>http://localhost/ccnet/webURL>

  13:         <modificationDelaySeconds>60modificationDelaySeconds>

  14:         <labeller type="defaultlabeller">

  15:             <prefix>0.1.prefix>

  16:             <incrementOnFailure>trueincrementOnFailure>

  17:             <labelFormat>000labelFormat>

  18:         labeller>

  19:         <state type="state" directory="State" />

First change the working directory. It needs to be the path of
the folder where you will have the solution downloaded. I generally
create folder structure like this:

  • D:CC – Root for all CC.NET enabled projects
    • ProjectName – Root project folder
      • Code – Code folder where code is downloaded from
        subversion
      • Artifact – CC.NET generates a lot of stuff. All goes
        here.

Next comes the Subversion integration block:

"border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, 'Courier New', courier, monospace;background-color:#f4f4f4;">
"padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, 'Courier New', courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">

   1: <sourcecontrol type="svn">

   2:     

   3:     <trunkUrl>http://localhost:8081/tfs02.codeplex.com/dropthings/trunktrunkUrl>

   4:     <workingDirectory>workingDirectory>

   5:     <username>***** SUBVERSION USER NAME *****username>

   6:     <password>***** SUBVERSION PATH *****password>

   7: sourcecontrol>

Here specify the subversion location where you want to download
code to the working folder. You should download the entire solution
because you will be building the entire solution using MSBuild
soon.

I left "text-decoration:underline;"> empty.
This means whatever is specified earlier in the "text-decoration:underline;"> is
used. Otherwise you can put some relative folder path here or any
absolute folder.

Now we start building the tasks that CC.NET executes – Build,
Email, and Deploy.

"border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, 'Courier New', courier, monospace;background-color:#f4f4f4;">
"padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, 'Courier New', courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">

   1: <tasks>

   2:     <artifactcleanup   cleanUpMethod="KeepLastXBuilds"   cleanUpValue="5" />

   3:     <modificationWriter>

   4:         <filename>mods.xmlfilename>

   5:         <path>path>

   6:     modificationWriter>

   7:

   8:     

   9:     <msbuild>

  10:         <executable>C:windowsMicrosoft.NETFramework64v3.5MSBuild.exeexecutable>

  11:         <workingDirectory>workingDirectory>

  12:         <projectFile>Dropthings.msbuildprojectFile>

  13:         <targets>Buildtargets>

  14:         <timeout>300timeout>

  15:         <logger>C:Program Files (x86)CruiseControl.NETserverThoughtWorks.CruiseControl.MsBuild.dlllogger>

  16:     msbuild>

This block first says, keep artifacts for last 5 build and
remove olders. Artifacts are like build reports, logs etc. You can
increase the value for longer history.

Then the most important "text-decoration:underline;"> task. The
executable path is to the MSBuild.exe. I am using .NET 3.5
Framework 64bit edition. You might have .NET 2.0 and 32bit version.
So, set the right path here for the MSbuild.exe.

"text-decoration:underline;"> maps to a
MSBuild file. It’s a skeleton MSBuild file which basically says
build this Visual Studio solution file. Here’s how the msbuild file
looks like:

"border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, 'Courier New', courier, monospace;background-color:#f4f4f4;">
"padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, 'Courier New', courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <Target Name="Build">

    

    <MSBuild Projects="Dropthings.sln" Targets="Rebuild" />

  Target>

Project>

The "text-decoration:underline;">Dropthings.msbuild and
Dropthings.sln file
exists in the same trunk folder. This file says – build
Dropthings.sln and do a rebuild.

Now you got the build done. Next is to deploy it. You will be
using robocopy to copy files from the code folder to a destination
folder which is mapped in IIS to a website. Robocopy will do a
synchronization of the directories. It will add new files,
overwrite old files and removes files from destination folder which
no longer exists in the source folder.

Before you can deploy, you need to stop the website or restart
IIS. Otherwise some files may be in use and you will not be able to
delete or overwrite the files. Here’s how to stop IIS using the
iisreset command
line tool:

"border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, 'Courier New', courier, monospace;background-color:#f4f4f4;">
"padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, 'Courier New', courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">



<exec>

    <executable>iisresetexecutable>

    <buildArgs>/stopbuildArgs>

exec>

If you do not want to stop the entire IIS, instead just stop a
website and recycle an application pool, you can use the iisweb.vbs
script for stopping a website and iisapp.vbs script for recycling
application pool. Here’s an example:

"border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, 'Courier New', courier, monospace;background-color:#f4f4f4;">
"padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, 'Courier New', courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">

<exec>

    <executable>iiswebexecutable>

    <buildArgs>/stop "Dropthings"buildArgs>

exec>



<exec>

    <executable>iisappexecutable>

    <buildArgs> /a "Dropthings" /rbuildArgs>

exec>

You need to first register "text-decoration:underline;">cscript as the default script
runtime. In order to do this, go to command line and enter iisweb.
It will tell you that it cannot use wscript to run this script and
it needs to make cscript default. Let it make cscript as
default.

Now the time to do the deployment of latest web site files. The
following task launches robocopy to do the deployment:

"border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, 'Courier New', courier, monospace;background-color:#f4f4f4;">
"padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, 'Courier New', courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">



<exec>

    

    <executable>robocopy.exeexecutable>

    <baseDirectory>DropthingsbaseDirectory>

    <buildArgs>. d:ccDropthingsDeploy *.* /E /XA:H /PURGE /XO /XD ".svn" /NDL /NC /NS /NPbuildArgs>

    <buildTimeoutSeconds>60buildTimeoutSeconds>

    <successExitCodes>1,0successExitCodes>

exec>

First you need to correct the robocopy.exe path. For Windows
Vista/Windows 2008, keep it as it is. For Windows 2003, you need to
specify the full path. You also need to remove the (x86) from the
path if you have 32bit OS.

Next is the "text-decoration:underline;">. This is
relative to the working directory. It’s the path of the website
folder. Dropthings website folder is located under the Dropthings
folder under trunk. So, I have specified Dropthings as the
subfolder where the website files are located. You need to specify
your project’s website folder’s relative path here form the
"text-decoration:underline;">.

Next change the path in the "text-decoration:underline;"> node. First
one is the source “.” which you keep as it is. It means copy files
from the "text-decoration:underline;">baseDirectory. Next is the
absolute path to the deployment folder where the web site is mapped
in IIS. You can use both relative or absolute path here. While
using relative path, just keep in mind the robocopy is running from
the folder.

After the path keep the *.* and the remaining flags intact. The
flags mean:

  • Copy all subdirectories /E
  • Copy hidded files /XA:H
  • Do not copy old files /XO
  • Exclude .svn directory while copying files /XD “.svn”
  • Do not show list of files and directories being copie /NDL,
    /NC, /NP

After the deployment, you need to turn IIS back on or start the
website that you stopped:

"border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, 'Courier New', courier, monospace;background-color:#f4f4f4;">
"padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, 'Courier New', courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">



<exec>

    <executable>iisresetexecutable>

    <buildArgs>/startbuildArgs>

exec>




Now we got the build and deployment done. Next is to email a
nice report to developers and QA. If build succeeds, email both
developers and QA so that they can check out the latest build. But
if build fails, email only developers.

"border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, 'Courier New', courier, monospace;background-color:#f4f4f4;">
"padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, 'Courier New', courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">

<publishers>

    <rss/>

    <xmllogger />

    <statistics />



    

    <email from="admin@yourcompany.com" mailhost="localhost" mailport="25" includeDetails="TRUE"

           mailhostUsername="" mailhostPassword="" useSSL="FALSE">



        <users>

            <user name="Developer1" group="devs" address="dev1@yourcompany.com"/>

            <user name="Developer2" group="devs" address="dev2@yourcompany.com"/>

            <user name="Developer3" group="devs" address="dev3@yourcompany.com"/>



            <user name="QA1" group="qa" address="qa1@yourcompany.com"/>

            <user name="QA2" group="qa" address="qa2@yourcompany.com"/>

            <user name="QA3" group="qa" address="qa3@yourcompany.com"/>



        users>



        <groups>

            <group name="devs" notification="Always"/>

            <group name="qa" notification="Success"/>

        groups>



        <converters>

            

        converters>



        <modifierNotificationTypes>

            <NotificationType>AlwaysNotificationType>

        modifierNotificationTypes>



    email>

    <modificationHistory  onlyLogWhenChangesFound="true" />

publishers>

First you need to change the "text-decoration:underline;"> tab where you
specify the from address, mail server name, and optionally a user
account for the email address that you need to use to send out
emails.

Then edit the "text-decoration:underline;"> node and put your
developers and QA.

That’s it! You got the configuration file done. Next step is to
launch the CruiseControl.NET from Programs -> CruiseControl.NET
-> CruiseControl.NET. It will launch a process that will execute
the tasks according to the configuration. On Windows Vista, you
will have to run it with Administrative privilege.

There’s also a Windows Service that gets installed. It’s named
CruiseControl.NET. You can start the service as well on a server
and go to sleep. It will do continuous integration and automated
deployment for you.

There’s also a web based Dashboard that you can use to force a
build or stop a build or see detail build reports.

"/wp-content/images/C397C8EFD2E3765F0D0CD4F7E22FDD97.png">
"/wp-content/images/E0F877B28A11DEBE53BEF00FD0711AB6.png"
alt="image" height="272" style=
"border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;">

You can create multiple projects. You can have one project to
build trunk code only, but do no deployment. Then you can create
another project to build, deploy some branch that’s ready for
production. You can create another project to build and deploy on
QA server and so on.

"http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/ccnet.zip">
Here’s the full configuration file
that you can use as your
baseline.

"padding-right:0px;display:inline;padding-left:0px;padding-bottom:0px;margin:0px;padding-top:0px;"
id=
"scid:B3E14793-948F-49af-A347-D19C374A7C4F:f699e682-0ab4-4a9d-97ad-c7aa1944438d"
class="wlWriterSmartContent">

"http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f10%2f06%2fasp-net-website-continuous-integration-deployment-using-cruisecontrol-net-subversion-msbuild-and-robocopy.aspx">
kick it on DotNetKicks.com "http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f10%2f06%2fasp-net-website-continuous-integration-deployment-using-cruisecontrol-net-subversion-msbuild-and-robocopy.aspx">

24 Comments

  1. This is really helpful article. I have heard that CIFactory is also doing great job in Continuous Integration. If you write something about that, it will also really help us.

    thanks !!

    Pathik

  2. Hi Omar.

    Just wanted to say thanks. I've been looking to do this for a while but have not done it due to the perceived learning curve. This article was a great way to get started for us.

    Very nice of you to share your work with the community.

    Cheers!

  3. re: ASP.NET website Continuous Integration+Deployment using CruiseControl.NET, Subversion, MSBuild and Robocopy

    Hi Omar.

    Dropthings.com is a wonderful website, but I found a bug recently, not a serious one, but I think you might be interested.

    Here is the bug:

    When I add a new stuff in a tab, for example “How to the Day”. Assume that I have two other widget in this tab already:BBC & CNN, with the order that CNN located under BBC, both in the same column. Now I drag the new widget “How to the Day ” to the bottom of the column,(the same column with BBC & CNN) and we have the order: BBC, CNN and then How to the Day, the same order I was expected after I refreshed this page. After I made a refresh, however, the order comes out like: BBC, How to the Day and then CNN, which means the new widget I dragged moved upward after refreshment.

    Hope you can check it out.

    :)

  4. re: ASP.NET website Continuous Integration+Deployment using CruiseControl.NET, Subversion, MSBuild and Robocopy

    When you want to auto deploy, why not use web deployment project?

    hxxp://msdn.microsoft.com/en-us/asp.net/aa336619.aspx

    secondly, you have not touched upon testing. I have toyed with automating FxCop

    hxxp://msdn.microsoft.com/en-us/library/bb429476(VS.80).aspx

    ccnet.config changes:

    c:Program Files (x86)Microsoft FxCop 1.36fxcopcmd

    c:ProjectsmyProject

    /file:applicationbinmydll.dll /o:ccnet-fxcop.xml

    100

    c:ProjectsmyProjectccnet-fxcop.xml

    dashboard.config changes:

    xslfxcop-summary.xsl

    xslfxcop-summary2.xsl

    —-

    Have not time to do nUnit ( hxxp://www.nunit.org/ ) and or SandCastle ( hxxp://blogs.msdn.com/sandcastle/ ) integrations yet

  5. This is great! I've seen a lot of examples using VSS but this is what I was looking for. I need to book mark this page. I will go forward with this and hope thtis helps me!

  6. Omar,

    Nice post. But how about the database changes? I would also like to run database scripts on the server while deploying the application. Any idea?

    Thanks in advance.

    Milan

  7. Hi Omar,

    How do you configure and deploy for different builds such as “debug” and “release”?

    Connection strings and different environment settings should be picked up in those builds so how would you achieve that?

    Thanks

  8. Awesome! I read your book when it released and loved it. Keep up the great work!

  9. excellent article. I have added aspnet_compiler within msbuild but somehow its not working. How if you can give some hint on that too ??? It has some problem with webconfig saying “MachineToApplication” setting has problem, I searched for solution and it says if I have multiple web config, but my project has only 1 web config.

    Please throw some light on that.

  10. re: ASP.NET website Continuous Integration+Deployment using CruiseControl.NET, Subversion, MSBuild and Robocopy

    Just going through your tutorial, thought I would just point out that you are missing some closing tags in your XML. This may lead to some confusion to newbies who are copying and pasting your code to have a look ( it did confuse me :-) )

    Otherwise I enjoyed it and it helped me get something going.

  11. Hi

    Its great article, but i have some more question to you is that how we can deploy the build code to different server i.e. QA, prod.

    What is best way to deploy to different server in your advice plz

    nlohchab@aim.com

  12. Hi Omar,

    I asked you earlier also in my comments the query i have regarding the deployment process with robocopy on to our different environment i.e. QA and dev servers(machines) After build : I need to deploy my latest code to other staging servers automatically with CruiseControl as I am using MSBuild, CruiseControl.net, SVN, and off course want to use robocopy for the deployment. if possible could you guys explain me a bit more about it, ccnet.config file will me really helpfull with bit explaination. As i ahve to copy my latest build from different location (multiple files)and as I already says to copy in specific directories on other environment.

    I really appericiate yor help and direction in this matter.

    Gary mention in his previos remarks that blog missed some xml in blog description, plz as i am also new to CI, guide me in that regard as well.

    Thanks

    nlohchab@aim.com

  13. Hi,

    What's about CVS' integration?

    Is it possible? Is it similar to Subversion's?

    Regards,

    Miodrag

  14. re: ASP.NET website Continuous Integration+Deployment using CruiseControl.NET, Subversion, MSBuild and Robocopy

    When runnig iisweb, you need to do this:

    cmd.exe /c iisweb /stop “Dropthings”

    or you get errors when attempting to execute the script.

    Rich

  15. re: ASP.NET website Continuous Integration+Deployment using CruiseControl.NET, Subversion, MSBuild and Robocopy

    can any one plz suggest, how can we build and then publish using same scenario

  16. Thank you for submitting this cool story – Trackback from PimpThisBlog.com

  17. web deployment project are very powerful to deploy a project and fully customizable since they’re based on msbuild file format.
    It’s possible to create the web deployment project and then edit the file with notepad and extend it with build, gallio for unit tests, etc…

    Also TeamCity is a much more easy to configure tool compared with cruisecontrol.

    anyway, great post

  18. It is very nice article.
    One Point is that …
    When deploying the .aspxdesigner.cs and .aspx.cs files are also are also deploying.
    But when we publish we only need only compiled .aspx page.
    How it could be possible?

  19. Pingback: http://%/bvyfdep

  20. thanks for a nice article.

    to run an executable which is there in system32, you have used the with build args. now if we want to run a application specific executable present in some location how can we run it. when i tried it is giving an “nused node detected”. please help me out here.

    Thanks
    Phanivikranth

  21. I don’t know why CVS is even something people talk about and use anymore. It’s a joke now that we have REAL source control out here such as SVN, TFS (well I don’t really like TFS), Git, etc.

    What the hell is this CVS or VSS shit still being talked about in 2011 for God sakes! We’re all the way in 2011 and you’re still using these old piles of shit? Stop! That’s such an amateur way to run a shop. Yea they used to be the way to go, 8-10 years ago! Technology changes and improves ten fold….start changing your process and tools for God sakes.

    You are developers still using this? This is sad for our profession if we can’t get people off this legacy shit source control.

    Wake up.

  22. HI,

    Thanks for the nice article.

    I needed one help while sending mail, I want only my text in the body like “Your results are here” and not the default text saying build time, success, who committed etc.

    Can you please help me out in this?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>