Installation

Installation

After downloading you will need to unzip the CI Factory distributable. Anywhere is good, I have it in C:\Tools. That's it, the install is done.

Tailoring the Installer

To tailor CI Factory to install a CI Server that meets the needs of your project you will need to edit the Arguments.xml file.  It is located in the Install Scripts directory.  There is a Visual Studio 2005 solution file that includes all the file you might want to edit.  Please open the solution (see figure 1).


cifactoryfolder.jpg

Figure 1

 

When you open up the file to edit, it should look like this:

<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://nant.sf.net/schemas/nant.xsd" name="Arguments">
  <!--Use Install.Package to install one or more Packages to an existing CI Factory Project.-->
  <property name="Install.Action" value="Install.Project" />
  <property name="ProjectName" value="TestProject" />
  <property name="CCNET.LabelPrefix" value="1.0.0."/>
  <property name="InitialVersion" value="1.0.0.0"/>
 
  <property name="ProjectsDirectory"        value="c:\Projects" overwrite="false"/>
  <property name="ProjectCodeLineName"      value="Current" overwrite="false"/>
  <property name="ProductDirectoryName"     value="Product"/>
  <property name="ThirdPartyDirectoryName"  value="Third Party"/>
  <property name="ProductionDirectoryName"  value="Production"/>
  <property name="UnitTestDirectoryName"    value="Unit Test"/>
  <property name="InstallDirectoryName"     value="Install"/>
 
  <include buildfile="Properties.Install.xml"/>
  <property name="CCNET.ServerName" value="${environment::get-machine-name()}"/>
  <property name="CCNET.ServerPort" value="21236"/>
  <property name="EmailHost"        value="127.0.0.1"/>
  <property name="CCNET.ModificationDelaySeconds" value="120"/>
  <property name="CCNET.IntervalTrigger" value="90"/>
  <property name="BuildMaster.Name" value="BuildMaster"/>
  <property name="BuildMaster.Email" value="
 This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
 "/>
  <largeproperty name="Developer.List">
    <value expand="true" xml="true">
      <user name="bill.smith" group="developer"  address="
 This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
 "/>
    </value>
  </largeproperty>
 
  <property name="SVN.URI.Root" value="https://${ProjectName}.googlecode.com/svn"  />
  <property name="SVN.URI.ProjectName" value="${SVN.URI.Root}" /> <!--In a shared repo this might be "${SVN.URI.Root}/${ProjectName}"-->
  <property name="SVN.URI.ProjectCodeLine" value="${SVN.URI.ProjectName}/${ProjectCodeLineName}"/>
 
  <property name="CCNet.SVN.URI.ProjectName" value="https://&ProjectName;.googlecode.com/svn" />
  <property name="CCNet.SVN.URI.ProjectCodeLine" value="${CCNet.SVN.URI.ProjectName}/&ProjectCodeLineName;" />
 
  <property name="SVN.WebVisible" value="true" />
  <property name="CCNet.SVN.WebRepoUrl" value="http://&ProjectName;.googlecode.com/svn"/><!--makes shure that the case is correct, Tags or tags-->
 
  <property name="SVN.Credentials.SafeStorage" value="false"/><!--Set to true if you do not want the build users credentials stored in the repository for ?anyone? to see.-->
  <property name="SVN.Username" value="Build" />
  <property name="SVN.Password" value="password" />
 
  <property name="Coverage.UnitTestPackageInclude" value="${PackagesDirectory.Ref}\DotNetUnitTest\UnitTest.Target.xml" />
  <property name="Coverage.UnitTestPropertiesInclude" value="${PackagesDirectory.Ref}\DotNetUnitTest\UnitTest.Properties.xml" />
 
  <strings id="Packages.InstallList">
    <string value="Subversion"/>
    <string value="CSDiff" />
    <string value="SourceModificationReport"/>
    <string value="Versioning"/>
    <string value="MSBuild" />
    <string value="NCover" />
    <string value="DotNetUnitTest"/>
    <string value="nDepend"/>
    <string value="FxCop"/>
    <string value="Simian" />
    <string value="Analytics" />
    <string value="Alerts" />
 
    <string value="Deployment"/>
    <string value="Workspace"/>
 
    <!--
    <string value="LinesOfCode"/>
    <string value="VisualSourceSafe"/>
    <string value="Perforce"/>
    <string value="Ant"/>
    <string value="Backup" />
    <string value="VS.NETCompile"/>
    <string value="MSTest" />
    <string value="Tracker"/>
    <string value="InstallShield"/>
    <string value="Vault"/>
    <string value="VSTSVersionControl" />
    -->
  </strings>
 
  <target name="Post.Install">
    <nant buildfile="${PackagesDirectory}\Workspace\Workspace.Setup.xml" inheritall="false" inheritrefs="false" target="WorkspaceSetup.CreateSfx" />
 
    <nant buildfile="${BuildDirectory}\Common.Build.xml" target="Common.CreateCCTraySfx">
      <properties>
        <property name="WinRarProgramPath" value="${property::expand(WinRarProgramPath)}" />
        <property name="BuildServerHostName" value="${CCNET.ServerName}"/>
        <property name="BuildServerPort" value="${CCNET.ServerPort}"/>
        <property name="CCNetBuildDate" value="2006-09-12"/>
        <property name="CCNetBuildTime" value="11:10:00"/>
        <property name="ArtifactRootDirectory" value="${BuildDirectory}\Artifacts"/>
      </properties>
    </nant>
 
    <fileset id="PacakgeFinder" />
    <property name="PackagePathPattern" value="${PackagesDirectory}\**\SourceControl.Target.xml"/>
    <function execute="${fileset::include-add('PacakgeFinder', PackagePathPattern)}"/>
    <property name="PackagePath" value="${fileset::get-name-at-index('PacakgeFinder', 0)}"/>
    <nant target="SourceControl.Repository.Load">
      <buildfiles>
        <include name="${PackagePath}"/>
      </buildfiles>
    </nant>
 
    <nant buildfile="${BuildDirectory}\SetupIIS.xml" inheritall="false" inheritrefs="false" />
 
    <asyncexec workingdir="${BuildDirectory}" program="${CCNET.BatchFile}" createnowindow="false" redirectoutput="false" useshellexecute="true" waitforexit="false" />
    <asyncexec workingdir="${BuildDirectory}" program="${BuildVS.OpenSolutionBat}" createnowindow="false" redirectoutput="false" useshellexecute="true" waitforexit="false" />
  </target>
 
</project>

First change the project name from TestProject to what ever the name of your project is. You might need to edit the port number used. It is important to understand that each CI Factory created CI Server has its very own CCNET server. This means that a unique port is required. The list of packages to install should be tailored to fit your projects needs. Are you using Source Safe or Subversion?  Please notice the target at the bottom of the file: Post.Install.  This target is the last thing to execute.  Please notice that it is set, out of the box, to load your source conrol repository, start the CCNet server, and open the build script solution.  In figure 2 you can see all the Package folders in the solution explorer.  If you will be using a Pacakge that is not included in the Arguments.xml you can find a Properties.xml in the Package folder that provides the configuration for that Package.  I suggest that you copy all the customized properties for the Packages that you will be using to the Arguments.xml.  If you are not using Subversion delete those properties from the Arguments.xml.  This will leave the Arguments.xml defining how you wish to tailor CI Factory to your needs.

 

cifactorysolutionexplorer.jpg

Figure 2

Installing a New CI Server

First you will have to make sure that the source repository is setup and ready to go. If not you will get a failure. For subversion this would require a SVN repository be set up and accessible. You will also want to make sure that the username supplied has access to the repository.

To execute the install script after you have finished editing the arguments file you can double click the run.bat file.

run.bat.jpg
Figure 3

 

After it has completed look in the directory C:\Projects for a folder with the same name as your project.

testprojectdirectory.jpg
Figure 4

The build script solution should already be open.  You can open it using the OpenSolution.bat file. The bat file sets env vars specifically the nAnt bin directory for this project. This allows you to do some interesting things, see blog post about nAnt VS.NET integration and Scratch. Once open have a look around the solution explorer.

testprojectsolutionexplorer.jpg
Figure 5

Not every file in the Build directory is part of this solution, just the scripts, config files, xsl... You should check the Main.Build.xml file to insure the order of operation is correct(this installer is smart but not that smart yet). The order of operations in the listing below is correct.

 

<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://nant.sf.net/schemas/nant.xsd" name="Main Build" default="Triggered">
 
  <include buildfile="Properties.build.xml" />
  <include buildfile="Common.Build.xml" />
 
  <description>Begin Package Includes</description>
  <include buildfile="${PackagesDirectory}\SourceModificationReport\SourceModificationReport.Target.xml" />
  <include buildfile="${PackagesDirectory}\Subversion\SourceControl.Target.xml" />
  <include buildfile="${PackagesDirectory}\Versioning\Versioning.Target.xml" />
  <include buildfile="${PackagesDirectory}\MSBuild\Compile.Target.xml" />
  <include buildfile="${PackagesDirectory}\NCover\NCover.Target.xml" />
  <include buildfile="${PackagesDirectory}\nDepend\nDepend.Target.xml" />
  <include buildfile="${PackagesDirectory}\Simian\Simian.Target.xml" />
  <include buildfile="${PackagesDirectory}\LinesOfCode\LinesOfCode.Target.xml" />
  <include buildfile="${PackagesDirectory}\Deployment\Deployment.Target.xml" />
  <include buildfile="${PackagesDirectory}\Workspace\Workspace.Targets.xml" />
  <description>End Package Includes</description>
 
  <target name="Triggered" depends="SetUps">
    <trycatch>
      <try>
        <description>Begin Main Build</description>
 
        <description>Begin Pre Build Actions</description>
        <!-- SourceModificationReport.PublishOldSource should be the first call! -->
        <call target="SourceModificationReport.PublishOldSource" />
        <call target="SourceModificationReport.ConsolidateReports" />
        <description>End Pre Build Actions</description>
 
        <description>Begin Clean Up Actions</description>
        <call target="SourceControl.CleanGetOfThirdPartyDirectory" />
        <call target="SourceControl.CleanGetOfProductDirectory" />
        <!-- SourceModificationReport.PublishNewSource should be the last call! -->
        <call target="SourceModificationReport.PublishNewSource" />
        <description>End Clean Up Actions</description>
 
        <description>Begin Compile Actions</description>
        <!-- Make sure that this happens before the call to Compile.CompileSource! -->
        <call target="Versioning.IncrementBuildNumberOfModifiedAssemblies" />
        <call target="Versioning.IncreamentBuildNumberOfProduct" />
        <call target="Compile.CompileSource" />
        <description>End Compile Actions</description>
 
        <description>Begin Varification Actions</description>
        <call target="UnitTest.RunTests" />
        <call target="LinesOfCode.CountCodeLines" />
        <description>End Varification Actions</description>
 
        <description>Begin Post Build Actions</description>
        <call target="nDepend.Calculate" />
        <call target="Simian.Run" />
        <description>End Post Build Actions</description>
 
        <description>End Main Build</description>
      </try>
      <finally>
        <call target="TearDowns" />
      </finally>
    </trycatch>
  </target>
 
  <target name="SetUps">
    <call target="Common.SetUp" />
    <description>Begin SetUps</description>
    <description>End SetUps</description>
    <call target="SourceModificationReport.SetUp" />
    <call target="SourceControl.SetUp" />
    <call target="Versioning.SetUp" />
    <call target="Compile.SetUp" />
    <call target="UnitTest.SetUp" />
    <call target="nDepend.SetUp" />
    <call target="Simian.SetUp" />
    <call target="LinesOfCode.SetUp" />
    <call target="Deployment.SetUp" />
    <call target="Workspace.SetUp" />
  </target>
 
  <target name="TearDowns">
    <description>Begin TearDowns</description>
    <description>End TearDowns</description>
    <call target="SourceModificationReport.TearDown" />
    <call target="SourceControl.TearDown" />
    <call target="Versioning.TearDown" />
    <call target="Compile.TearDown" />
    <call target="UnitTest.TearDown" />
    <call target="nDepend.TearDown" />
    <call target="Simian.TearDown" />
    <call target="LinesOfCode.TearDown" />
    <call target="Deployment.TearDown" />
    <call target="Workspace.TearDown" />
  </target>
</project>

 

There are a few steps left to get the build up and running, get your product into source control and create a .NET project to be built(you may already have one that just needs to be copied into the correct spot).


The build server should already be running. In the future you can start the server by executing the batch file C:\Projects\TestProject\Current\Build\CCNETServer.Bat.

Now from your dev machine get the latest from source control. Go to the C:\Projects\TestProject\Current\Product and execute the batch file OpenSolution.bat. Again you can open the solution file the way you normally do if you wish.

 

You can add to the OpenSolutionFile.bat. If your source control is on a network share that requires authentication you can have the batch file do the authentication for you. If you bind the solution file to source control this can be very helpful. Now you don't have to remember to authenticate before you open the solution.


If you are going to bind the solution to source control then now is the best time while there are no projects in the solution yet. If you have existing projects that you would like to add copy them to either the Unit Test directory or the Production directory. All references other than to the .NET framework should be placed in C:\Projects\TestProject\Current\Third Party. I prefer to place GAC installed third party components in the Third Party directory as well(see Using Junctions to Manage a Development Environment), but that is just a preference.

 

Before adding an existing project remove all source control binding information from the project. That means source control files and information in the project file itself.

Add the existing projects as you normally would, commit to source control, and wait for the build result(the commit just triggered a build). If you are going to add new project make sure that you add it to the Production directory if it is deploy-able code or to Unit Test if it is unit test code. If you look back at the main build file you will see a call to Versioning.IncreamentBuildNumberOfProduct. This will update all projectinfo files. You can have one in every project if you like but I prefer to have one in the Product directory and link to it from all the Production projects.

using System.Reflection;

using System.Runtime.CompilerServices;

using System.Runtime.InteropServices;

 

[assembly: AssemblyProduct("CI Factory")]

[assembly: AssemblyInformationalVersion("1.0.0.5")]

Don't forget to add the link into your project files. I do this by opening a the project file ina text editor and adding the following.

 

<File RelPath = "ProjectInfo.cs" Link = "..\..\ProjectInfo.cs" SubType = "Code" BuildAction = "Compile" />


Every build the version information is updated, the assembly version and the product version are separet versions.

Assembly versions are incremented only when the assembly has changed. The product version is incremented every successful build.

There is a target in the Versioning Package named Versioning.FixUp.  You can call this from the Scratch.Build.xml file to automatically add links in all your projects to the correct ProjectInfo.* file.  As well it will remove any duplicate attribute in the AssemblyInfo.* files to prevent compile errors.

 

After you have added a project to Production and Unit Test and committed to source control a build will occur. You can review the results of the build at the CCNET dashboard. The URL for this page is of the format http://<hostname>/<projectname>-<codelinename>.


 

testprojectbuildreport.jpg

Figure 7

At this point you have a working build that produces a zip with all debug binaries. You may wish to add to it by manipulating the main build, adding packages, or even creating your own.

 

Adding a Package

This section is about adding a package to and existing build server not authoring a new package. Instruction on authoring a new package can be found here. There are two ways to add a package; manually and with a script.  First lest look at the scripted approach.

 

Open the Arguments.xml file and notice the property at the top of the file: Install.Action.  It's default value is Install.Project, change this to Install.Package.  Now adjust the strings list to include the Package(s) that you would like to install and execute the run.bat file.  This will add the Package(s) to the local Project.  It will not add the Package to source control.  Please open the build script solution and review the changes made.  When you are ready add the new Package(s) to source control and commit the additions and modifications.

 

From here on describes how to manually install a package.  A package should be placed in the directory C:\Projects\<projectname>\Current\Build\Packages. A package can integrate into CI Factory in several ways. In most cases it will supply a targets file <packagename>.Target.xml that will need to be included in the main build file. Place a new includes statement in between the description tags for package includes.

 

<description>Begin Package Includes</description>
<include buildfile="${PackagesDirectory}\SourceModificationReport\SourceModificationReport.Target.xml" />
<include buildfile="${PackagesDirectory}\Subversion\SourceControl.Target.xml" />
<include buildfile="${PackagesDirectory}\Versioning\Versioning.Target.xml" />
<include buildfile="${PackagesDirectory}\MSBuild\Compile.Target.xml" />
<include buildfile="${PackagesDirectory}\NCover\NCover.Target.xml" />
<include buildfile="${PackagesDirectory}\nDepend\nDepend.Target.xml" />
<include buildfile="${PackagesDirectory}\Simian\Simian.Target.xml" />
<include buildfile="${PackagesDirectory}\LinesOfCode\LinesOfCode.Target.xml" />
<include buildfile="${PackagesDirectory}\Deployment\Deployment.Target.xml" />
<include buildfile="${PackagesDirectory}\Workspace\Workspace.Targets.xml" />
<description>End Package Includes</description> 

If it needs to be called directly from main add a call to the target in between the description tags for main build. Don't forget to add the calls to the package's setup and teardown as well.

 

<target name="Triggered" depends="SetUps">
  <trycatch>
    <try>
      <description>Begin Main Build</description>
 
      <description>Begin Pre Build Actions</description>
      <!-- SourceModificationReport.PublishOldSource should be the first call! -->
      <call target="SourceModificationReport.PublishOldSource" />
      <call target="SourceModificationReport.ConsolidateReports" />
      <description>End Pre Build Actions</description>
 
      <description>Begin Clean Up Actions</description>
      <call target="SourceControl.CleanGetOfThirdPartyDirectory" />
      <call target="SourceControl.CleanGetOfProductDirectory" />
      <!-- SourceModificationReport.PublishNewSource should be the last call! -->
      <call target="SourceModificationReport.PublishNewSource" />
      <description>End Clean Up Actions</description>
 
      <description>Begin Compile Actions</description>
      <!-- Make sure that this happens before the call to Compile.CompileSource! -->
      <call target="Versioning.IncrementBuildNumberOfModifiedAssemblies" />
      <call target="Versioning.IncreamentBuildNumberOfProduct" />
      <call target="Compile.CompileSource" />
      <description>End Compile Actions</description>
 
      <description>Begin Varification Actions</description>
      <call target="UnitTest.RunTests" />
      <call target="LinesOfCode.CountCodeLines" />
      <description>End Varification Actions</description>
 
      <description>Begin Post Build Actions</description>
      <call target="nDepend.Calculate" />
      <call target="Simian.Run" />
      <description>End Post Build Actions</description>
 
      <description>End Main Build</description>
    </try>
    <finally>
      <call target="TearDowns" />
    </finally>
  </trycatch>
</target>
 
<target name="SetUps">
  <call target="Common.SetUp" />
  <description>Begin SetUps</description>
  <description>End SetUps</description>
  <call target="SourceModificationReport.SetUp" />
  <call target="SourceControl.SetUp" />
  <call target="Versioning.SetUp" />
  <call target="Compile.SetUp" />
  <call target="UnitTest.SetUp" />
  <call target="nDepend.SetUp" />
  <call target="Simian.SetUp" />
  <call target="LinesOfCode.SetUp" />
  <call target="Deployment.SetUp" />
  <call target="Workspace.SetUp" />
</target>
 
<target name="TearDowns">
  <description>Begin TearDowns</description>
  <description>End TearDowns</description>
  <call target="SourceModificationReport.TearDown" />
  <call target="SourceControl.TearDown" />
  <call target="Versioning.TearDown" />
  <call target="Compile.TearDown" />
  <call target="UnitTest.TearDown" />
  <call target="nDepend.TearDown" />
  <call target="Simian.TearDown" />
  <call target="LinesOfCode.TearDown" />
  <call target="Deployment.TearDown" />
  <call target="Workspace.TearDown" />
</target> 

You should review the properties file to insure that the values set are desired. The properties file for packages are found in the same folder as the target file named in the follow format, <packagename>.Properites.xml. The package may produce output that needs to be merged into the CCNET build log. If so edit C:\<projectname>\Current\Build\ccnetproject.xml adding to the merge files section(please review CCNET help files if needed). If content is merged in to the build log or published through other means it may be displayed on the dashboard. Xsl files in the Package directory are visible through an IIS virtual directory. The packages virtual directory is a child of dashboard, dashboard's virtual dir is name is the project name.


testprojectiisvirtualdirs.jpg

Figure 8

 

This is important information when trying to register an new build report plugins. To do this edit C:\Projects\<projectname>\Current\Build\dashboard\dashboard.config(please review CCNET help files if needed).

 

<buildPlugins>
  <buildReportBuildPlugin imageFileName="images/BuildReport.gif">
    <xslFileNames>
      <xslFile>xsl\header.xsl</xslFile>
      <xslFile>xsl\modifications.xsl</xslFile>
      <xslFile>xsl\compile.xsl</xslFile>
      <xslFile>Packages\MSBuild\compile-msbuild.xsl</xslFile>
      <xslFile>Packages\NCover\NCoverDisplaySummary.xsl</xslFile>
      <xslFile>Packages\DotNetUnitTest\MbUnitDisplaySummary.xsl</xslFile>
      <xslFile>Packages\nDepend\nDependSummaryDisplay.xsl</xslFile>
      <xslFile>Packages\Simian\SimianDisplaySummary.xsl</xslFile>
      <xslFile>Packages\LinesOfCode\LinesOfCode.xsl</xslFile>
      <xslFile>Packages\Deployment\deployment.xsl</xslFile>
    </xslFileNames>
  </buildReportBuildPlugin>
  <buildLogBuildPlugin imageFileName="images/Log.gif"/>
  <xslReportBuildPlugin description="NAnt Output" actionName="NAntOutputBuildReport" xslFileName="xsl\Nant.xsl" imageFileName="images/NAntOutput.gif" />
  <xslReportBuildPlugin description="NAnt Timings" actionName="NAntTimingsBuildReport" xslFileName="xsl\NantTiming.xsl" imageFileName="images/NAntTimings.gif"/>
  <xslReportBuildPlugin description="NCover Details" actionName="NCoverDetails" xslFileName="Packages\NCover\NCoverDisplayReport.xsl" imageFileName="Packages\NCover\logo.ico" />
  <xslReportBuildPlugin description="NDepend Report" actionName="NDependReport" xslFileName="Packages\NDepend\nDependReport.xsl" imageFileName="Packages\NDepend\logo.gif" />
  <xslReportBuildPlugin description="Simian Report" actionName="SimianReport" xslFileName="Packages\Simian\SimianDisplayReport.xsl" imageFileName="Packages\Simian\logo.gif" />
</buildPlugins> 

And that is all there is to it.

Uninstall

To uninstall the setup just delete the Project folder and remove the two IIS virtual directories that were setup. That's it! :)