Dec 15 2009

Integrating CruiseControl.NET in your build process

Category: Continuous Integrationryancmartin1976 @ 21:05

First Strategy:

Second Strategy:

Let CruiseControl.NET take care of the heavy lifting!

Automating your daily and nightly builds is the most effective process one can take from the agile methodology processes and procedures. It is also very easy to setup and configure. Once you have it in place, it is on rare occasions when you have to make edits or upgrades to the build process. You can almost say it is as easy as, set it and forget it.

CruiseControl.NET automates your automation of the build process. Download the executable from Source Forge and run the executable on the server where the build process will be run from.

Ok things to note:

The configuration file for CruiseControl.NET lives here C:\Program Files\CruiseControl.NET\server\ccnet.config and this is where you will tell CruiseControl.NET what tasks in the build process to monitor and at what intervals to run at and who to notify when the task is either successful or broke.

There are 2 types of tasks that can be run from the ccnet.config file. First is run directly which special commands that are built right into CruiseControl.NET and the other is calling NAnt build script to run external tasks. You have a lot more flexibility with writing build tasks in NAnt.

ccnet.config – cruise control internal tasks

This task checks subversion for any edits or updates to the server every 120 seconds. If one is found then CruiseControl.NET compiles the solution making sure that the code introduced did not break the build.

<project name="Build">
  <labeller type="defaultlabeller" />
  <webURL>http://localhost/ccnet/ViewFarmReport.aspx</webURL>
 
  <sourcecontrol type="filtered">
    <sourceControlProvider type="svn" autoGetSource="true">
      <executable>C:\Program Files\VisualSVN Server\bin\svn.exe</executable>
      <trunkUrl>http://domain.com/svn/ProjectName/trunk</trunkUrl>
      <workingDirectory>D:\Projects\compile\ProjectName\trunk</workingDirectory>
      <tagOnSuccess>false</tagOnSuccess>
      <tagBaseUrl>http://domain.com/svn/ProjectName/tags</tagBaseUrl>
      <username>rmartin</username>
      <password>********</password>
    </sourceControlProvider>
    <inclusionFilters>
      <pathFilter>
        <pattern>**/*.*</pattern>
      </pathFilter>
    </inclusionFilters>
  </sourcecontrol>
 
  <triggers>
    <intervalTrigger name="continuous" seconds="120" buildCondition="IfModificationExists" />
  </triggers>
 
  <publishers>
    <merge>
      <files>
        <file>C:\Program Files\CruiseControl.NET\server\Build\Artifacts\results.xml</file>
      </files>
    </merge>
    <xmllogger />
    <statistics />
    <email
      from="ProjectNameBuild@domain.com"
      mailhost="mail.domain.com" includeDetails="TRUE">
      <users>
        <user name="Ryan Martin" group="buildmaster" address="rmartin@domain.com"/>
        <user name="Some Guy" group="buildmaster" address="sguy@domain.com"/>
      </users>
      <groups>
        <group name="buildmaster" notification="always"/>
      </groups>
    </email>
  </publishers>
</project>

ccnet.config – nant external tasks

This task is an external task which is run by a nant build script that lives potentially on the build server. You can have your build script wherever you choose but I like to have it with the project and all of its dependencies (documentation, binaries, database scripts and build scripts and reports).

<project name="Deploy-To-Development">
  <labeller type="defaultlabeller" />
  <webURL>http://localhost/ccnet/ViewFarmReport.aspx</webURL>
 
  <sourcecontrol type="filtered">
    <sourceControlProvider type="svn" autoGetSource="true">
      <executable>C:\Program Files\VisualSVN Server\bin\svn.exe</executable>
      <trunkUrl>http://domain.com/svn/ProjectName/trunk</trunkUrl>
      <workingDirectory>D:\Projects\compile\ProjectName\trunk</workingDirectory>
      <tagOnSuccess>false</tagOnSuccess>
      <tagBaseUrl>http://domain.com/svn/ProjectName/tags</tagBaseUrl>
      <username>rmartin</username>
      <password>Madison1</password>
    </sourceControlProvider>
    <inclusionFilters>
      <pathFilter>
        <pattern>**/*.*</pattern>
      </pathFilter>
    </inclusionFilters>
  </sourcecontrol>
 
  <tasks>
    <nant>
      <executable>D:\Projects\compile\ProjectName\trunk\binaries\nant\bin\nant.exe</executable>
      <baseDirectory>D:\Projects\compile\ProjectName\trunk\source\</baseDirectory>
      <buildArgs>-D:svn.executable="D:\Projects\compile\ProjectName\trunk\binaries\subversion\svn.exe"</buildArgs>
      <nologo>false</nologo>
      <buildFile>D:\Projects\compile\ProjectName\trunk\Build\ProjectName.build</buildFile>
      <targetList>
        <target>deploy-to-development</target>
      </targetList>
      <buildTimeoutSeconds>1200</buildTimeoutSeconds>
    </nant>
  </tasks>
 
  <publishers>
    <merge>
      <files>
        <file>C:\Program Files\CruiseControl.NET\server\Deploy-To-Development\Artifacts\results.xml</file>
      </files>
    </merge>
    <xmllogger />
    <statistics />
    <email
      from="ProjectNameBuild@domain.com"
      mailhost="mail.domain.com" includeDetails="TRUE">
      <users>
        <user name="Ryan Martin" group="buildmaster" address="rmartin@domain.com"/>
      </users>
      <groups>
        <group name="buildmaster" notification="always"/>
      </groups>
    </email>
  </publishers>
</project>

ProjectNameWeb.build – nant build script

This script has endless capabilities. There is an extensive set of commands you can call within nant scripts that are specific to nant build process. The command such as exec, echo, delete and copy are easy to learn and understand and most of all extremely powerful in helping cut down on development time by automating everyday remedial tasks.

<?xml version="1.0" encoding="utf-8"?>
<project name="IpswitchftWeb" default="build" xmlns="http://nant.sf.net/release/0.85/nant.xsd">
  <!-- Properties -->
  <property name="devserver.website.dir" value="D:\Projects\www\ProjectName"/>
  <property name="trunk.dir" value="..\" />
  <property name="source.dir" value="${trunk.dir}\Source" />
  <property name="msbuild.exe" value="C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe" />
  <property name="solution.sln" value="${source.dir}\ProjectNameWeb.sln" />
 
  <!-- Called Externally -->
  <target name="build" depends="compile" />
  <target name="deploy-to-development" depends="compile, deploy.to.development" />
 
  <!-- Coding Tasks -->
  <target name="compile">
    <exec program="${msbuild.exe}" commandline="${solution.sln} /t:Rebuild /v:q" />
  </target>
 
  <target name="deploy.to.development">
    <echo message="Deleting all files in development web directory"/>
    <delete verbose="true">
      <fileset basedir="${devserver.website.dir}">
        <include name="*.*" />
      </fileset>
    </delete>
 
    <echo message="XCopy files to development web directory"/>
    <copy todir="${devserver.website.dir}" includeemptydirs="false" overwrite="true">
      <fileset basedir="${ProjectNameWeb.dir}">
        <exclude name="**/obj/**"/>
        <exclude name="**/*.csproj"/>
        <exclude name="**/*.csproj*"/>
        <exclude name="**/App_Data*"/>
        <exclude name="**/App_Data*/**"/>
        <exclude name="**/.svn*"/>
        <exclude name="**/.svn*/**"/>
        <include name="**"/>
      </fileset>
    </copy>
  </target>
</project>

CruiseControl.NET Web Dashboard

This is a web interface to view and run CruiseControl.NET configuration file. From here you can run any task configured in your ccnet.config file and view the results.

This web page url defaults to the localhost setting but you will be viewing it from your local machine like other developers so you must change localhost with the server name: http://servername.domain.com/ccnet/ViewFarmReport.aspx

Tags: , , ,

Dec 15 2009

Integrate FxCop code analysis into CruiseControl.NET

Category: Continuous Integrationryancmartin1976 @ 21:01

First Strategy:

Second Strategy:

Integrating FxCop into CruiseControl.NET

I am not a fan of this technology and I would probably steer away from using this in future projects.

There are three steps in setting up, configuring and viewing the results of FxCop within your Continuous Integration process.

STEP 1

Add a CruiseControl.NET task in your ccnet.config file

<project name="FxCop">
  <labeller type="defaultlabeller" />
  <webURL>http://localhost/ccnet/ViewFarmReport.aspx</webURL>
 
  <sourcecontrol type="filtered">
    <sourceControlProvider type="svn" autoGetSource="true">
      <executable>C:\Program Files\VisualSVN Server\bin\svn.exe</executable>
      <trunkUrl>http://domain.com/svn/ProjectName/trunk</trunkUrl>
      <workingDirectory>D:\Projects\compile\ProjectName\trunk</workingDirectory>
      <tagOnSuccess>false</tagOnSuccess>
      <tagBaseUrl>http://domain.com/svn/ProjectName/tags</tagBaseUrl>
      <username>rmartin</username>
      <password>*******</password>
    </sourceControlProvider>
    <inclusionFilters>
      <pathFilter>
        <pattern>**/*.*</pattern>
      </pathFilter>
    </inclusionFilters>
  </sourcecontrol>
 
  <tasks>
  <exec>
  <executable>C:\Program Files\Microsoft FxCop 1.36\FxCopCmd.exe</executable>
  <baseDirectory>D:\Projects\compile\ProjectName\trunk\source\</baseDirectory>
  <buildArgs>
      /p:"d:\Projects\compile\ProjectName\trunk\Build\rules.FxCop" 
      /out:"c:\Program Files\CruiseControl.NET\server\FxCop\Artifacts\results.xml" /gac
  </buildArgs>
  <buildTimeoutSeconds>300</buildTimeoutSeconds>
  </exec>
  </tasks>
 
  <publishers>
    <merge>
      <files>
        <file>c:\Program Files\CruiseControl.NET\server\FxCop\Artifacts\results.xml</file>
      </files>
    </merge>
    <xmllogger />
    <statistics />
    <email
      from="ProjectNameBuild@domain.com"
      mailhost="mail.domain.com" includeDetails="TRUE">
      <users>
        <user name="Ryan Martin" group="buildmaster" address="rmartin@domain.com"/>
      </users>
      <groups>
        <group name="buildmaster" notification="always"/>
      </groups>
    </email>
  </publishers>
</project>

STEP 2

Add a task in your NAnt build script

<?xml version="1.0" encoding="utf-8"?>
<project name="ProjectNameWeb" default="build" xmlns="http://nant.sf.net/release/0.85/nant.xsd">
  <!-- Properties -->
  <property name="fxcop.output.dir" value="${build.output.dir}\FxCopOutput" />
  <property name="fxcopcmd.exe" value="C:\Program Files\Microsoft FxCop 1.36\fxcopcmd.exe" />
  <property name="rules.fxcop" value="rules.fxcop" />
  <property name="fxcop.xml" value="${fxcop.output.dir}\fxcop.xml" />
 
  <!-- Called Externally -->
  <target name="build" depends="compile" />
  <target name="fxcop" depends="compile, reporting" />
 
  <!-- Coding Tasks -->
  <target name="reporting" depends="compile">
    <exec program="${fxcopcmd.exe}" commandline="/p:${rules.fxcop} /o:${fxcop.xml}" failonerror="false"/>
  </target>
</project>

STEP 3

Go to your CruiseControl.NET Web Dashboard to run and view the results from FxCop

Click the FORCE button for the FxCop task and review the results it generates

NOT WORTH IT IN MY OPINION, RESHARPER DOES A LOT OF THE SAME FUNCTIONALITY IN REAL TIME

Tags: , , , , ,

Dec 15 2009

Deploy Subversion code base into your development environment via CruiseControl.NET

Category: Continuous Integrationryancmartin1976 @ 21:00

First Strategy:

Second Strategy:

Deploy your local code to development for further testing with a click of a button

There are 3 techniques used here to make code deployment seamless for testing in your development environment.

  1. Setup a server to be the development server
  2. Add your project to Subversion
  3. Configure your cruisecontrol.net configuration file and nant build script accordingly

STEP 1

Pick any server to be your development server, potentially one that you use for all projects and sites. This server should mirror your production server, same frameworks, executables and services.

STEP 2

Add your local project to your Subversion server.

STEP 3

Configure the CruiseControl.NET ccnet.config file to call Nant build task without an interval trigger. This assures that the versioned codebase will never get copied over by accident.

<project name="Deploy-To-Development">
  <labeller type="defaultlabeller" />
  <webURL>http://localhost/ccnet/ViewFarmReport.aspx</webURL>
 
  <sourcecontrol type="filtered">
    <sourceControlProvider type="svn" autoGetSource="true">
      <executable>C:\Program Files\VisualSVN Server\bin\svn.exe</executable>
      <trunkUrl>http://domain.com/svn/ProjectName/trunk</trunkUrl>
      <workingDirectory>D:\Projects\compile\ProjectName\trunk</workingDirectory>
      <tagOnSuccess>false</tagOnSuccess>
      <tagBaseUrl>http://domain.com/svn/ProjectName/tags</tagBaseUrl>
      <username>rmartin</username>
      <password>Madison1</password>
    </sourceControlProvider>
    <inclusionFilters>
      <pathFilter>
        <pattern>**/*.*</pattern>
      </pathFilter>
    </inclusionFilters>
  </sourcecontrol>
 
  <tasks>
    <nant>
      <executable>D:\Projects\compile\ProjectName\trunk\binaries\nant\bin\nant.exe</executable>
      <baseDirectory>D:\Projects\compile\ProjectName\trunk\source\</baseDirectory>
      <buildArgs>-D:svn.executable="D:\Projects\compile\ProjectName\trunk\binaries\subversion\svn.exe"</buildArgs>
      <nologo>false</nologo>
      <buildFile>D:\Projects\compile\ProjectName\trunk\Build\ProjectName.build</buildFile>
      <targetList>
        <target>deploy-to-development</target>
      </targetList>
      <buildTimeoutSeconds>1200</buildTimeoutSeconds>
    </nant>
  </tasks>
 
  <publishers>
    <merge>
      <files>
        <file>C:\Program Files\CruiseControl.NET\server\Deploy-To-Development\Artifacts\results.xml</file>
      </files>
    </merge>
    <xmllogger />
    <statistics />
    <email
      from="ProjectNameBuild@domain.com"
      mailhost="mail.domain.com" includeDetails="TRUE">
      <users>
        <user name="Ryan Martin" group="buildmaster" address="rmartin@domain.com"/>
      </users>
      <groups>
        <group name="buildmaster" notification="always"/>
      </groups>
    </email>
  </publishers>
</project>

Next setup the NAnt build script to run a task that does the deployment

<?xml version="1.0" encoding="utf-8"?>
<project name="IpswitchftWeb" default="build" xmlns="http://nant.sf.net/release/0.85/nant.xsd">
  <!-- Properties -->
  <property name="devserver.website.dir" value="D:\Projects\www\ProjectName"/>
  <property name="trunk.dir" value="..\" />
  <property name="source.dir" value="${trunk.dir}\Source" />
  <property name="msbuild.exe" value="C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe" />
  <property name="solution.sln" value="${source.dir}\ProjectNameWeb.sln" />
 
  <!-- Called Externally -->
  <target name="build" depends="compile" />
  <target name="deploy-to-development" depends="compile, deploy.to.development" />
 
  <target name="deploy.to.development">
    <echo message="Deleting all files in development web directory"/>
    <delete verbose="true">
      <fileset basedir="${devserver.website.dir}">
        <include name="*.*" />
      </fileset>
    </delete>
 
    <echo message="XCopy files to development web directory"/>
    <copy todir="${devserver.website.dir}" includeemptydirs="false" overwrite="true">
      <fileset basedir="${ProjectNameWeb.dir}">
        <exclude name="**/obj/**"/>
        <exclude name="**/*.csproj"/>
        <exclude name="**/*.csproj*"/>
        <exclude name="**/App_Data*"/>
        <exclude name="**/App_Data*/**"/>
        <exclude name="**/.svn*"/>
        <exclude name="**/.svn*/**"/>
        <include name="**"/>
      </fileset>
    </copy>
  </target>
</project>

Next run the task from CruiseControl.NET Web Dashboard

This process takes about 30 seconds to 3 minutes depending on the size of the application. You can add all types of files to exclude from the copy over which saves you tons of time in it from doing it manually. This is especially helpful when your project is in Subversion and you have all of those .svn folders everywhere.

Tags: , , ,

Dec 15 2009

Report on your code base for TODO comments via CruiseControl.NET

Category: Continuous Integrationryancmartin1976 @ 20:59

First Strategy:

  • a
  • b
  • c

Second Strategy:

Everyone has to do's in their code comments, so here is an easy way to to check how many you have left in your project

STEP 1

Add a new project to your solution called BuildTasks. Add a new class called ParseCodeDebt.cs

Here is the class code

using System.Diagnostics;
using System.IO;
using NAnt.Core;
using NAnt.Core.Attributes;
 
[TaskName("ParseCodeDebt")]
public class ParseCodeDebt : Task
{
    private string CurrentFolder { get; set; }
 
    public void PerformTest()
    {
        ExecuteTask();    
    }
 
    [TaskAttribute("PathToParse", Required = true)]
    [StringValidator (AllowEmpty = false)]
    public string PathToParse { get; set; }
    protected override void ExecuteTask()
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        Log(Level.Warning,"---------------------------------------------------------------------------");
        Log(Level.Warning, "CODE DEBT CHECK for " + PathToParse);
 
        //iterate through all the files in a directory recursively
        System.IO.DirectoryInfo root = new DirectoryInfo(PathToParse);
        WalkDirectoryTree(root);
 
        Log(Level.Warning, "");
        Log(Level.Warning, "Completed in " + sw.ElapsedMilliseconds + "ms");
        Log(Level.Warning, "---------------------------------------------------------------------------");
        Log(Level.Warning, "");
    }
 
    private void WalkDirectoryTree(System.IO.DirectoryInfo root)
    {
        System.IO.FileInfo[] files = null;
        System.IO.DirectoryInfo[] subDirs = null;
 
        // First, process all the files directly under this folder
        try
        {
            files = root.GetFiles("*.*");
        }
            // This is thrown if even one of the files requires permissions greater
            // than the application provides.
        catch (UnauthorizedAccessException e)
        {
            // This code just writes out the message and continues to recurse.
            Log(Level.Warning, e.Message);
        }
 
        catch (System.IO.DirectoryNotFoundException e)
        {
            Log(Level.Warning, e.Message);
        }
 
        if (files != null)
        {
            foreach (System.IO.FileInfo fi in files)
            {
                if (fi.Name.ToLower().EndsWith(".cs") && fi.Name.ToLower() != "parsecodedebt.cs")
                {
                    try
                    {
                        //look for code debt in this file
                        ParseFile(fi);
                    }
                    catch (FileNotFoundException e)
                    {
                        Log(Level.Warning, e.Message);
                    }
                }
            }
 
            // Now find all the subdirectories under this directory.
            subDirs = root.GetDirectories();
 
            foreach (System.IO.DirectoryInfo dirInfo in subDirs)
            {
                if (dirInfo.Name != ".svn")
                {
                    // Resursive call for each subdirectory.
                    WalkDirectoryTree(dirInfo);
                }
            }
        }
    }
 
    private void ParseFile(FileInfo file)
    {
        StreamReader sr = file.OpenText();
        int lineNumber = 1;
        string line = "";
        line = sr.ReadLine();
        while(line!=null)
        {
            if(line.ToLower().Contains("//codedebt"))
            {
                if (CurrentFolder != file.DirectoryName)
                {
                    CurrentFolder = file.DirectoryName;
                    Log(Level.Warning, "");
                    Log(Level.Warning, CurrentFolder);
                }
                Log(Level.Warning, "\t" + file.Name);
                string[] attributes = line.ToLower().Replace("//codedebt","").Trim().Split('|');
                Log(Level.Warning, "\tLine " + lineNumber.ToString());
                foreach (string s in attributes)
                {
                    Log(Level.Warning, "\t" + s.Trim());
                }
            }
            lineNumber++;
            line = sr.ReadLine();
        }
        sr.Close();
    }
}

STEP 2

Next you need to create a new NAnt build task, here is the code

<?xml version="1.0" encoding="utf-8"?>
<project name="ProjectNameWeb" default="build" xmlns="http://nant.sf.net/release/0.85/nant.xsd">
  <!-- Properties -->
  <property name="trunk.dir" value="..\" />
  <property name="dependencies.dir" value="${trunk.dir}\dependencies" />
 
  <!-- Custom Assemblies -->
  <loadtasks assembly="${dependencies.dir}\CustomBuildTasks\CustomBuildTasks.dll"/>
  <loadtasks assembly="${dependencies.dir}\NCover\NCover.NAntTasks.dll"/>
  <loadtasks assembly="${dependencies.dir}\NCover\NCoverExplorer.NAntTasks.dll"/>
 
  <!-- Called Externally -->
  <target name="findToDo" depends="compile, parseCodeDebt" />
 
  <!-- Coding Tasks -->
  <target name="parseCodeDebt">
  <ParseCodeDebt RootPathToParse="${ProjectNameWeb.dir}" 
    DirectoriesToIgnore=".svn,_ReSharper.ProjectNameWeb" 
    FileTypeToProcess=".cs" />
  <ParseCodeDebt RootPathToParse="${ProjectNameWebTests.dir}" 
    DirectoriesToIgnore=".svn,_ReSharper.ProjectNameWeb" 
    FileTypeToProcess=".cs" />
  </target>
</project>

STEP 3

Go to your log4net output directory and open up the file and your Custom NAnt Build task should of dumped all of the data there

some more text here

Tags: , , , ,

Dec 15 2009

Compile your solution with and without MSBuild via CruiseControl.NET

Category: Continuous Integrationryancmartin1976 @ 20:57

First Strategy:

Second Strategy:

Compiling your solution every time subversion has a new commit

There are 2 ways to compile a solution in CruiseControl.NET, with MSBuild and without. I use both, one, without, is very simple process and runs every time a new file is committed to Subversion.

Compiling without MSBuild in ccnet.config

<project name="Build">
  <labeller type="defaultlabeller" />
  <webURL>http://localhost/ccnet/ViewFarmReport.aspx</webURL>
 
  <sourcecontrol type="filtered">
    <sourceControlProvider type="svn" autoGetSource="true">
      <executable>C:\Program Files\VisualSVN Server\bin\svn.exe</executable>
      <trunkUrl>http://domain.com/svn/ProjectName/trunk</trunkUrl>
      <workingDirectory>D:\Projects\compile\ProjectName\trunk</workingDirectory>
      <tagOnSuccess>false</tagOnSuccess>
      <tagBaseUrl>http://domain.com/svn/ProjectName/tags</tagBaseUrl>
      <username>rmartin</username>
      <password>********</password>
    </sourceControlProvider>
    <inclusionFilters>
      <pathFilter>
        <pattern>**/*.*</pattern>
      </pathFilter>
    </inclusionFilters>
  </sourcecontrol>
 
  <triggers>
    <intervalTrigger name="continuous" seconds="120" buildCondition="IfModificationExists" />
  </triggers>
 
  <publishers>
    <merge>
      <files>
        <file>C:\Program Files\CruiseControl.NET\server\Build\Artifacts\results.xml</file>
      </files>
    </merge>
    <xmllogger />
    <statistics />
    <email
      from="ProjectNameBuild@domain.com"
      mailhost="mail.domain.com" includeDetails="TRUE">
      <users>
        <user name="Ryan Martin" group="buildmaster" address="rmartin@domain.com"/>
        <user name="Some Guy" group="buildmaster" address="sguy@domain.com"/>
      </users>
      <groups>
        <group name="buildmaster" notification="always"/>
      </groups>
    </email>
  </publishers>
</project>

Compiling with MSBuild in my nant build script

<?xml version="1.0" encoding="utf-8"?>
<project name="ProjectNameWeb" default="build" xmlns="http://nant.sf.net/release/0.85/nant.xsd">
  <!-- Properties -->
  <property name="devserver.website.dir" value="D:\Projects\www\ProjectName"/>
  <property name="trunk.dir" value="..\" />
  <property name="source.dir" value="${trunk.dir}\Source" />
  <property name="msbuild.exe" value="C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe" />
  <property name="solution.sln" value="${source.dir}\ProjectNameWeb.sln" />
 
  <!-- Called Externally -->
  <target name="build" depends="compile" />
 
  <!-- Coding Tasks -->
  <target name="compile">
    <exec program="${msbuild.exe}" commandline="${solution.sln} /t:Rebuild /v:q" />
  </target>
</project>

Seeing the results

Launch the CruiseControl.NET from Programs -> CruiseControl.NET -> CruiseControl.NET from the server where you installed CruiseControl.NET. The software will run the tasks in the configuration file you setup in ccnet.config

I recommend using the windows service which runs continuously and does all of the automation for you based off of the interval trigger you setup in the file as well. The interval triggers are task specific.

And lastly you can force builds and view the result in the CruiseControl.NET Web dashboard.

Tags: , , , ,