CRUISE CONTROL.NET
SLNo
Content
Page
Study & Overview
1.
Introduction to Continuous Integration and Cruise Control .Net
2
2.
Installation Process
11
3.
CCNet server configuration(CCNet.config)
12
4.
File Merge task
22
5.
Configure CruiseControl.Net to Automatically Update its Config File
24
6.
CCTray
26 Build Configuration - Nant
7.
Integration on a project built using Nant
29
8.
Nant element in configuration file
31
9.
Nant O/p in XML File
32
10.
Nant and Nunit
32
11.
CCNet build labels in Nant
33
12.
CCNet build from Nant script
35
Build Configuration - MSBuild
13.
Integration on a project built using MSBuild
43
14.
MSBuild element in configuration file
43
Build Configuration - Visual Studio
15.
Integration on a project built using Visual Studio
51
16.
Visual Studio element in configuration file
52
Web Dashboard
17.
Installation
53
18.
Configuring the web dashboard
54
CRUISE CONTROL.NET
19.
Using Web dashboard
67
20.
Developing web dashboard plug-ins
69
Study & Overview Introduction of Continuous Integration Continuous Integration is a software development practice where members of a team integrate their work frequently; usually each person integrates at least daily - leading to multiple integrations per day. Integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly. Feature with Continuous Integration Maintain a Single Source Repository. Software projects involve lots of files that need to be orchestrated together to build a product. Keeping track of all of these is a major effort, particularly when there's multiple people involved. So it's not surprising that over the year’s software development teams have built tools to manage all this. These tools - called Source Code Management tools, configuration management, version control systems, repositories, or various other names - are an integral part of most development projects. So as a simple basis make sure you get a decent source code management system. The current open source repository of choice is Subversion. (The older open-source tool CVS is still widely used, and is much better than nothing, but Subversion is the modern choice.). Once you get a source code management system, make sure it is the well known place for everyone to go get source code. Everything should be in the repository. The basic rule of thumb is that you should be able to walk up to the project with a virgin machine, do a checkout, and be able to fully build the system. You must put everything required for a build in the source control system; however you may also put other stuff that people generally work with in there too. IDE configurations are good to put in there because that way it's easy for people to share the same IDE setups. One of the features of version control systems is that they allow you to create multiple branches, to handle different streams of development. Keep your use of branches to a minimum. In particular have a mainline: a single branch of the project currently under development. Pretty
CRUISE CONTROL.NET
much everyone should work off this mainline most of the time. In general you should store in source control everything you need to build anything, but nothing that you actually build. Automate the Build Getting the sources turned into a running system can often be a complicated process involving compilation, moving files around, loading schemas into the databases, and so on. However like most tasks in this part of software development it can be automated - and as a result should be automated. Automated environments for builds are a common feature of systems. The .NET community has had Nant and now has MSBuild. Make sure you can build and launch your system using these scripts using a single command. A common mistake is not to include everything in the automated build. The build should include getting the database schema out of the repository and firing it up in the execution environment. I'll elaborate my earlier rule of thumb: anyone should be able to bring in a virgin machine, check the sources out of the repository, issue a single command, and have a running system on their machine. A big build often takes time; you don't want to do all of these steps if you've only made a small change. So a good build tool analyzes what needs to be changed as part of the process. The common way to do this is to check the dates of the source and object files and only compile if the source date is later. Dependencies then get tricky: if one object files change those that depend on it may also need to be rebuilt. Compilers may handle this kind of thing, or they may not. Depending on what you need, you may need different kinds of things to be built. You can build a system with or without test code, or with different sets of tests. Some components can be built stand-alone. A build script should allow you to build alternative targets for different cases. Make Your Build Self-Testing Traditionally a build means compiling, linking, and all the additional stuff required to get a program to execute. A program may run, but that doesn't mean it does the right thing. Modern statically typed languages can catch many bugs, but far more slip through that net. A good way to catch bugs more quickly and efficiently is to include automated tests in the build process. Testing isn't perfect, of course, but it can catch a lot of bugs - enough to be useful. For self-testing code you need a suite of automated tests that can check a large part of the code base for bugs. The tests need to be able to be kicked off from a simple command and to be selfchecking. The result of running the test suite should indicate if any tests failed. For a build to be self-testing the failure of a test should cause the build to fail. Everyone Commits Every Day
CRUISE CONTROL.NET
Integration is primarily about communication. Integration allows developers to tell other developers about the changes they have made. Frequent communication allows people to know quickly as changes develop. My general rule of thumb is that every developer should commit to the repository every day. In practice it's often useful if developers commit more frequently than that. The more frequently you commit, the less places you have to look for conflict errors, and the more rapidly you fix conflicts. Frequent commits encourage developers to break down their work into small chunks of a few hours each. This helps track progress and provides a sense of progress. Often people initially feel they can't do something meaningful in just a few hours, but we've found that mentoring and practice helps them learn. Every Commit Should Build the Mainline on an Integration Machine Using daily commits, a team gets frequent tested builds. This ought to mean that the mainline stays in a healthy state. You should ensure that regular builds happen on an integration machine and only if this integration build succeeds should the commit be considered to be done. Since the developer who commits is responsible for this, that developer needs to monitor the mainline build so they can fix it if it breaks. A continuous integration server acts as a monitor to the repository. Every time a commit against the repository finishes the server automatically checks out the sources onto the integration machine, initiates a build, and notifies the commitment of the result of the build. The committer isn't done until she gets the notification - usually an email. At ThoughtWorks, we're big fans of continuous integration servers - indeed we led the original development of Cruise Control and CruiseControl.NET, the widely used open-source CI servers. Since then we've also built the commercial Cruise CI server. We use a CI server on nearly every project we do and have been very happy with the results. Not everyone prefers to use a CI server. I agree with him that CI is much more than just installing some software. All the practices here need to be in play to do Continuous Integration effectively. But equally many teams who do CI well find a CI server to be a helpful tool. Many organizations do regular builds on a timed schedule, such as every night. This is not the same thing as a continuous build and isn't enough for continuous integration. The whole point of continuous integration is to find problems as soon as you can. Nightly builds mean that bugs lie undetected for a whole day before anyone discovers them. Once they are in the system that long, it takes a long time to find and remove them. A key part of doing a continuous build is that if the mainline build fails, it needs to be fixed right away. The whole point of working with CI is that you're always developing on a known stable base. It's not a bad thing for the mainline build to break, although if it's happening all the time it suggests people aren't being careful enough about updating and building locally before a commit.
CRUISE CONTROL.NET
When the mainline build does break, however, it's important that it gets fixed fast. To help avoid breaking the mainline you might consider using a pending head. When teams are introducing CI, often this is one of the hardest things to sort out. Early on a team can struggle to get into the regular habit of working mainline builds, particularly if they are working on an existing code base. Patience and steady application does seem to regularly do the trick, so don't get discouraged. Keep the Build Fast The whole point of Continuous Integration is to provide rapid feedback. Nothing sucks the blood of a CI activity more than a build that takes a long time For most projects, however, the XP guideline of a ten minute build is perfectly within reason. Most of our modern projects achieve this. It's worth putting in concentrated effort to make it happen, because every minute you reduce off the build time is a minute saved for each developer every time they commit. Since CI demands frequent commits, this adds up to a lot of time. If you're staring at a one hour build time, then getting to a faster build may seem like a daunting prospect. It can even be daunting to work on a new project and think about how to keep things fast. For enterprise applications, at least, we've found the usual bottleneck is testing - particularly tests that involve external services such as a database. Probably the most crucial step is to start working on setting up a staged build. The idea behind a staged build (also known as build pipeline) is that there are in fact multiple builds done in sequence. The commit to the mainline triggers the first build - what I call the commit build. The commit build is the build that's needed when someone commits to the mainline. The commit build is the one that has to be done quickly; as a result it will take a number of shortcuts that will reduce the ability to detect bugs. The trick is to balance the needs of bug finding and speed so that a good commit build is stable enough for other people to work on. Once the commit build is good then other people can work on the code with confidence. However there are further, slower, tests that you can start to do. Additional machines can run further testing routines on the build that take longer to do. A simple example of this is a two stage build. The first stage would do the compilation and run tests that are more localized unit tests with the database completely stubbed out. Such tests can run very fast, keeping within the ten minute guideline. However any bugs that involve larger scale interactions, particularly those involving the real database, won't be found. The second stage build runs a different suite of tests that do hit the real database and involve more end-to-end behavior. This suite might take a couple of hours to run. In this scenario people use the first stage as the commit build and use this as their main CI cycle. The second-stage build is a secondary build which runs when it can, picking up the executable from the latest good commit build for further testing. If the secondary build fails, then this doesn't have the same 'stop everything' quality, but the team does aim to fix such bugs as rapidly
CRUISE CONTROL.NET
as possible, while keeping the commit build running. Indeed the secondary build doesn't have to stay good, as long as each known bug is identified and dealt with in a next few days. As in this example, secondary builds are often pure tests since these days it's usually tests that cause the slowness. If the secondary build detects a bug, that's a sign that the commit build could do with another test. As much as possible you want to ensure that any secondary build failure leads to new tests in the commit build that would have caught the bug, so the bug stays fixed in the commit build. This way the commit tests are strengthened whenever something gets past them. There are cases where there's no way to build a fast-running test that exposes the bug, so you may decide to only test for that condition in the secondary build. Most of time, fortunately, you can add suitable tests to the commit build. This example is of a two-stage build, but the basic principle can be extended to any number of later builds. The builds after the commit build can also be done in parallel, so if you have two hours of secondary tests you can improve responsiveness by having two machines that run half the tests each. By using parallel secondary builds like this you can introduce all sorts of further automated testing, including performance testing, into the regular build process. (I've run into a lot of interesting techniques around this as I've visited various ThoughtWorks projects over the last couple of years - I'm hoping to persuade some of the developers to write these up.) Make it Easy for Anyone to Get the Latest Executable One of the most difficult parts of software development is making sure that you build the right software. We've found that it's very hard to specify what you want in advance and be correct; people find it much easier to see something that's not quite right and say how it needs to be changed. Agile development processes explicitly expect and take advantage of this part of human behavior. To help make this work, anyone involved with a software project should be able to get the latest executable and be able to run it: for demonstrations, exploratory testing, or just to see what changed this week. Doing this is pretty straightforward: make sure there's a well known place where people can find the latest executable. It may be useful to put several executables in such a store. For the very latest you should put the latest executable to pass the commit tests - such an executable should be pretty stable providing the commit suite is reasonably strong. If you are following a process with well defined iterations, it's usually wise to also put the end of iteration builds there too. Demonstrations, in particular, need software whose features are familiar, so then it's usually worth sacrificing the very latest for something that the demonstrator knows how to operate. Everyone can see what's happening
CRUISE CONTROL.NET
Continuous Integration is all about communication, so you want to ensure that everyone can easily see the state of the system and the changes that have been made to it. One of the most important things to communicate is the state of the mainline build. If you're using Cruise there's a built in web site that will show you if there's a build in progress and what was the state of the last mainline build. Many teams like to make this even more apparent by hooking up a continuous display to the build system - lights that glow green when the build works, or red if it fails are popular. A particularly common touch is red and green lava lamps not just do these indicate the state of the build, but also how long it's been in that state. Bubbles on a red lamp indicate the build's been broken for too long. Each team makes its own choices on these build sensors. Cruise provides an indication not just of who is building, but what changes they made. Cruise also provides a history of changes, allowing team members to get a good sense of recent activity on the project. I know team leads who like to use this to get a sense of what people have been doing and keep a sense of the changes to the system. Another advantage of using a web site is that those that are not co-located can get a sense of the project's status. In general I prefer to have everyone actively working on a project sitting together, but often there are peripheral people who like to keep an eye on things. It's also useful for groups to aggregate together build information from multiple projects - providing a simple and automated status of different projects. Good information displays are not only those on a computer screens. One of my favorite displays was for a project that was getting into CI. It had a long history of being unable to make stable builds. We put a calendar on the wall that showed a full year with a small square for each day. Every day the QA group would put a green sticker on the day if they had received one stable build that passed the commit tests, otherwise a red square. Over time the calendar revealed the state of the build process showing a steady improvement until green squares were so common that the calendar disappeared - its purpose fulfilled. Automate Deployment To do Continuous Integration you need multiple environments, one to run commit tests, one or more to run secondary tests. Since you are moving executables between these environments multiple times a day, you'll want to do this automatically. So it's important to have scripts that will allow you to deploy the application into any environment easily. A natural consequence of this is that you should also have scripts that allow you to deploy into production with similar ease. You may not be deploying into production every day (although I've run into projects that do), but automatic deployment helps both speed up the process and reduce errors. It's also a cheap option since it just uses the same capabilities that you use to deploy into test environments. If you deploy into production one extra automated capability you should consider is automated rollback. Bad things do happen from time to time, and if smelly brown substances hit rotating
CRUISE CONTROL.NET
metal, it's good to be able to quickly go back to the last known good state. Being able to automatically revert also reduces a lot of the tension of deployment, encouraging people to deploy more frequently and thus get new features out to users quickly. (The Ruby on Rails community developed a tool called Capistrano that is a good example of a tool that does this sort of thing
Continuous Integration with CruiseControl.net
CruiseControl.net is the application which I will be discussing in particular. At its most basic it can be used simply to create automatic builds which can at least prove that the application will compile on a development server and not just on the developer's own desktop. Setting up continuous integration for a project does take some time and effort but the end result is that you can be much lazier: just let the automated process do it all for you. So why would you want to implement continuous integration in the first place? Well, it eliminates many of the concerns regarding integrating code that has been created by individual developers and then has to be integrated into the final application. By building the application on a clean machine any missing files or dependencies will be instantly recognized as these will cause the build to fail. Continuous integration need not stop at just building the software it can also automate unit testing (e.g. Nunit), code coverage (e.g. Ncover) which indicates the amount of code that is actually being tested by unit test, documentation (e.g. Sandcastle) and standards compliance (e.g. FxCop) amongst others. Now you can begin to see the real value of this automation. Developers can feel much more assured that the code they check into source control will build and, provided that it has adequate code coverage, that it doesn't break any other code in the process. I must point out that this process does not test the display of the GUI, it only tests the functionality. As such it cannot replace all manual testing but it does cover a great deal.
CruiseControl.net Definition of Cruise control.Net: It is set of application aimed towards an automated integration with the help of CCNET Server. Cruise Control is a free, Java-based framework, open-source software for a continuous build process. It allows one to perform a continuous integration of any software development process.
CRUISE CONTROL.NET
Cruise Control is, distributed under a BSD-style license. It was originally created by employees of Thought Works to allow for continuous integration on a project they were working on. It was later extracted into a stand-alone application. CruiseControl.NET (CCNet) consists of a suite of applications, but at its core is the CruiseControl.NET Server which is an automated integration server. The Server automates the integration process by monitoring the team's source control repository directly. Every time a developer commits a new set of modifications, the server will automatically launch an integration build to validate the changes. When the build is complete, the server notifies the developer whether the changes that they committed integrated successfully or not. Effectively, integration becomes as easy as checking in code. Using an automated integration server not only makes integration easy, it also guarantees that an integration build will happen. There is no danger of developers forgetting to validate their changes after checking in. The CCNet Server offers several key features: • • • •
Integration with a variety of Source Control systems Integration with other external tools, such as NAnt and Visual Studio Can build multiple projects on one server Remote management and reporting
Automatic Integration is done by monitoring Source control repository. In case, if you have versioning servers like SVN, VSTS. By monitoring (i.e. by looking at the code) Source control server (i.e. SVN, VSTS) your CCNet server will do the automatic integration process .As it contains various applications, it will do various activities like Automatic Unit testing, Auto Documentation, Static Code analysis, Code coverage and Error reports are generated and it will sent them through mail. CCTray & Web dashboard are application inbuilt in Cruise control. The Web Dashboard is an ASP.NET application running on IIS. It provides you with details about all your builds including reports and stats on individual builds. See screen grab below:
CRUISE CONTROL.NET
Here is an example of a unit testing stats page:
CRUISE CONTROL.NET
Here is a build report:
Installation Prerequisites - CruiseControl.NET CruiseControl.NET Server To get CruiseControl.NET server up and running, you need to have the following environments set up and installed: Microsoft.NET Framework Version 2.0 (download) CruiseControl.NET Web Dashboard Microsoft.NET Framework Version 2.0 (download) ASP.NET-enabled web server (typically IIS with ASP.NET configured) Developer desktop running CCTray Microsoft.NET Framework Version 2.0 (download)
CRUISE CONTROL.NET
Basic Installation CruiseControl.NET is distributed in 3 formats: Two Installers, one for CruiseControl.NET proper (the Server and Web Dashboard), and a second for the optional CCTray utility. The Installers are conventional Windows installation programs, which perform some useful early setup work for you, such as copying files to good locations, setting up a Virtual Directory for the Dashboard, etc. For most people starting out, this is the way to go. A binary zip file includes the same files as the installers but gives you more control over what you can do with them. A source zip which allows you to read or make your own changes to the CruiseControl.NET source code. The binary zip file will give you several sub-folders: /server: holds the assemblies for the CruiseControl.NET Server, including both the Server Console Application and the Server Service Application . /webdashboard: contains the ASP.NET Web Dashboard application /cctray: contains the assemblies for the CCTray application /doc: contains HTML documentation for CruiseControl.NET
CruiseControl.Net Server Configuration All the configuration files we’re going to talk about are placed or are to be placed in: C:\%ProgramFiles%\CruiseControl.NET\server. CruiseControl.NET comes with two server executables: ccservice.exe which is the windows service installed by the installation setup and ccnet.exe which is a console application included for testing purposes. It is much easier to debug a console application that a service so I strongly suggest to make your initial tests with ccnet.exe and carefully read the console output to get familiar with CCNet behavior. Each of the two executables comes with a default configuration file (i.e.: ccservice.exe.config and ccnet.exe.config) that you don’t need to change at the moment.
CRUISE CONTROL.NET
Moreover both the server processes (windows service or console application) look for a file named CCNet.config in which you will place all the actual information needed by CCNet to learn what it is supposed to do and how it is supposed to do it. CCNet.config is an xml file with a root element named
and a child element, named <project>, for each set of activities that we want CruiseControl.NET to execute, as shown in the following example: -->
Structure of a ‘Project’ Configuration File Sample Structure: <project name="1 - test Project"> <webURL>http://192.168.15.2:222 <workingDirectory>C:\develop\CCnet\project1WorkingDir
<artifactDirectory>C:\develop\CCnet\project1CCnetArtifacts
<webURL> Tag: It represents the URL at which the current project is available through the web interface. For now just make sure to set it to the IP of the server machine (in which you installed CCNet) and to the port that you chose for the Web Dashboard website when you configured the web site in IIS is the path to the main directory of this project and is meant to contain the checked out version of the project under integration. <workingDirectory> Tag: I use to place all the projects managed with CCNET in folders under a common directory named: C:\develop\CCnet. For this test project I chose: C:\develop\CCnet\project1WorkingDir.
CRUISE CONTROL.NET
It is convenient to choose a directory in which to place all the stuff that will be used by CCNet (script files or executable files that you may want CruiseControl.NET to execute) as well as the workingDirectory in which CCNET will checkout the versioned files and the artifactDirectory in which it will output log files. In the example above I chose the directory: C:\develop\CCnet as the container of all CCNet related stuff. It is the path to the directory where all the build logs for this project will be placed.
Source Control Block Source Control configuration block tells CruiseControl.NET that the project named ‘1 testProject’ is bound to a Subversion repository. This means that the task performed when executing this project depends on the status of that particular Subversion repository. As soon as CruiseControl.NET detects a new revision in the repository it updates its working copy and executes the tasks related to the current project. Here is the sample source control Block
<sourcecontrol type="svn"> <trunkUrl>svn://localhost/trunk <workingDirectory>C:\develop\CCnet\project1WorkingDir <username>ccnet <password> ccnet
<trunkUrl> contains the url of the repository that we want to check for modifications (e.g., svn://svnserver/pathToRepo). As we saw in the post Guide to Versioning a Visual Studio Solution with Subversion, TortoiseSVN and AnkhSVN, Subversion could host several repositories under a common folder, say: C:\develop\TestRepo.
CRUISE CONTROL.NET
But in that article, as well as in the current example, we set up only one repository and run svnserve with the command line: svnserve -d -r “C:\develop\test\repo”. So, specifying the server name (localhost) and the path to the particular repository we’re interested in, turns out to be simply: svn://localhost/trunk (instead of: svn://localhost/SpecificRepositoryFolder/trunk); This is the directory that will contain the working copy checked out by CCNET; sets the timeout for the source control operation. It defaults to 10 minutes and you can set it to a different amount of time in milliseconds (default) or specifying units (”millis”, “seconds”, “minutes”, “hours”); I left it out thus accepting the default. If you want to set it to a different value remember to not choose a too short timeout value because if the timeout is exceeded the build will fail without providing information about the reason. In that case the only way you can retrieve the actual reason of the build failing is by analyzing CCNET log file in the CruiseControl.NET\server folder (if you set log4net to the debug log level) and must be set to a valid svn account that CCNET can use to access Subversion repository.
Trigger Block A trigger block is needed to specify when CruiseControl.NET will start a new integration cycle. We want to check for the repository status continuously so we need an ‘Interval Trigger’ to tell CruiseControl.NET to perform integration periodically after a specified amount of time: Sample Trigger Block CruiseControl.NET, as far as project ‘1 - TestProject’ is concerned, polls the repository every 10 seconds to see if any changes has been committed. The name attribute is used by CruiseControl.NET GUI to identify the trigger that requested the build; The seconds attribute is the amount of time before triggering the next integration cycle. Each time the time interval elapses, CCNET checks for modifications and, by default, runs integration only if changes are detected.
Labeller Block
CRUISE CONTROL.NET
A label is created, at each integration cycle, to identify the specific build occurred. Different labellers can be used to generate the label that CCNet will use to track the builds. Other than the Labeller Blocks that come with the CruiseControl.NET distribution, many people provided plugin Labeller Blocks to target the generation of labels with specific formats. A very good one, IMHO, is SvnRevisionLabeller by David Keaveny (much important to me because I recently contributed to the project). This plugin allows labelling CruiseControl.NET builds with Subversion’s repository revision numbers and I think this is a really useful feature. So this example will use SvnRevisionLabeller as the Labeller Block. For detailed information about this plugin see my post: CruiseControl.NET and Subversion SvnRevisionLabeller. To use the SvnRevisionLabeller plugin in your installation of CruiseControl.NET you need to unzip the downloaded package and copy the assembly: ccnet.SvnRevisionLabeller.plugin.dll in the server folder directory under the CruiseControl.NET install path (e.g.: ‘C:\Program Files\CruiseControl.NET\server’). Next you need to configure the Labeller Block in your project:
<major>7 <minor>11 svn://localhost/trunk SvnRevisionLabeller will produce build labels in the format: major.minor.svnRevision.build where major and minor are the two values you set in the configuration block while svnRevision is the current version in the Subversion’s repository related to this project. The build number is automatically incremented each time a new build is forced if no further modification has been committed to the repository. is the path to the repository used to retrieve the revision number (e.g. svn://svnserver/pathToRepo/trunk). Actually it should be filled with the same path used in the <trunkUrl> field of the Subversion Source Control Block. In our example it is:
CRUISE CONTROL.NET
svn://localhost/trunk Following is a configuration for SvnRevisionLabeller with the complete set of fields: <prefix>Test- <major>7 <minor>11 svn://localhost/trunk <username>ccnet <password>ccnet Such a configuration will produce a label with the following format: Testmajor.minor.svnRevision.build. <username> and <password> are the username and password of a valid Subversion account for the repository specified in the field. You can use in an external script the build label produced, which is stored in an environment variable. It can be useful to flag release version of output dlls. You can access the build number from a script with the syntax: %CCNetLabel% or from a C# application with the following row:
Environment.GetEnvironmentVariable("ccnetlabel"); If you used the SolutionInfo approach in your Visual Studio solution (see my post: SolutionInfo and Partitioned Single Solution) you can use the build label produced by SvnRevisionLabeller to update the AssemblyFileVersion attribute in the SolutionInfo.cs file. In this way you can provide consistent versioning of the released assemblies together with easy trackability of the corresponding source code’s revision. Be careful not to use the <prefix> tag in this case because you need to set AssemblyFileVersion to a string in the format:
CRUISE CONTROL.NET
major.minor.svnRevision.build with all of the 4 fields being numerical values.
Tasks Block The tasks block represents how the build of the project actually takes place. In our example we will use an MsBuild Task to accomplish the main purpose of our project, which is to compile the versioned Visual Studio solution. After that we will use an Executable Task to run our unit tests, if the build succeeds. Let’s see the whole Tasks Block, at first:
CRUISE CONTROL.NET
You should place your File Merge Tasks in the
section of your Project Configuration Block before your Xml Log Publisher.
The files processed by File Merge Task must be in XML format.
Modify the contents of the
element to contain the path of the files that you wish to merge. The file can be specified using an asterisk ("*") wildcard in order to include multiple files that match the specified pattern (i.e. "*-results.xml" will merge all files ending with the suffix "-results.xml"). The asterisk wildcard can only be used in the filename, not in the path. If a relative location is specified, this is relative to the Project Working Directory. Why are the merged results not showing up in the [Project Report Web Application]? If you have set up the configuration for the File Merge Task as described above and you are still not ending up with the appropriate results showing up within the web application, please try the following steps: 1. Click the original log link and check to see if the merged content is included in the xml. If it is missing then got onto step 2. If it is present and is still not showing up in the web page then try emailing the CCNet users list . 2. Have you put the File Merge Tasks in the section of your Project Configuration Block before your Xml Log Publisher? 3. Check the folder that contains the files that should be merged. If they are not there then you need to dig into your build script to find out why they aren't getting created. 4. If the files are there but aren't getting merged, double-check your ccnet.config file. Is the configuration specified correctly as specified above? Remember that case matters in XML tag and attribute names. 5. Check the ccnet.log file. You should see Info-level log messages stating that the files have been merged. 6. Does the file contain valid XML data? The File Merge Task only expects to process XML files. It will attempt to clean up non-XML files and write errors to the ccnet.log file, but it isn't always successful. Comments (Hide Comments) It would be nice to define new tag where file should be merged. MyFile1.xml MyFile2.xml Both file will be merged to <MyTag> And second won't be create new <MyTag>, it will be added inside. In such way it is possible correctly to add new modification or anything else to existent tags. It could be usefull if you can’t directly control output files.
Configure CruiseControl.Net to Automatically Update its Config File Step 1: Get your configuration file under source control
CRUISE CONTROL.NET
At minimum this involves checking the file in. But there are cleaner and less clean ways to do this. Rather than checking the entire CruiseControl.Net folder in, I like to have a config folder underneath the main program folder that only has the config file in it.
This is not the default location for ccnet's config file, so it needs to be told to look in a different place as well. If you are using CC.Net as a service, then the "ccnet.config" key can be added to the section in ccservice.exe.config to point to the new configuration file, as shown in the next code block. If you are running CC.Net in a console, using ccnet.exe.config, then you can pass the new path as a command-line parameter in the form "-config:config\ccnet.config". The path can be relative to the exe or an absolute path. More information about moving the configuration file is available on the Server Application Config File page. ... ... ... Step 2: Add a CruiseControl.Net project to update the config file At this point, someone could manually update the working copy on the cruise box when changes to the config are committed. But, we can have ccnet itself automatically perform this step by adding a project to ccnet. This project will check for changes to the configuration file in the
CRUISE CONTROL.NET
source control repository and update it on disc. We only need a trigger block and a source control block. For the example worked above, this project would look like: <project name="cc-config"> <sourcecontrol type="svn"> <trunkUrl>file:///c:/Repo/sandbox/config <workingDirectory>C:\Program Files\CruiseControl.NET\server\config Now, when someone commits changes, the next time the cc-config project runs it will pull the changes on to the local disc. CruiseControl.Net will notice the changes and reload the configuration file. If you have the console visible you should see lines similar to the following:
CCTray CCTray is a little application that helps you monitor your build. Simply access you Web Dashboard, and it the left menu, there is an option to download CCTray.
CRUISE CONTROL.NET
Then you need to add the projects you want to monitor. You do that first by entering the name of the server and then selecting the projects you want. I’m usually using the “Connect directly using .NET remoting.
Cruisecontrol Tray
CRUISE CONTROL.NET
CruiseControl.net comes with a client side application which is shown in the sys tray and can be viewed via a double click on the icon:
Here is the application:
OK, in this window you will see four separate builds. The bottom three builds have been created for just one application. I will discuss these three as they are the most interesting. SSE Main Build this simply builds the application in its entirety. It runs every 30 seconds looking for any new code that has been checked into source control. SSE-NightlyBuild creates a version of the application that is the latest build which can be run on the server itself. It also performs all unit tests. This runs at 1am every day. SSE-Documentation simply creates all the documentation from the comments.xml files created when each assembly is built. This relies on the developer adequately commenting their code using Xml comments and predefined tags preceding any method or property. You can choose to view as many builds as you wish and they do not have to be on the same CruiseControl.net server. To do this select Settings by right clicking on the CCTray icon:
CRUISE CONTROL.NET
Now you can add a CruiseControl.net server and any builds it has that you wish to monitor. If any or all of the builds are currently building, the icon changes colour to orange. When a build is complete the icon is either green for successful or red when there has been an error. The same colour keys are used in the Cctray window itself.
Build Configuration - Nant
NAnt NAnt (& Ant) is an automated build tool that enables you to perform all kinds of different build-related tasks. It should not replace but rather enhance the IDE (VS.NET). NAnt is a free .NET build tool based on Ant (a build tool for Java). NAnt, like Ant, is similar to make in that it is used to generate output from your source files. But where Ant is Java-centric, NAnt is .NET-centric. NAnt has built-in support for compiling C#, VB.NET, and J# files and can use Visual Studio .NET solution files to do builds. NAnt also has built-in support for NUnit and NDoc (.NET version of JUnit and JDoc, respectively). NAnt is a useful tool for automating the build process. The build process can include tasks such as compiling source code and resource files into assemblies, running unit tests, configuring build-specific settings, and so on. The benefit of tools like NAnt is that they help automate the build process by providing enough power and flexibility to highly customize build actions for specific applications. 1. Fast and easy to run (simply type nant on the command line) 2. The concept of build files that specify the build procedure. These files are XML files which potentially gives you platform-independence. 3. Includes a lot of predefined tasks (NAnt and NAntContrib distributions) 4. Extensible: if something is missing you can simply write your own tasks. NAnt defines a recipe or procedure for composing the program. What is this thing you call Build Tool? A “build tool” is a tool that you use to build your source code and resources files into assemblies. We use build tools everyday in development. Here are some tasks that are performed during the “entire” build process:
CRUISE CONTROL.NET •
Get latest source code from source code control (SVN/VSS/CVS).
•
Configure the build (put files in specific folders based on build number).
•
Compile the code
•
Run Unit Tests
•
Create Documentation from the source code comments
•
Include non-code output files in the output of the build (images, database files, config files, etc...)
•
Package the output for deployment
NAnt is different. Instead of a model where it is extended with shell-based commands, NAnt is extended using task classes. Instead of writing shell commands, the configuration files are XML-based, calling out a target tree where various tasks get executed. Each task is run by an object that implements a particular Task interface. The system requirements are pretty obvious and simple. To use Nant you need one of the following CLR’s: •
Microsoft .NET Framework 1.0
•
Microsoft .NET Framework 1.1
•
Microsoft .NET Framework 2.0
•
Mono 1.x
We will instruct CruiseControl.NET to run a Nant task by adding a CruiseControl.NET Nant Task Block. Such block lets us instruct CruiseControl.NET to execute Nant and lets us specify a Nant build file and the list of Nant targets to execute. Remember that we named the build file: nant. Build and we placed it in the directory: C:\develop\CCnet. Now we provide this information to the CruiseControl.NET Nant Task Block as shown in the following example: Example:
CRUISE CONTROL.NET <executable>c:\fromcvs\myrepo\myproject\tools\nant\nant.exe c:\fromcvs\myrepo\myproject -D:cvs.executable=c:\putty\cvswithplinkrsh.bat <nologo>false cruise.build My.Other.XmlLogger run 1200
Configuration Elements: Node
Description
Type
Required Default
executable
The path of the version of nant.exe string you want to run. If this is relative, then must be relative to either (a) the base directory, (b) the CCNet Server application, or (c) if the path doesn't contain any directory details then can be available in the system or application's 'path' environment variable
false
nant.exe
baseDirectory
The directory to run the NAnt string process in. If relative, is a subdirectory of the Project Working Directory
false
Project Working Directory
buildFile
The name of the build files to run, relative to the baseDirectory.
string
false
no build file specified (NAnt will use the default build file in the working directory)
buildArgs
Any arguments to pass through to NAnt (e.g. to specify build properties)
string
false
no args specified
nologo
Whether to use the -nologo argument when calling NAnt
Boolean
false
true
logger
The NAnt logger to use. If you are using a version of NAnt prior to 0.8.3, you may need to specify this
string
false
NAnt.Core.XmlLogger
CRUISE CONTROL.NET
as SourceForge.NAnt.XmlLogger. buildTimeoutSeconds Number of seconds to wait before assuming that the process has hung and should be killed. targetList
int
A list of targets to be called. string list CruiseControl.NET does not call NAnt once for each target; it uses the NAnt feature of being able to specify multiple targets.
description
If filled in, this will be shown in the string build stage as the process name
false
600 (10 minutes)
false
no targets specified (NAnt will use the build's default target
false
n/a
NAnt output in Xml CruiseControl.NET expects NAnt to generate its output as Xml so that the build results can be parsed and rendered appropriately. To accomplish this, CruiseControl.NET will, by default, launch NAnt using the "logger: NAnt.Core.XmlLogger" argument. If you want to override this behavior, specify the logger property in the NAntBuilder configuration in the CCNet.config file. If this element is specified but is empty then NAnt will be started with the default logger (though this may cause some problems for CCNet). It is also possible to instruct NAnt to log its output to an Xml file and then merge the file into the build using the File Merge Task. NOTE: the configuration of which NAnt logger to use was originally specified in the ccnet.exe.config file. This has now been deprecated, and the "NAnt. Logger" element in the section can now be removed.
NUnit and NAnt CruiseControl.NET uses xml to process the build log and produce html for display on the web page. Since xml is so easy to parse the nunit2 task in NAnt can produce xml output. The tasks must be configured to do that in order for test results to show up on the web page. Typically this is done by adding a formatter element to the nunit2 task and setting the type to be "Xml". Additionally the usefile flag of the formatter element must be set to "false". If it isn't the nunit2 task will try and save the output to a file and not write it out to the build log.
CRUISE CONTROL.NET It would be pretty tedious for developers to read the xml output when they run the build locally. Define a property for the build output type and set it to "Plain" and use the property in the formatter element...
<property name="outputType" value="Plain"/> ... ... Then in the CCNet.config file pass in a different value for outputType. ... "-DoutputType=Xml" ...
Accessing CruiseControl.NET build labels in NAnt CCNet will pass the current build label to NAnt via the NAnt property CCNetLabel. This means that you can access use this property to, for example, archive the newly built assemblies in a folder with the same name as the build label (this is what we do on CCNetLive). Here's some example NAnt script demonstrating how to do this: <property name="publish.dir" value="D:\download-area\CCNet-Builds\${CCNetLabel}" />
<mkdir dir="${publish.dir}" />
CRUISE CONTROL.NET
Integration Properties The following parameters are passed to NAnt as commandline arguments: Label
Description
Example
CCNetBuildCondition
The condition used to trigger the build, indicating if the build was triggered by new modifications or if it was forced. Legal values are: "IfModificationExis ts" or "Force Build"
Force Build
CCNet IntegrationStatus
The status of the current integration. Could be Success, Failure, Exception or Unknown
Success
CCNetLabel
The label used to identify the CCNet build. This label is generated by the CCNet labeler.
1.0.2.120
CCNetLastIntegration Status
The status of the previous integration. Could be Success, Failure, Exception or Unknown
Success
CCNetProject
The name of the CCNet project that is being integrated.
MyProject
CCNetBuildDate
The date of the build (in yyyyMM dd format)
20050810
CRUISE CONTROL.NET
CCNetBuildTime
The time of the start of the build (in HH:mm:ss format)
08:45:12
CCNetArtifactDirector y
c:\program The project files\CruiseControl.NET\Server\MyProject\Artifa artifact directory cts (as an absolute path)
CCNet WorkingDirectory
c:\program The project files\CruiseControl.NET\Server\MyProject\Workin working directory gDirectory (as an absolute path)
CCNetRequestSource The source of the integration request; this will generally be the name of the trigger that raised the request. (Added in CCNet 1.1)
Interval Trigger
CCNetFailureUsers
The list of users who have contributed modifications to a sequence of builds that has failed.
John, Smith
CCNetListenerFile
Viewing build progress with Nant and MSBuild (Added in CCNet 1.4)
c:\Project\Artifact\listener.xml
CCNetProjectUrl
The URL where the project is located
http://myhost/ccnet/server/
CCNetNumericLabel Contains the label as an integer if conversion is
1
CRUISE CONTROL.NET
possible, otherwise zero. CCNetModifyingUsers The list of users who have contributed to the current build only
Smith
CCNet build from Nant script Sometimes (e.g.: if you want to build a list of projects in sequence) it can be convenient to trigger builds from a NAnt script. For that purpose one can use the launchccnetbuild NAnt task (source available here: LaunchCruiseControlBuildTask.cs).
using using using using using using
System; System.Runtime.Remoting; System.Threading; NAnt.Core; NAnt.Core.Attributes; ThoughtWorks.CruiseControl.Remote;
namespace LoGeek.BuildServer.CustomTasks { /// <summary> /// A NAnt task to launch a build on a CCNet server. /// [TaskName("launchccnetbuild")] public class LaunchCruiseControlBuildTask : Task { #region Private Instance Fields private private private private private
string _serverUrl; string _projectName; int _timeOutInSeconds = 30*60; int _pollingIntervalInSeconds = 5; ICruiseManager _cruiseManager;
#endregion Private Instance Fields #region Public Instance Properties [TaskAttribute("serverurl", Required=true)] public string ServerUrl { get { return _serverUrl; }
CRUISE CONTROL.NET set { _serverUrl = value; } } [TaskAttribute("projectname", Required=true)] public string ProjectName { get { return _projectName; } set { _projectName = value; } } /// <summary> /// Time out in seconds. Default to 1800 seconds (30 minutes) /// [TaskAttribute("timeoutinseconds", Required=false)] public int TimeOut { get { return _timeOutInSeconds; } set { _timeOutInSeconds = value; } } /// <summary> /// Polling interval in seconds. Default to 5 seconds. /// [TaskAttribute("pollinginterval", Required=false)] public int PollingInterval { get { return _pollingIntervalInSeconds; } set { _pollingIntervalInSeconds = value; } } #endregion Public Instance Properties #region implementation of Task protected override void ExecuteTask() { Log(Level.Info, "Connecting to CCNet server " + ServerUrl);
_cruiseManager = (ICruiseManager) RemotingServices.Connect(typeof (ICruiseManager), ServerUrl); IntegrationStatus status = LaunchBuild(_cruiseManager, ProjectName, PollingInterval, TimeOut); if (status != IntegrationStatus.Success) throw new BuildException(string.Format("Project '{0}' failed : {1}", ProjectName, status)); } #endregion /// <summary> /// Return the current status of the project. Return null if the project does not exist. /// private ProjectStatus GetCurrentProjectStatus(ICruiseManager cruiseManager, string name)
CRUISE CONTROL.NET { ProjectStatus[] allStatus = cruiseManager.GetProjectStatus(); foreach (ProjectStatus status in allStatus) { if (status.Name == name) return status; } return null; } public IntegrationStatus LaunchBuild(ICruiseManager cruiseManager, string projectName, int pollingIntervalInSeconds, int timeOutInSeconds) { ProjectStatus status = GetCurrentProjectStatus(cruiseManager, projectName); if (status == null) throw new BuildException(string.Format("Project '{0}' not found on the build server.", projectName)); if (status.Activity != ProjectActivity.Sleeping) throw new BuildException(string.Format("Project '{0}' activity is '{1}' instead of expected '{2}'", projectName, status.Activity, ProjectActivity.Sleeping)); Log(Level.Info, "Forcing build for project '{0}'", projectName);
timeOutInSeconds);
cruiseManager.ForceBuild(projectName); DateTime startTime = DateTime.Now; TimeSpan timeout = new TimeSpan(0, 0,
while (true) { TimeSpan elapsed = DateTime.Now - startTime; if (elapsed >= timeout) throw new BuildException(string.Format("Project '{0}' build timed-out (lasted more than {1} seconds)", projectName, timeOutInSeconds)); Thread.Sleep(pollingIntervalInSeconds*1000); // check current integration status to decide what to do status = GetCurrentProjectStatus(cruiseManager, projectName); switch (status.Activity) { case ProjectActivity.Building: // fine, keep it rolling break; case ProjectActivity.CheckingModifications: // fine break; case ProjectActivity.Sleeping:
CRUISE CONTROL.NET // the build is finished (may be successful or have failed)
return status.BuildStatus; default: throw new Exception(string.Format("Unknown ProjectActivity '{0}'",status.Activity)); } } } } }
Example: The task works synchronously: it polls the server periodically to check a given project status. A build exception is raised if the build times out or is not successful (although this behavior could easily be altered). To build a list of projects sequentially and stop the script whenever one project fails to build, you can use something like : <property name="serverurl" value="tcp://buildserver:21234/CruiseManager.rem" />
Configuration Elements: Attribute serverurl projectname
Description
Type Required Default
The url of the remote CruiseControl.Net server hosting the string project. The name of the project to build.
timeoutinseconds After that amount of time, a build exception will be raised. pollinginterval
How many seconds between each project status check.
true
N/A
string
true
N/A
int
false
1800
int
false
5
NUnit Task The second Task Block that you find in the xml fragment above is an Executable Task used to instruct CruiseControl.NET to run unit tests with NUnit.
CRUISE CONTROL.NET
At first I tried to use a NUnit Task Block but I soon realized that it was not good for me because it was not possible to provide arguments to the task that should be used as arguments of the NUnit command-line executable. This is a problem because there’s no way to let the NUnit task be aware of NUnit categories. For those who don’t know, NUnit lets you specify a ‘Category‘attribute in test methods, with the following syntax: 1. 2. 3. 4. 5.
[Test] [Category("Long Running")] public void VeryLongTest() { /* ... */ }
This attribute allows you to instruct NUnit to treat all the methods belonging to the same category in the same way. Usually what we want to do is to exclude a cluster of tests from running. Typically we exclude tests that take too much to run, using the following syntax with the NUnit command-line tool: nunit-console.exe /exclude:LongRunning,AnotherCategoryName You can configure excluded categories in NUnit GUI as well, by clicking the ‘Categories‘ tab in the top left corner. A list of available categories will be shown. Just select the categories of interest and click the Add button. Then check the Exclude these categories checkbox at the bottom of the page and run the NUnit project. It is very useful to be able to exclude some categories of tests from the continuous integration environment, still being able to run them on developer machines. This is the reason why I recently submitted a patch to CruiseControl.Net adding support for NUnit categories. It’s not included in the official release yet, because I submitted it too late for this purpose. However you can find it in the current build which is publicly available at: CCNetLive. The patch is included starting from build: 3591. So now you have two chances to use categories: 1. If you really want to use the last officially released version, read the paragraph 11.2 about how to use an Executable Task (the method described can be useful also if you want to use any other unsupported Nunit command line argument); 2. Instead if you can download the latest build from ccnetlive you will be able to specify categories inside the Nunit Task block, as explained in paragraph 11.1
CRUISE CONTROL.NET Nunit Task
If you downloaded the most recent build and followed the installation instructions (see: 3. Installation) you can go on reading this paragraph. If you installed the official release or a build older than 1.4.0.3591, you can still modify your installation with the following instructions: download the zipped package (here) or source code. Unzip it in a temporary directory and locate the assembly: ThoughtWorks.CruiseControl.Core.dll (which, for the zip package, is in the directory: ’server’). Copy and replace it to the original one in your CCNET installation directory (back up the original one first) that should be: Program Files\CruiseControl.NET\server. That’s it! Now you can use the CruiseControl.NET’s Nunit Task Block also for specifying Nunit categories (see: Nunit categories for reference). It is possible to specify a list of the categories of tests that we want to be excluded. It is possible, as well, to specify a list of the only categories that we want to be included as allowed by the Nunit Command-line or GUI interface. The configuration syntax for the Nunit task becomes: view plaincopy to clipboardprint? 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
<path>C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe Dummy.sln.nunit <excludedCategories> <excludedCategory>LongRunning <excludedCategory>Category 2
for excluded categories, or: view plaincopy to clipboardprint? 1. 2. 3. <path>C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe 4. 5. 6. Dummy.sln.nunit 7. 8.
CRUISE CONTROL.NET 9. LongRunning 10. Category 2 11. 12.
for included categories. You can find the official reference at this page on the official website. The Nunit task output log file is automatically integrated in the CCNET build results. So you don’t need to specify the Merge task (needed if you use the procedure explaine in paragraph 11.2 instead of this one) in the Publishers block as explained in paragraph 12: view plaincopy to clipboardprint? 1. 2. <merge> 3. 4. ..\project1CCnetArtifacts\nunit-results.xml 5. 6.
Instead you still need to delete the previous Nunit log file before each build process as explained in the paragraph 13 - PreBuild Block. → top of post → top of paragraph
11.2. Executable Task
If you’re working with the official release of CruiseControl.Net (release 1.4) Nunit Task Block syntax only allows you to specify the target solution and little more. In our example it would be: view plaincopy to clipboardprint? 1. 2. 3. 4. 5. 6. 7. 8.
<path>C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe Dummy.sln.nunit
where Dummy.sln.nunit is the Nunit project file for our solution. The solution I strongly suggest is to replace the Nunit Task with an Executable Task like the one shown below: view plaincopy to clipboardprint?
CRUISE CONTROL.NET 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
<exec> <executable> C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe /xml:..\project1CCnetArtifacts\nunit-results.xml /nologo Dummy.sln.nunit /exclude:LongRunning,AnotherCategoryName
You only need to specify the full path to the Nunit command-line executable file in the <executable> field and the command-line arguments in the field. In the field you specify arguments as if provided directly to nunit-console.exe: 1. specify the path to the file in which nunit will write its output: /xml:..\project1CCnetArtifacts\nunit-results.xml. The file should be produced in the artifactDirectory of the current CCNET project. By default the executable run by an executable task is run in the Project Working Directory, so the path to the output file is relative to such directory. 2. You can pass many things as Nunit targets (assemblies, Visual Studio projects or Nunit project files). I suggest creating an Nunit project and passing it as argument to nunit-console.exe as shown in the sample above (where the nunit project file is called: Dummy.sln.nunit). 3. you can then add: /exclude:LongRunning,AnotherCategoryName thus excluding unwanted tests.
Specifying the name of the output file is not enough. In order to make the output written by nunit in the file nunit-results.xml (arbitrary name specified in the buildArgs tag), available to CruiseControl.NET we need to use a File Merge Task. If we used Nunit task the output file would have been automatically merged with other output for CruiseControl.NET. Using the Executable Task we need to explicitly configure CruiseControl.NET to merge the Nunit output file in the log file parsed by CruiseControl.NET. We will tell CruiseControl.NET to do it at the end of the build process, namely in the Publishers section.
Build Configuration - MSBuild
MsBuild Task The <msbuild> task is used to execute MsBuild projects, which are the default project format for Visual Studio 2005 projects and can also be compiled by using the MSBuild application that ships with the .NET 2 Framework.
CRUISE CONTROL.NET In order to work with the results of MsBuild it is important to use a custom xml logger to format the build results.
Let’s have a look at the meaning of the xml nodes children of the <msbuild> node: <executable>: contains the path to the msbuild executable file. You don’t really need to set it because the default value is the standard installation path: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe. <workingDirectory>: is the directory in which MsBuild will be run, so it must be the directory containing our projects checked out working copy. You can provide a path relative to the current project’s workingDirectory. Actually, the path to the CCNET checked out working copy is the same as the <workingDirectory> field of the Source Control Block. <projectFile>: is the name of the project to build. MsBuild accepts a Visual Studio solution file as the project file to build. Obviously the MsBuild Task accepts it as well. This row provides additional command line arguments to MsBuild. We tell it not to log events to the console (/noconsolelogger), to build the Debug configuration (/p:Configuration=Debug) and to provide a reduced output (/v:quiet). As far as the /p:ReferencePath buildArg is concerned it is worth to talk extensively about a problem that could arise with Nunit, so have a look at paragraph 10.1. 1.1 MSBuild and ReferencePath - CruiseControl.NET not resolving reference to Nunit
It could happen that CCNET is not able to locate Nunit (or some other dependency assembly) depending on how your project file has been created by Visual Studio. Open your project file (DummyProject.csproj) with a text editor (e.g.: Notepad++). If you find an entry as follows in it: view plaincopy to clipboardprint? 1. 2. 3. 6. .... 7.
with no associated to the Nunit it could be that CCNET will not be able to resolve that reference if you don’t register nunit.framework.dll in the server’s GAC.
CRUISE CONTROL.NET
You can make sure that CCNET is able to resolve the dependency by providing an alternative search path in which to look for. Each assembly referenced in the Visual Studio project files needs to be located by MSBUild at compile time. The location of the referenced assemblies is resolved by MSBuild by looking in several locations in a particular search order (as explained here). We could modify the .csproj file by providing a value as a child node of the node, e.g.: view plaincopy to clipboardprint? 1. 2. 4. <SpecificVersion>False 5. ..\..\CommonReferencedDLLs\DummyLibrary.dll 6. 7.
This approach has two drawbacks: 1. the hintpath is a relative path, thus making the build success depend on the location of the project relative to the referenced assembly (this could be a problem if we reference an external assembly); 2. we need to modify each Visual Studio project file by hand and we don’t want to do it!
Fortunately there’s an easy way out: We can override all the project specific settings for path resolving by passing a ReferencePath property from the MSBuild command line. Such property accepts as value a list of paths (MSBuild DummySolution.sln /p:”ReferencePath=<Path1;Path2;Path3>”) and it is checked by the build process before checking other locations (HintPath for example). So the way to provide an alternative search path from the command line is to pass as argument a ReferencePath property. This is the reason why the command line provided in the field contains the ReferencePath property pointing to the Nunit install path: /p:ReferencePath=”C:\Program Files\NUnit 2.4.7\bin”.
Let’s go on with the analysis of the xml nodes children of the <msbuild> node: specifies which targets to build in this msbuild project file. It represents the MSBuild /target command line argument. We set it to Rebuild (clean and build).
CRUISE CONTROL.NET
is the number of seconds before assuming that the process has hung. If timeout is exceeded the process will be killed. specifies the path to the assembly containing the logger to use to format the log output of MSBuild . If you don’t want to use the alternative logger that I used in the configuration shown above, you can rely on the default logger as explained here and skip the following To use the default logger: • • •
leave out the field, download the assembly containing the default xml logger here (find info here), copy the downloaded assembly (ThoughtWorks.CruiseControl.MSBuild.dll) to the folder: C:\%ProgramFiles%\CruiseControl.NET\server.
I suggest using the alternative logger (by Christian Rodemeyer) as explained in the following paragraph. The RodeMeyer’s logger provides lighter msbuild output and his modified stylesheets provide much more readable display of such information. 1.2. An Alternative MSBuild Logger - Christian Rodemeyer’s MsBuildToCCNet
I chose to use a logger alternative to the default one: Christian Rodemeyer’s MsBuildToCCNet. You can find it at: Improved MSBuild Integration. From there either you can download separately the assembly and all related stuff needed to correctly display the results from Rodemeyer’s logger or you can download a zip file with the whole project and source code. In the page cited above you can find detailed instructions on how the logger works and how it should be configured. In the current paragraph I’ll illustrate the installation process and add some useful tips for making it work. I suggest downloading the full project that comes in a zip file named: MsBuildToCCNet.zip (download here). Unzipping the package you will have a directory named: MsBuildToCCNet. Inside this directory you will find, among the rest, a directory named Release, containing the assembly: Rodemeyer.MsBuildToCCnet.dll. Just copy the assembly to the \CruiseControl.NET\server folder (e.g.: c:\Program Files\CruiseControl.NET\server\). There’s another subdirectory of the MsBuildToCCNet folder, named ccnet where you can find the resources needed to correctly display the logs produced by Rodemeyer’s logger. Those resources are: cruisecontrol.css and msbuild2ccnet.xsl. You need to use those two files and to configure the Webdashboard:
CRUISE CONTROL.NET 1. Move into your CruiseControl.NET Webdashboard folder, under the path: C:\%ProgramFiles%\CruiseControl.NET\webdashboard (e.g.: c:\Program Files\CruiseControl.NET\webdashboard\) and back up the file: cruisecontrol.css. Then replace it with the cruisecontrol.css file you found in the Rodemeyer’s MsBuildToCCNet folder (e.g.: copy MsBuildToCCNet\ccnet\cruisecontrol.css to c:\Program Files\CruiseControl.NET\webdashboard\cruisecontrol.css); 2. There’s a subdirectory of the CruiseControl.NET Webdashboard folder, named: xsl. You need to copy the other resource (msbuild2ccnet.xsl) you found in the MsBuildToCCNet\ccnet folder in that directory: C:\%ProgramFiles%\CruiseControl.NET\webdashboard\xsl\; 3. You need to modify the dashboard. Config file in the CruiseControl.NET Webdashboard folder in order to correctly show the output of the logger. Being that we’re talking about the Webdashboard configuration I will show you all the changes you will need to do to let it work with the following three components (even if we’ll see two of them only in the following paragraphs): o MsBuildToCCNet o Nunit integration o FxCop integration
First of all choose a 32 x 32 jpg image representing a smiling icon and place it in the CruiseControl.NET Webdashboard folder: C:\%ProgramFiles%\CruiseControl.NET\webdashboard. Rename the image file: your_happy_image.jpg and, when a new build succeeds, you’ll obtain a smiling icon in the Webdashboard report! (you can find a sample image here). Then open CruiseControl.NET\webdashboard\xsl\msbuild2ccnet.xsl and go to line 24: view plaincopy to clipboardprint? 1. 2.<xsl :if test="@error_count = 0 and @warning_count = 0"> 3. 4.
includes/images/smilies/icon_smile.gif"> " /> Juchuu !!! | 6.
7.
replace the img src attribute: /ccnet/your_happy_image.jpg with /your_happy_image.jpg if you configured iis with a new website for the webdashboard instead of a virtual directory. If you’re usign the default virtual directory named ccnet, don’t modify that row. Next you need to locate the field: in C:\%ProgramFiles%\CruiseControl.NET\webdashboard\dashboard.config and arrange or delete its children nodes in order to obtain the following configuration (remember to back up the file first): view plaincopy to clipboardprint?
CRUISE CONTROL.NET 8. 9. 10. 11. <xslfilenames> 12. <xslfile>xsl\header.xsl 13. <xslfile>xsl\modifications.xsl 14. <xslfile>xsl\msbuild2ccnet.xsl 15. <xslfile>xsl\unittests.xsl 16. <xslfile>xsl\compile.xsl 17. <xslfile>xsl\fxcop-summary.xsl 18. 19. 20. 21. <xslreportbuildplugin description="NUnit Details" 22. actionName="NUnitDetailsBuildReport" 23. xslFileName="xsl\tests.xsl" /> 24. <xslreportbuildplugin description="NUnit Timings" 25. actionName="NUnitTimingsBuildReport" 26. xslFileName="xsl\timing.xsl" /> 27. <xslreportbuildplugin description="FxCop Report" 28. actionName="FxCopBuildReport" 29. xslFileName="xsl\FxCopReport.xsl" /> 30.
As you can see, such configuration includes also stylesheet files for nunit and fxcop integration. We will soon configure the server to integrate those components. While adding the smiling image in the previous paragraph we had to change the path in the xsl file. The same problem could arise with other stylesheet files if you configured the webdashboard to be a website instead that a virtual directory named ccnet. Have a look at the next paragraph for details: 1.3. CruiseControl.NET Webdashboard Fails in Finding Images if Not Installed in Virtual Directory
If you unchecked ‘Create virtual directory in IIS for Web dashboard’ as shown in part 1 of this tutorial at 3.1. Install CruiseControl.NET and installed the Webdashboard as a new website as shown in the paragraph: 3.2. Create a CCNet Website in IIS, the webdashboard could have problems in resolving image paths. You will realize it as soon as you will configure the server to integrate nunit or fxcop (will see it in following paragraphs). To make sure not to have this problems you must modify the following files: xsl\tests.xsl xsl\fxcop-summary.xsl under: C:\%ProgramFiles%\CruiseControl.NET\webdashboard\
CRUISE CONTROL.NET
you have to replace all the paths relative to the root of the website with relative paths, e.g: in the file: xsl\tests.xsl you should replace all entries like: view plaincopy to clipboardprint? 1. 2. eImg.src = "<xsl :value-of select="$applicationPath"/>/images/arrow_minus_small.gif";
with: view plaincopy to clipboardprint? 1. 2. eImg.src = "<xsl :value-of select="$applicationPath"/>images/arrow_minus_small.gif";
and entries like: view plaincopy to clipboardprint? 1. 2.
with: view plaincopy to clipboardprint? 1. 2.
that is, you simply need to delete the leading ‘forward slash’ at the beginning of the path (just before the ‘images’ folder name). you need to accomplish the same task with the file xsl\fxcop-summary.xsl, e.g.: you should replace entries like: view plaincopy to clipboardprint? 1. 2. <xsl :attribute name="src"><xsl :value-of select="$applicationPath" />/images/fxcop-criticalerror.gif
with: view plaincopy to clipboardprint?
CRUISE CONTROL.NET 1. 2. <xsl :attribute name="src"><xsl :value-of select="$applicationPath" />images/fxcop-criticalerror.gif
Actually, you should find all paths to images in those two files and delete the leading forward slash. Back to the MSBuildToCCNET alternative Logger for MsBuild, I will explain now why I decided to recompile the source code instead of using the assembly provided: MsBuildToCCNet\Release\Rodemeyer.MsBuildToCCnet.dll 1.4. MSBuildToCCNET Reports Wrong Number of Compiled Projects
I found that MsBuildToCCNet reported the wrong number of projects in the webdashboard in the page reporting the details of the last build. There’s a row that sounds like the following, displaied in that page: ‘15 Projects built with 2 warnings’ Looking at the source code (in the file: Logger.cs) I realized that the list of Project type instances includes the solution file (DummySolution.sln) and a Project object named “MSBuild“, somehow representing the MsBuild process. Appearently this is the reason why the reported number of projects is wrong. I still haven’t tried to contact the author so I don’t know very well how the Logger is supposed to work as far as this count is concerned. As a workaround I modified the following row: 1. 2. w.WriteAttributeString("project_count", 3. XmlConvert.ToString(projects.Count));
turning it into: 1. 2. w.WriteAttributeString("project_count", 3. XmlConvert.ToString(projects.Count - 2));
in the ‘WriteLog(XmlWriter w)’ method (file: Logger.cs at row 104). This seems having fixed the problem with no side effects. You could have problems running msbuild task if your server machine (the one in which you installed CruiseControl.NET) is not updated with all the software installed in a developer workstation. Let’s see which problems could arise:
CRUISE CONTROL.NET 1.5. CruiseControl.NET, MsBuild Task and Resources - Assembly Linker
If you want to provide localization for any of your projects or somehow use resources files (.resx) you will get an error during the build on the CruiseControl.NET server if MsBuild is not able to locate the Assembly Linker. The error should look something like: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets(1950,9): error MSB3011: “C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\AL.exe” was not found. Either 1) Install the .NET Framework SDK, which will install AL.exe. Or 2) Pass the correct location of AL.exe into the “ToolPath” parameter of the AL task. AL.exe is used to produce the satellite assemblies and the executable file is placed in the .NET framework directory. But Al.exe is a .Net Framework SDK tool. It is not included in .Net Framework 2.0 runtime installation. You need to install the .NET framework SDK on the server machine if you don’t want to encounter this problem. If you want to solve this particular issue in a tricky way without installing the whole SDK, you can copy al.exe.config e al.exe from a developer workstation and place them in the C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 directory on the server machine. This is how I solved the problem but I suggest you to install the .NET framework SDK on the server machine. 1.6. CruiseControl.NET, MsBuild Task and Web Application projects
A particular note is due for Web projects. Updating Visual Studio 2005 you get the SP1. Together with the Service Pack 1 for Visual Studio you get the WebApplication project template. Such template lets us add a new kind of project to our solution: a web site project structured exactly like any other Visual Studio project. So you can quit creating new websites (File –> New –> Web Site…) and start creating new WebApplication projects (File –> New –> Project… and then choose ‘ASP.NET Web Application‘). In order to use WebApplication projects you need to have Visual Studio installed on your machine and the WebApplication project plugin (that comes with the Visual Studio 2005 SP1). If the server in which CruiseControl.NET server is running is not a develpment workstation you will get an error when trying to build a WebApplication project, beacuse you miss those two prerequisites. You can easily fix this problem: you simply need to copy the file: Microsoft.WebApplication.targets that you can find under: “C:\Program Files\MSBuild\Microsoft\VisualStudio\v8.0\WebApplications\” from a development workstation and paste it to the corresponding path on the server machine (creating the directories in the path if needed).
CRUISE CONTROL.NET
Build Configuration –Visual Studio Most complex build processes use NAnt or MSBuild to script the build. However, for simple projects that just need to build a Visual Studio.NET solution, the Visual Studio task <devenv> provides an easier method. Examples Minimalist example: <devenv> <solutionfile>src\MyProject.sln Debug Full example: <devenv> <solutionfile>src\MyProject.sln Debug Build <project>MyProject <executable>c:\program files\Microsoft Visual Studio .NET\Common7\IDE\devenv.com 600 VS2002 Configuration Elements: Node
Description
Type
solutionfile
The path of the solution filesstring to build. If relative, it is relative to the Project
Required Default true
n/a
CRUISE CONTROL.NET
Working Directory. configuration
The solution configuration string to use (not case sensitive).
true
n/a
buildtype
The type of build. Valid values are Rebuild, Build or Clean (not case sensitive).
string
false
rebuild
project
A specific project in the string solution, if you only want to build one project (not case sensitive).
false
The default is to build all projects selected by the configuration.
executable
The path to devenv.com.
false
(see below)
false
600 (10 minutes)
string
buildTimeoutSeconds Number of seconds to wait int before assuming that the process has hung and should be killed. version
The version of Visual Studio.
One of VS2002, false VS2003, VS2005, VS2008, 7.0, 7.1, 8.0, or 9.0
description
If filled in, this will be string shown in the buildstage as the process name
false
(see below)
n/a
If executable and version are not specified, CC.NET will search the registry for VS.NET 2008, 2005, 2003, and 2002 in that order. If you need to use a specific version when a newer version is installed, you should specify the version property to identify it, or specify the executable property to point to the location of correct version of devenv.com. Note: this task requires you to have Visual Studio .NET installed on your integration server. Often programmers like to use a centralised project to build an entire software system. They define specific dependencies and the build order on that specific project to reproduce the behaviours of an nmake build.
Web Dashboard
CRUISE CONTROL.NET
Simple Installation The simplest way to install the Web Dashboard is to use the CruiseControl.NET installer, as described in the Basic Installation section. This should setup everything, resulting in a Dashboard instance being viewable at the Virtual Directory /ccnet. If something goes wrong, or you want more control, read the next section
Self-managed installation Basic Installation: CruiseControl.NET is distributed in 3 formats: Two Installers, one for CruiseControl.NET proper (the Server and Web Dashboard), and a second for the optional CCTray utility. The Installers are conventional Windows installation programs, which perform some useful early setup work for you, such as copying files to good locations, setting up a Virtual Directory for the Dashboard, etc. For most people starting out, this is the way to go. A binary zip file includes the same files as the installers but gives you more control over what you can do with them. A source zip which allows you to read or make your own changes to the CruiseControl.NET source code. The binary zip file will give you several sub-folders: /server: holds the assemblies for the CruiseControl.NET Server, including both the The Server Console Application and The Server Service Application . /webdashboard: contains the ASP.NET Web Dashboard application /cctray: contains the assemblies for the CCTray application /doc: contains HTML documentation for CruiseControl.NET With the binary zip file, you will have to manually configure IIS if you want to use the Web Dashboard, and you will have to manually install the service if you wish to run the Server that way. This is in addition to the usual, such as adding shortcuts to the Start Menu if you wish.
Then, in your system's IIS Admin tool: 1. Map a virtual directory to the 'webdashboard' subfolder of your CCNet folder (typically called ccnet) 2.In the configuration for this virtual directory, click the Configuration button of the Virtual Directory tab 3.Click Add to add a new Application Mapping 4.In Executable, enter the location of the aspnet_isapi.dll file you use (look at the .aspx mapping as an example. A typical value would c:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\aspnet_isapi.dll for CruiseControl.NET release 1.2.1 or earlier, or c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll for later releases) 5.In Extension, enter .xml
CRUISE CONTROL.NET 6.Make sure Script engine is checked and Check that file exists is not checked 7.Click OK as necessary to save your changes 8.Under the Virtual Directory's Documents tab make sure that default.aspx is added as a default document
Configuring the web dashboard The Web Dashboard is configured through the dashboard.config file, a set of XSL Files, and a set of [style sheets] (CSS files). In most cases this file will be found in the root of the Web Dashboard application. The only deployment-specific configuration in the web. Config file is an optional appSetting which can specify an alternative location for the dashboard.config file. If you want to use this behavior, set the DashboardConfigLocation appSetting value to be the absolute path of your dashboard.config file. The configuration file forms a tree of constructs, starting at the root element. The documentation for the rest of this section is reference documentation for each of the types of constructs you can use. Default Configuration The dashboard.config file that ships with CruiseControl.NET will work with a default setup, i.e. one where you are using a build server on the same machine as the Web Dashboard and haven't changed any of the Remoting settings.
Monitoring Multiple Servers It's easy to use a single IIS running the Web Dashboard to monitor multiple CruiseControl.Net build servers. See the Servers Configuration Block.
Configuration elements Dashboard Configuration Block Plugins Configuration Block • Build Log Build Plugin • Build Report Build Plugin • CCTray Download Plugin • Custom templates • Farm Report Farm Plugin • Latest Build Report Project Plugin • modificationHistoryProjectPlugin • Multiple XSL Report Build Plugin • Project Configurable Build Plugin • Project Report Project Plugin • Project Statistics Plugin • projectConfigurationServerPlugin • RSSFeedProjectPlugin • Server Information Server Plugin • Server Log Project Plugin
CRUISE CONTROL.NET • • • • • • •
Server Log Server Plugin Server Report Server Plugin View All Builds Project Plugin View Configuration Project Plugin ViewServerQueue Server Plugin XSL Report Build Plugin XSL Report Project Plugin Remote Services Configuration Block Servers Configuration Block
Dashboard Configuration Block : The root tag in the Dashboard Configuration file is the tag. The tag contains a section and a section. Example: . .
. . Plugins Configuration Block: The Web Dashboard comes pre-configured to use a default set of plugins. To change what plugins you want to use for your CruiseControl.NET deployment, use the section of the Dashboard configuration. The section is split up into 4 parts, representing the Farm, Server, Project and Build views available in the Dashboard. Each section can be configured with any number of plugins. Most Build Plugins can be configured just to be used for certain Projects. Example:
CRUISE CONTROL.NET <customTemplates>some_folder . . <serverPlugins> . . <projectPlugins> . . . .
Build Log Build Plugin: The Build Log Build Plugin shows you the XML log for a specific build. Initially it is viewed inline in an HTML view, but there is also an option to download the raw XML form. This is a Project Configurable Build Plugin. Example Configuration Elements There is no configuration for this plugin.
Build Report Build Plugin: The Build Report Build Plugin shows detailed output for a specific build. This report is generated by applying a list of XSL transforms to the build's log file.
CRUISE CONTROL.NET See XSL Files for a list of available XSL transforms. This is a Project Configurable Build Plugin. Example <xslFileNames> <xslFile>xsl\header.xsl <xslFile>xsl\compile.xsl <xslFile>xsl\unittests.xsl <xslFile>xsl\modifications.xsl <xslFile>xsl\fxcop-summary.xsl Configuration Elements Node
Description
xslFileName A list of <xslFile> tags, each one containing the path of an s XSL file relative to the root of the WebDashboard folder.
Type list of strings
Required Default yes
n/a
CCTray Download Plugin:
The CCTray Download Plugin adds a link to the dashboard to download the installer for CCTray. Example Configuration Elements There is no configuration for this plugin.
custom templates: It is possible to change the templates that are used in the dashboard. By default the dashboard looks in the /templates folder for the template to use. But, it is now possible to set a custom template location by setting <customtemplates> in .
CRUISE CONTROL.NET When a template is requested it will first look in the location specified by <customtemplates>. If there is a template in this folder it will use that template, otherwise it will use the template in the default location. Templates The following are some of the more commonly modified templates: Template
Description
SiteTemplate.vm
The main site template. This contains the header information (including links to the stylesheet and javascript), plus the overall layout for each page.
TopMenu.vm
The breadcrumbs for each page.
FarmSideBar.vm
The side bar for the farm-level views.
ServerSideBar.vm
The side bar for server-level views.
ProjectSideBar.vm
The side bar for project-level views.
BuildSideBar.vm
The side bar for build-level views.
ProjectReport.vm
The main project details page - this displays the build history graph.
ProjectGrid.vm
The main grid display - this is the list of all the projects, their current status and the action buttons.
Note: The side bars contain all the actions from the plug-ins. Themes It is possible to build themes using the custom templates location. This normally involves adding a new SiteTemplate.vm and a new stylesheet. SiteTemplate.vm needs to be modified to point to the new stylesheet, plus any other theme changes. Additionally, any of the other templates can be modified for a theme.
Farm Report Farm Plugin:
The Farm Report Farm Plugin shows you status information for all projects on all servers. If the Dashboard cannot connect to any specific server then an errors table is shown detailing the problems. Example Configuration Elements There is no configuration for this plugin.
CRUISE CONTROL.NET Latest Build Report Project Plugin:
The Latest Build Report Project Plugin lists all available builds for a project. Example Configuration Elements There is no configuration for this plugin.
modificationHistoryProjectPlugin: This plugin shows all the modifications of a project. The newest builds are shown first. The project must use the ModificationHistory Publisher to get results to show up. Minimal Configuration <projectPlugins> < modificationHistoryProjectPlugin />
....
This is available from build 1.3.0.2981 onwards Full Configuration <projectPlugins> < modificationHistoryProjectPlugin onlyShowBuildsWithModifications="true" />
....
Node onlyShowBuildsWithModifications
Description When true, builds without modifications will not be shown
Type Required Default bool
false
false
Multiple XSL Report Build Plugin:
The Multiple XSL Report Build Plugin shows detailed output for a specific build. This report is generated by applying a list of XSL transforms to the build's log file. It also allows for end users create build reports that combine existing XSL stylesheets in order. This was previously only available on the Build Report
CRUISE CONTROL.NET Build Plugin. See XSL Files for a list of available XSL transforms. This is a Project Configurable Build Plugin. Example <xslMultiReportBuildPlugin description="Build and Test Details" actionName="NUnitDetailsBuildReport"> <xslFileNames> <xslFile>xsl\header.xsl <xslFile>xsl\compile.xsl <xslFile>xsl\unittests.xsl Configuration Elements Node
Description
Type
Required Default
description
The description that will appear for the Plugin in the Dashboard
string
yes
n/a
actionName
A name for the action for this instance of the plugin. This must be strictly alpha-Numerical with no spaces and unique
string
yes
n/a
xslFileName A list of <xslFile> tags, each one containing the path of an s XSL file relative to the root of the WebDashboard folder.
list of strings
yes
n/a
Project Configurable Build Plugin: Most Build Plugins can be configured to be used only for certain projects. If they can be, it will say on their own documentation page. A Build Plugin by default will appear on the Build Plugins list for all projects, but you can specify either a specific inclusion or exclusion list. These are described below. You cannot have both an inclusion and an exclusion list (if you do, you will get a configuration exception.) Example The name of the plugin (myBuildPlugin) is just an example - it will actually be the name of the specific type of Build Plugin you are using. Also, the other property shown (myBuildPluginsOwnProperty) is just an example of where the plugin-specific properties would go.
CRUISE CONTROL.NET By default, you don't have to specify either an or <excludedProjects /> section, in which case your Build Plugin will be shown for all projects. <myBuildPlugin myBuildPluginsOwnProperty="Something"> <projectName>My Project <projectName>My Other Project OR <myBuildPlugin myBuildPluginsOwnProperty="Something"> <excludedProjects> <projectName>My Project <projectName>My Other Project Configuration Elements Node
Description
Type
includedProjects OR excludedProjects
A list of project names. If you use an string section the build plugin will list only appear for those projects. If you use an <excludedProjects> section the build plugin will appear for all projects apart from the specified ones. In both cases, the project names must match exactly to those specified in your build server config files, including use of spaces and capital letters
Required Default no
empty lists for both sections, plugin used for all projects.
Project Report Project Plugin:
The Project Report Project Plugin shows you summary details for a specific project. Part of these details is any External Links you have specified in the project configuration. Example <projectReportProjectPlugin /> Configuration Elements There is no configuration for this plugin.
CRUISE CONTROL.NET
Project Statistics Plugin:
The Project Statistics Plugin displays the statistics for the project. Since version 1.4 the graphs of Eden Ridgway are incorporated into CCNet. Example <projectStatisticsPlugin xslFileName="xsl\statistics.xsl" />
<projectStatisticsPlugin xslFileName="xsl\StatisticsGraphs.xsl" /> Configuration Elements Node xslFileName
Description The file containing the XSL transforms to use. The path is relative to the root directory of the Web Dashboard
Type Required Default string
yes
n/a
projectConfigurationServerPlugin: This plugin shows the basic configuration of the projects on this buildserver. Like project name, category, queue and queue priority, making it easier to spot conflicts in the queue setup for this buildserver. Example <projectConfigurationServerPlugin/> Configuration Elements There is no configuration for this plugin.
RSSFeedProjectPlugin: This publisher generates an RSS feed reporting the builds for a project. The project must use the RSS Publisher to produce the data for the feed. This is available from build 1.3.0.3011 onwards. The RSS icon will be displayed on the project page, whenever a build is done with the Publisher. So there is no configuration to be done in the webdashboard for this. Should you want to remove the RSS icon from the project page, remove the RSS publisher from the project, and delete the RssData.xml file from the artifact folder.
Server Information Server Plugin:
CRUISE CONTROL.NET The Server Information Server Plugin gives you information about a build server, for example the version of CruiseControl.NET the build server is running. Example <serverInformationServerPlugin /> Configuration Elements There is no configuration for this plugin.
Server Log Project Plugin: The Server Log Project Plugin shows you recent activity that has been output to the server log for a specific project. Read the Server Application Config File page for more help on build server logging. Example <serverLogProjectPlugin /> Configuration Elements There is no configuration for this plugin.
Server Log Server Plugin: The Server Log Server Plugin shows you recent activity that has been output to the server log for a specific build server. Read the Server Application Config File page for more help on build server logging. Example <serverLogServerPlugin /> Configuration Elements There is no configuration for this plugin.
Server Report Server Plugin: The Server Report Server Plugin shows you status information for all projects on a specific server. If the Dashboard cannot connect to the server then an errors table is shown detailing the problem. Example <serverReportServerPlugin /> Configuration Elements
CRUISE CONTROL.NET There is no configuration for this plugin.
View All Builds Project Plugin: The View All Builds Project Plugin lists all available builds for a project. Example Configuration Elements There is no configuration for this plugin.
View Configuration Project Plugin: The View Configuration Project Plugin shows the configuration for a project. This plugin shows the entire configuration. From build 1.4.0.3737 onwards, passwords are masked by default. Should you want to check the passwords via the dashboard, set hidePasswords to false. .
Example Configuration Elements Element
Description
Type Required Default
hidePassword Hides(masks) the passwords of all sections that have password bool s attributes.
ViewServerQueue Server Plugin: This plugin shows the current state of the queues on the build server. Example Configuration Elements There is no configuration for this plugin.
false
true
CRUISE CONTROL.NET
Xsl Report Build Plugin: The Xsl Report Build Plugin shows detailed output for a specific build using a configured XSL Transform. See XSL Files for a list of available XSL transforms and how to use your own transforms. This is a Project Configurable Build Plugin. Example <xslReportBuildPlugin description="NUnit Details" actionName="NUnitDetailsBuildReport" xslFileName="xsl\tests.xsl" /> Configuration Elements
CRUISE CONTROL.NET
Node Description Type Required Default
description The description that will appear for the Plugin in the Dashboard string yes n/a
actionName A name for the action for this instance of the plugin. This must be strictly alphaNumerical with no spaces and unique string yes n/a
xslFileName
CRUISE CONTROL.NET
Remote Services Configuration Block: At this time the tag just contains a <servers> section. This section contains all the build servers that the Dashboard will visualize. Example: <servers> . .
Servers Configuration Block: The Dashboard needs to connect over the network to each of Build Servers you want to report on. If you have changed any of the remoting configuration for your servers, you'll need those details now. (See Server Application Config File for more details on configuring remoting and management URLs.) To configure the dashboard, add a <server> tag for each CruiseControl.NET Server you want to monitor to the <servers> section. Example <servers> <server name="local" url="tcp://localhost:21234/CruiseManager.rem" allowForceBuild="true" allowStartStopBuild="true" /> Configuration Elements <server> tags have the following syntax: Node
Description name
Type Required Default
A referential name for the server - this must be unique string for each server monitored by the Dashboard
yes
n/a
CRUISE CONTROL.NET
url
string
yes
n/a
Displays or hides the Force Build button on the Project bool Dashboard page
no
true
allowStartStopBuil Displays or hides the Stop Build button on the Project bool d Dashboard page. Stopping a build will stop the project's triggers so that they will not trigger new builds until the project is started again; this will not abort a build that is in progress.
no
true
allowForceBuild
The management URL for the Server
Using Web dashboard Assuming you've set everything up OK, you should be able to view the default page in the Virtual Directory you setup for your web application. The default page on CCNetLive is at http://ccnetlive.thoughtworks.com/ccnet/, and you should see something similar.
CRUISE CONTROL.NET
What you are seeing here is the Farm View. There are 4 different views in the CCNet Web Application, with increasingly narrower scope. Here's a brief description: • • • •
Farm - shows all projects running on all servers. Drill down into a project by clicking on its name Server - shows all projects running on a server. From here you can also view the 'server log' (and later on add projects to a server) Project - Shows a summary of the current state of a project, shows the recent builds, and allows project configuration (to come later.) Drill down into a specific build by clicking on its name Build - This is the equivalent of the old CCNet [Project Report Web Application]. Here you can view the results of a build in various ways (summary report, full log, FxCop results, etc.)
CRUISE CONTROL.NET
Developing webdashboard plugins: The Web Dashboard supports custom plugins. This page is documentation for developing your own Dashboard plugins. First of all, you need to decide what type of plugin you are developing: • • • •
A Farm Plugin is used when you have not specified any particular project or server to view. Farm plugins therefore appear in the 'default' view of the Dashboard. A Server Plugin is used when you are looking at a specific server, but not any particular project. A Project Plugin is used when you are looking at a specific project, but not a particular build. A Build Plugin is used when you are viewing a specific build for a specific project. Actions About Actions The CruiseControl.NET Web Dashboard includes its own Web Framework implementation. The fundamental 'component' in this framework is an Action. An Action represents a specific interaction between the application and a user. Some features require multiple actions, e.g. one Action to allow a user to edit some fields, and then another to show the results of this. Your Dashboard Plugin must include at least 1 Action. It can include more than 1, but only 1 will ever be linked directly from the Dashboard menus (the others must be linked by your other actions.) Implementing Actions The Actions you write should implement ICruiseAction. This has one method on it:
•
IResponse Execute(ICruiseRequest cruiseRequest) The responsibility of an Action's Execute method is 'Given a request, generate a response'. The response is the 'main panel' part of the Dashboard's UI. Defining dependencies The CruiseControl.NET Web Dashboard uses a Constructor Dependency Injection (CDI) pattern to enable classes to define what types they are dependent on. The Dashboard API has a number of types you can depend upon which can do things like return you the currently viewed build log. You can also specify dependencies to your own types. It is recommended that you use interfaces to define responsibilities. The Dashboard's CDI implementation does not currently allow for runtime configuration. It will use sensible defaults where available. We plan on adding more configuration later. How to start To implement your own actions, it’s probably best to first look at the source code for the Dashboard's own plugins. These are available in the ThoughtWorks.CruiseControl.WebDashboard.Plugins Namespace. Support Class
CRUISE CONTROL.NET Once you've written your action(s), your Plugin is almost complete, but you have one more interface, IPlugin, to implement. For simple , single-action, plugins you can just implement this interface on the same class as your action, otherwise it must be implemented on another (single) class. IPlugin contains the following properties: • •
{{LinkDescription { get; }}} – Specifies the text that appears in the Dashboard UI to link to this plugin {{INamedAction[] NamedActions { get; }}} The Actions property returns instances of all the Actions in your plugin. An Action is specified (in a INamedAction) by giving the action instance itself, and also a (unique) Action Name that will be used by the Web Framework's controller to route user requests. Action Names should just include alpha-numeric characters (i.e. only a-z, A-Z, and 0-9). The Actions property must return an array with at least one INamedAction. The first named action, i.e. Actions [0] will be the Action linked to through the Dashboard UI. For this entire look at existing implementations to see how CruiseControl.NET defines its own plugins. Build Plugins Build Plugins have a slight complication, in that they must implement the slightly richer interface IBuildPlugin rather than IPlugin. Most Build Plugins will do this by extending the ProjectConfigurableBuildPlugin class, which automatically makes them a Project Configurable Build Plugin - simple! Apart from that Build Plugins are identical to other plugins. Deploying your Plugin To deploy your plugin:
• • •
Compile your plugin to an assembly with the name ccnet.anything-you-like.plugin.dll Copy the assembly to the bin folder of the Dashboard Configure your plugin in the Plugins Configuration Block as normal
Getting the Web Dashboard working with IIS Make sure that ASP.NET is installed on server: Go to add/remove programs, add/emove windows components, select Application Server then click on Details. Make sure that ASP.net is ticked.
CRUISE CONTROL.NET
If you installed IIS after the .Net framework was installed, you need to register ASP.Net with IIS. You can do this by running the aspnet_regiis.exe -i tool found under \Windows\Microsoft.NET\Framework\v2.0.50727\ In IIS Admin go to Web Service Extentions and make sure that Asp.net v2.0.* is allowed and any other version prohibited.
Setup the Dashboard With the build server all setup, make sure to configure your Dashboard to show MSBuild results. You will need to make the following modifications to the dashboard.config file: Make sure your Build Report Build Plugin includes the compile-msbuild.xsl file
CRUISE CONTROL.NET
You'll probably also want to setup an MSBuild Output XSL Report Build Plugin using the msbuild.xsl file, e.g. : <xslReportBuildPlugin description="MSBuild Output" actionName="MSBuildOutputBuildPlugin" xslFileName="xsl\msbuild.xsl" />