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).

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.
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.

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

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.

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>.
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.
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! :)
|