UppercuT – Added Pre-Task Hooks for Custom Tasks

Tonight I committed pre-task hooks for custom tasks in UppercuT. What has been available up to this point is only the post-task custom hooks.  Now you can hook in before a task runs and run your own custom tasks!

This is done the same way as the post run custom tasks. The naming convention here is *.pre.build in the name. For example _compile.pre.build would be the pre-task custom tasks for _compile.build.

The post task custom tasks are now moving to a *.post.build naming standard. For now using the same name as the task will still give the same results as in previous versions, but it is deprecated in favor of the *.post.build naming. We expect that to change at some point (probably at the point of using that naming convention for the replacement tasks).

The Tools Do Make a Difference OR How to Justify a New Laptop to Your Wife!

It doesn’t matter how good you are, the tools do make a difference.  That is not to discount the skill of the person that is using the tools.  That is not to say that the tools are more important than the person. The most important thing is still the abilities of the person. 

I recently got a new laptop with SSD. I can say this is the nicest thing I have ever had for a laptop. I can also say that I am definitely enjoying what I like to call “instant” Visual Studio. It’s not really instant, but it loads a solution in less than 4 seconds. It itself opens in about 1-2 seconds. I haven’t even optimized the laptop yet (and I won’t until after I install Windows 7), so I’m not really for sure how fast it can be yet.

image 

I got a Dell Studio XPS 16. The features are amazing! And there are plenty of reviews that gave the laptop high marks! Plus I really liked the look of this laptop. I looked around at a bunch of laptops. I even looked at Macs. For the money and the features, I found this was going to best meet my needs in a laptop.  Some reviews even compared this to the looks of the Mac Book! Of course they considered it a knock off and a bit cheaper, but it also didn’t cost me $4K+ to get a MBP with the same features!

I got this for just under $2K. This is also the first time I have spent over $1K on a laptop. Heck, this was even more expensive than my first ever computer (Gateway POS Windows 95, Pentium I 133, 32MB RAM, 4GB HDD) that cost me nearly $1900 dollars! My justification for the cost is that I am a developer and I should have better tools to work with. Now I can get things done closer to the speed of thought. I find myself waiting less on the computer and more the computer waiting on me now. So like I was saying, the tools can really make a difference!

image

image

Specs (for the 2 people that are actually still reading this):

  • Display - 16in RGBLED LCD (1920x1080) – This display gives you 100% of the color gamut and 130 degree viewing angle!
  • Processor - Intel Core 2 Duo 8600 (2.4GHz) – I didn’t really upgrade the processor as much as I probably should have.
  • Memory - 4GB DDR3 SDRAM at 1067MHz – I didn’t see much need to buy more RAM yet. It’s cheaper to get from other sources anyways.
  • Hard Drive - 256GB Samsung PM800 SSD (Solid State Drive) – Yeah. I splurged here. It was much cheaper than full price!
  • Video Card - ATI Mobility Radeon HD 3670 (512MB) – It was the only option at the time. Now they have the 4670 (1GB).
  • I didn’t get the BluRay optical drive. I am not sure if I should have or not. I just looked at it and didn’t want to spend more on it.
  • I got the additional 9 cell battery. It lifts the back up a little more, but it fits in pretty snugly into the laptop. 

All in all I am very happy with the laptop so far and will really enjoy it once I move to Windows 7! I’ve never really been a fan of Vista, but I don’t mind spending another month with it.

TortoiseSVN Missing Context Menu After Vista Upgrade from Home to Ultimate

Recently I upgraded Vista Home to Ultimate. I could not get the context menu back. I thought I was going crazy trying to get it back. I uninstalled and reinstalled many a time trying to get it back. I still couldn’t get TortoiseSVN to show up. So I uninstalled and started a rampage through the registry to find what I needed to remove. I came across this key:

image

HKEY_CURRENT_USER\Software\TortoiseSVN

It had an entry for Context Menus (which I had modified). I backed the key up and deleted it. Then re-installed TortoiseSVN and rebooted. And viola! It works! That’s totally money! YMMV, but I thought I would share if you find yourself in the same boat as me.

 

Subversion 1.6, Tree Conflicts, and the Incompatibility of Subversion 1.5: What You Need to Know

NOTE: Subversion's new tree conflicts feature is something you need to learn about. Otherwise it will bite you later and you will be left with an uncommitted change and confusion about how to get it committed. Take a few moments to read this article.

SVN 1.6 Client + 1.5 Server = "Error: Aborting commit: 'C:\SVN\source-branch\src\item.vssscc' remains in conflict " and the file is gone. It's just gone!

image

Subversion 1.6 has been out for awhile and quite a few of us just upgraded our TortoiseSVN clients because there was a new version. There are some new features with it that make it desirable (including externals support for files, file system storage improvements, etc).

Perhaps the most important new feature we learn about (usually the hard way during a merge) is a new feature call Tree Conflicts. Just what are tree conflicts?  Submerged, the CollabNet Subversion Blog talks about these conflicts:

Subversion 1.6.0 expands this concept to cover conflicts at the directory level, e.g. you locally delete a file then an update tries to bring a text change down on that file. These new types of conflicts are called tree conflicts.

I think the best definition is in the subversion book:

What happens if your collaborators move or delete a file that you are still working on? Maybe there was a miscommunication, and one person thinks the file should be deleted, while another person still wants to commit changes to the file. Or maybe your collaborators did some refactoring, renaming files and moving around directories in the process. If you were still working on these files, those modifications may need to be applied to the files at their new location. Such conflicts manifest themselves at the directory tree structure level rather than at the file content level, and are known as tree conflicts.

To further explain a tree conflict is when SVN notices changes in a directory. Like a file gets renamed to something else. Then someone tries to edit the original file in a branch or in the mainline (or in the same line before getting latest). What they are going to get on the next subversion update or merge is a tree conflict.

If you still don't understand what a tree conflict is and how it affects you, I encourage you to read the links above that explain it in detail.

SVN 1.5 & SVN 1.6 Do NOT Play Well Together

Read that again. Subversion 1.5 and Subversion 1.6 DO NOT play well together. If you have upgraded a client to 1.6 or the server to 1.6 and you still have 1.5 out there lingering, you are going to run into some compatibility issues.  You are going to run into errors like I described above.

When the client is upgraded and the server is not, you are going to see conflicts that you cannot physically resolve. You are also going to get issues with trying to resolve the tree conflicts you can resolve because the server is confused. I ran into these types of errors. Most of you will upgrade your clients and possibly run into this as well.

"Error: Aborting commit: 'C:\SVN\source-branch\src\item.vssscc' remains in conflict " and the file is gone. It's just gone!

I was able to resolve everything except for the case where a file was deleted both from the branch and the mainline. During the merge there was no file I could click on to resolve the conflict and there wasn't a way to resolve the issue otherwise. I pulled my hair out trying to figure this out. Then I started searching. I probably should have started there.  If you look at the comments in Paul Barba's Submerged article (CollabNet Subversion Blog):

Hi Rob,

I just wrote a long response, but then something occurred to me: What version of TortoiseSVN are you using? I haven't downgraded to check exactly what happens, but if you are not using TortoiseSVN 1.6+ then you will definitely have problems with tree conflicts if you are using a 1.6+ command line client.

See http://tortoisesvn.tigris.org/tsvn_1.6_releasenotes.html#compatibility.

Of course if you *are* using TortoiseSVN 1.6+ then let me know and we can go from there.

Paul

What I missed originally is that Paul is talking about TortoiseSVN as the server. I use VisualSVN Server for the server in source control. He hadn't downgraded to see what the issue is, but I know from experience (and a couple of long and painful merge processes), it's a bear!

When the server is upgraded and the client is not, its possible everything is going to look okay locally and you won't be able to commit due to a tree conflict. This is pretty scary as well!  Imagine the frustration when everything looks fine and you can't commit! Note: I haven't actually verified this side, it's more theory. If you have had this experience or not, please comment. It's possible this scenario will work appropriately (see http://tortoisesvn.tigris.org/tsvn_1.6_releasenotes.html#tree-conflicts).

Recommendation

Wait until you can upgrade both the client and the server (and usually it's the server that is waiting for the upgrade) before you migrate to Subversion 1.6. Otherwise you might run into some weird issues. And not issues you can resolve before a commit!

Did you enjoy this article?

kick it on DotNetKicks.com     Subscribe for more updates!

SQL Server 2005/ SQL Server 2008 - Rebuild or Reorganize ALL Indexes in a Database

I found this gem while looking at a database that needed all indexes rebuilt.

I actually had to create the programmatic way of doing rebuilding all indexes in a database based on the information in these posts:

See the fragmentation:

USE __REPLACE_WITH_DATABASE_NAME__
GO

Print 'Selecting Index Fragmentation in the database.'

SELECT 
  DB_NAME(DPS.DATABASE_ID) AS [DatabaseName]
 ,OBJECT_NAME(DPS.OBJECT_ID) AS TableName
 ,SI.NAME AS IndexName
 ,DPS.INDEX_TYPE_DESC AS IndexType
 ,DPS.AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation
 ,DPS.PAGE_COUNT AS PageCounts
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, NULL) DPS --N'LIMITED') DPS
INNER JOIN sysindexes SI 
    ON DPS.OBJECT_ID = SI.ID 
    AND DPS.INDEX_ID = SI.INDID
ORDER BY DPS.avg_fragmentation_in_percent DESC
GO

Fix the fragmentation with a rebuild:

Print 'Rebuilding indexes on every table in the database.'

EXEC sp_MSforeachtable @command1="print 'Rebuilding indexes for ?' ALTER INDEX ALL ON ? REBUILD WITH (FILLFACTOR = 90)"
GO

Fix the fragmentation with reorganize:

Print 'Reorganizing indexes on every table in the database.'

EXEC sp_MSforeachtable @command1="print 'Reorganizing indexes for ?' ALTER INDEX ALL ON ? REORGANIZE"
GO

Notice how we have items that are at 99% fragmentation and how they are gone once we run this rebuild.

image

Awesome?

If you are fuddy-duddy DBA, you would say only to rebuild indexes with greater than 30% fragmentation and reorganize the rest.  That's fine, show me some code on how to programmatically do this! :D

Or put the Ayende way, send me a patch!

kick it on DotNetKicks.com

UppercuT - TeamCity Integration - Part 4 (Code Drop / Artifacts of the Build)

In Part 1 we create a project. In Part 2 we set up the Build Configuration. In Part 3 we ran the build. Now we are just going to note how we get to our code.

 

Code Drop / Artifacts

TeamCity stores all artifacts in a database. So for every build, the drop location is not a physical disk location, it’s actually in a database.

  clip_image002_thumb[2]

This is why we called zip.bat instead of build.bat. We have to download the items from TeamCity and want to just download the one file. If we download that file and unzip it, we can see that the DLLs were versioned correctly.

  clip_image004_thumb

 

 UppercuT - TeamCity Integration Series

  1. Part 0 - Prerequisites
  2. Part 1 - Set up TeamCity Project
  3. Part 2 - Build Configuration
  4. Part 3 - Run the Build
  5. Part 4 - Code Drop / Artifacts

With this knowledge you shall build.

kick it on DotNetKicks.com

UppercuT - TeamCity Integration - Part 3 (Run the Build)

In Part 1 we create a project. In Part 2 we set up the Build Configuration. This time we will Run the build.

 

Run the Build Project

1. Click on Projects.

  clip_image002_thumb[1]

2. You can see that the new project has not run before due to the question mark.

  clip_image004_thumb[1]

  clip_image006_thumb

3. Let’s kick it off. Click {Run |…}.

  clip_image008_thumb

4. The page refreshes automatically to show that we are running.

  clip_image010_thumb[1]

5. NOTE: The first build may fail due to folder cleaning that is happening at the same time. You will see a note in the build log that it is deleting items at the same time it is trying to build. If this happens, just click on {Run |…} again.

  clip_image012_thumb[1]

6. We can follow along with what’s happening by clicking on the down arrow next to the status and clicking on [Full log].

  clip_image014_thumb[1]

7. We have a successful build.

  clip_image016_thumb[1]

 

Next time we will talk about the code drop / artifacts.

 UppercuT - TeamCity Integration Series

  1. Part 0 - Prerequisites
  2. Part 1 - Set up TeamCity Project
  3. Part 2 - Build Configuration
  4. Part 3 - Run the Build
  5. Part 4 - Code Drop / Artifacts

With this knowledge, you shall build.

kick it on DotNetKicks.com

UppercuT - TeamCity Integration - Part 2 (Create a Build Configuration)

 

Last time we created a project. This time we will set up the build configuration with it.

 

Create a Build Configuration

1. Click {add a build configuration} for this project.

  clip_image002_thumb[1]

2. In the [Name:] field, we need to add something descriptive. We are building the trunk on every change. Let’s call it Bombali Trunk CI.

  clip_image004_thumb[1]

3. In [Artifact paths:] enter code_drop/*.zip.

  clip_image006_thumb[1]

4. In the Fail build if: section, ensure that these settings are checked:

    a. build process exit code is not zero

    b. at least one test failed

    c. an out of memory or crash is detected

  clip_image008_thumb[1]

5. In the Build options: section, ensure that these settings are checked:

    a. Enable hanging builds detection

  clip_image010_thumb[1]

6. Click {VCS settings >>}.

  clip_image012_thumb[1]

7. Click on {Create and attach new VCS root}.

  clip_image014_thumb[1]

8. Enter a name in [VCS root name:]. We are going to use our project and where the source is from, so we put in Bombali SVN. Choose what is most appropriate for you.

  clip_image016_thumb[1]

9. Select the appropriate source control. We select Subversion as our source control. NOTE: Each source control option has different options. We are only going to talk about SVN.

  clip_image018_thumb[1]

10. We enter the [URL:] to our project.

  clip_image020_thumb[1]

11. The next option is [Externals support:]. If you use externals at all, you would want to enable full support. And you would know if you are using externals. Otherwise, leave default to ignore externals.

  clip_image022_thumb[1]

12. I like to clear out [Labeling rules], but that is a matter of preference. With UppercuT we can get back to any specific build and revision based on our DLLs. Choose what is most appropriate for you.

  clip_image024_thumb[1]

13. I leave the [Checking interval:] at the default of [use global server setting (60 seconds)]. Choose what is most appropriate for you.

  clip_image026_thumb[1]

14. Click {Test connection}. If it is successful, we can move on. If not, make the edits you need.

  clip_image028_thumb[1]

15. Click {close}.

  clip_image030_thumb[1]

16. Click {Save} to continue.

  clip_image032_thumb[1]

17. In the Checkout Settings section:

    a. [VCS checkout mode:] is Automatically on server.

    b. [Checkout directory:] is an appropriate directory for you. We are going to use C:\CodeBuild\Bombali.

    c. We leave [Clean all files before build:] unchecked. Choose what is most appropriate for you.

  clip_image034_thumb[1]

18. In the VCS Labeling section:

    a. We select [Do not label]. Choose what is most appropriate for you.

  clip_image036_thumb[1]

19. Click on {Choose Build Runner >>}.

  clip_image038_thumb[1]

20. Set [Build runner:] to Command Line.

21. Set [Command executable:] to zip.bat.

  clip_image040_thumb[1]

22. We are leaving the XML Report Processing section set to its default for now. Choose appropriately if you would like to use this section.

23. Click {Save}.

  clip_image042_thumb

24. You should get a message that the build configuration has been created successfully.

  clip_image044_thumb[1]

25. Click on [Build triggering].

  clip_image046_thumb

26. Check [Enable triggering when files are checked into VCS].

  clip_image048_thumb[1]

27. Click {Save}.

  clip_image050_thumb

28. Set any other options you need to set.

 

Next time we are going to run the build.

 UppercuT - TeamCity Integration Series

  1. Part 0 - Prerequisites
  2. Part 1 - Set up TeamCity Project
  3. Part 2 - Build Configuration
  4. Part 3 - Run the Build
  5. Part 4 - Code Drop / Artifacts

With this knowledge you shall build.

kick it on DotNetKicks.com

UppercuT - TeamCity Integration - Part 1 (Create a TeamCity Project)

 

Integrating UppercuT with TeamCity is actually very easy. We will go through the steps to set up and run a build. Let's start with Creating a project.

Create A Project

1. Log into TeamCity.

2. Go to Administration.

  clip_image002_thumb

3. Click on create project.

  clip_image004_thumb

4. Type a name for your project. Try to use an identifying name. In our example, we are using Bombali. We also add a nice description about the project. Choose what is most appropriate for you.

  clip_image006_thumb[1]

5. Click {Create}.

 

Next we will create a Build Configuration.

UppercuT - TeamCity Integration Series

  1. Part 0 - Prerequisites
  2. Part 1 - Set up TeamCity Project
  3. Part 2 - Build Configuration
  4. Part 3 - Run the Build
  5. Part 4 - Code Drop / Artifacts

With this knowledge, you shall build.

 

kick it on DotNetKicks.com

UppercuT - Automated Builds - Test Category Filters

I'm happy to announce that UppercuT now has test category filters.  The NUnit Task had them by default. To get categories added to MbUnit Task, I had to go back to the source code and add them. I followed the same format that NAnt-Extensions used:

<mbunit
    report-types="Html;Xml;Text"
    report-filename-format="${file.test_results}"
    report-output-directory="${dirs.test_results}"
    halt-on-failure="true"
    failonerror="true"
    >
  <assemblies>
    <exclude name="${dirs.build}\*Database*dll" />
    <exclude name="${dirs.build}\*.Integration*dll" />
    <exclude name="${dirs.build}\TestFu.dll" />
    <include name="${dirs.build}\*Test*dll" />
    <include name="${dirs.build}\*.Specs*dll" />
  </assemblies>
  <categories>
    <exclude name="Database" />
    <exclude name="Integration" />
    <exclude name="Slow" />
    <exclude name="NotWorking" />
    <exclude name="Ignore" />
    <exclude name="database" />
    <exclude name="integration" />
    <exclude name="slow" />
    <exclude name="notworking" />
    <exclude name="ignore" />
  </categories>
</mbunit>

That has been added in Revision 111. Keep in mind when you get the latest version, you will need to replace MbUnit.Tasks.dll in your NAnt folder as well.

With this knowledge you shall build.

 

kick it on DotNetKicks.com

UppercuT - Automated Builds - Getting Started Part 0 (Prerequisites)

In all discussion about how to get started, I didn't mention that there are prerequisites to using UppercuT.  Well, really there is only one prerequisite. 

Prerequisites

  • Source control command line tool on the path

image

If you are unsure, open a command line and type svn to find out if you already have it installed.

Download

In our case Subversion Command line client. You can get that from Collabnet (you will have to register) at http://www.collab.net/downloads/subversion/. Note: If you have installed VisualSVN, you already have command line SVN on the path. 

Choose CollabNet Subversion Command-Line Client v1.x.x (for Windows).

image 

Register, download, and install that.

Ensure Path

Then you have to ensure it's on the path so you can open a command line in any folder and type svn.

Note: If you install CollabNet's SVN client, it should already be on the path.

1. These instructions are geared to WindowsXP. Adjust for other Operating Systems.

2. Right click on My Computer on the Desktop and select [Properties].

  image

3. Click on the Advanced tab. Click on {Environment Variables}.

  image 

4. In the System variables section, there is a variable named Path. Select Path, and then click {Edit}.

  image

5. Ensure that somewhere in that long set of text is C:\Program Files\CollabNet Subversion Client;. If it's not there, add it. Make sure you separate each path with a semi-colon (;).

  image

6. Click {OK}. Click {OK} all the way out.

 

With this knowledge you shall build.

kick it on DotNetKicks.com

NDepend and CruiseControl.NET

NDepend is one of the best code analysis tools out there for determining code quality! It does so with some advanced metrics and I can say I still don't understand all of it, but we take advantage of the areas we do understand! It will help point you to possible problems with code during code reviews and it has some nice images to help visualize what's going on in your code.  You can even hook it up to CruiseControl.NET (CC.NET) and see reports for NDepend per build. We are going to talk about how to do that as well as displaying images.

One of the most interesting things you have to do to get images working for NDepend on CruiseControl.NET is to apply an image handler.  This is based on Robin Curry's original method (and still the one that is referred to by NDepend) for getting images into CC.NET build reports. It does further abstract the location of the images to the build's known location instead of hard coding it into the handler. Don't worry if you don't understand that, you will by the time we are done.

Get Revision Information Merged In

One thing we won't get in our build log on CC.NET is our revision number. So we need to make sure that information gets merged in.

In our builds, we set up the revision number:

<target name="generate_build_info_file">
  <echo message="Generating XML file with some information to possibly get merged in at ${files.build_info}."/>
  <echo file="${files.build_info}" append="false" failonerror="false">
    <![CDATA[
    <revision>${version.revision}</revision>
    ]]>
  </echo>
</target>

This creates a file named _buildinfo.xml.

image

The contents of this file are:

      <revision>5</revision>

Then we import that on every project, along with NDepend xml. This is done in the ccnet.config file for each project. Below nearly everything else has been removed for clarity. This also takes advantage of Preprocessors.

<project name="$(projectName)">
...
<publishers> <merge> <files> <file>$(working_directory)\$(projectName)\build_output\build_artifacts\*.xml</file> <file>$(working_directory)\$(projectName)\build_output\build_artifacts\mbunit\*-results.xml</file> <file>$(working_directory)\$(projectName)\build_output\build_artifacts\nunit\*-results.xml</file> <file>$(working_directory)\$(projectName)\build_output\build_artifacts\ncover\*-results.xml</file> <file>$(working_directory)\$(projectName)\build_output\build_artifacts\ndepend\*.xml</file> </files> </merge>
....
<xmllogger/> </publishers> </project>

This will merge that file into each build log. That means that <revision> is now available for our use.

XSL File for NDepend Reports

We have some good information available in our build logs file after a build that we can use for our needs:

<integrationProperties>
  <CCNetArtifactDirectory>c:\CodeDrop\Bombali</CCNetArtifactDirectory>
  ...
  <CCNetLabel>16</CCNetLabel>
  <CCNetNumericLabel>16</CCNetNumericLabel>
  <CCNetProject>Bombali</CCNetProject>
  <CCNetProjectUrl>http://robz.homedns.org:8081/ccnet</CCNetProjectUrl>
  ...
</integrationProperties>

Remember that _buildinfo.xml file we merged in?

We also get this near the top of the file:

</integrationProperties>
 <build date="2009-05-31 14:58:31" buildtime="00:00:00" buildcondition="IfModificationExists">
     
<revision>108</revision>
     

Now we can use that information so that we can refer to images in the ndependreport-ccnet.v2.xsl (comes with NDepend).

First we need to set up our xsl variables at the top of the file.

<xsl:variable name="label" select="//CCNetNumericLabel/text()" />
<xsl:variable name="revision_number" select="//revision/text()" />
<xsl:variable name="project_directory" select="//CCNetArtifactDirectory/text()" />
<xsl:variable name="project_url" select="//CCNetProjectUrl/text()" />

Then there are three locations where the NDepend XSL refers to images.  We will update all three of them keeping the name of the image.

<img>
  <xsl:attribute name="src">
    <xsl:copy-of select="$project_url" />/image.ashx?project=<xsl:copy-of select="$project_directory" />&amp;label=<xsl:copy-of select="$label" />&amp;revision=<xsl:copy-of select="$revision_number" />&amp;name=AbstractnessVSInstability.png
  </xsl:attribute>
</img>

Here is a picture to illustrate (that line is very long):

image 

The important thing to note is that we are passing query string information to image.ashx so that it can find and include the NDepend images.

We need to include that file with CruiseControl.NET. That goes in the XSL directory of the webdashboard. That is usually in  C:\Program Files\CruiseControl.NET\webdashboard\xsl.

image

Make sure your dashboard.config file knows to include NDepend Reports. This is usually in C:\Program Files\CruiseControl.NET\webdashboard. Mine is in a location where I can keep it in source control, but the relative path works for both. You can choose to remove ..\webdashboard if you keep the dashboard.config file in that location.

<buildPlugins>
    <buildReportBuildPlugin>
        <xslFileNames>
            ...
            <xslFile>..\webdashboard\xsl\ndependreport-ccnet.v2.xsl</xslFile>
            ...
        </xslFileNames>
    </buildReportBuildPlugin>
    <buildLogBuildPlugin />
    ...
    <xslReportBuildPlugin description="NDepend Report" actionName="NDependBuildReport" xslFileName="..\webdashboard\xsl\ndependreport-ccnet.v2.xsl" />
    ...
</buildPlugins>

The Image Handler

The image handler (image.ashx) from Robin must be added to the webdashboard folder of CC.NET's install location. I tried not to change Robin's handler much, but I made a few tweaks to suit my needs (in bold):

<%@ webhandler language="C#" class="ImageHandler" %>
using System;
using System.Configuration;
using System.Data; 
using System.Data.SqlClient; 
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Net;
using System.Web;
using System.Web.Caching;
 
 
public class ImageHandler : IHttpHandler
{
  public bool IsReusable  { get { return true; }  }
 
  private string _imagePath = @"{0}\b{1}-r{2}\build_artifacts\ndepend\";
 
  /// <summary>
  /// Processes the request.
  /// </summary>
  /// <param name="ctx">CTX.</param>
  public void ProcessRequest(HttpContext ctx)
  {
    try
    {
      string name = ctx.Request.QueryString["name"];
      string project = ctx.Request.QueryString["project"];
      string label = ctx.Request.QueryString["label"];
      string revision = ctx.Request.QueryString["revision"];
      string cacheKey = string.Format("{0}|{1}|{2}|{3}", name, project, label, revision);
 
      if ( name != null && name.Length > 0)
      {
        Byte[] imageBytes = null;
 
        // Check if the cache contains the image.
        object cachedImageBytes = ctx.Cache.Get(cacheKey);
 
        // Use cache if possible...
        if ( cachedImageBytes != null )
        {
          imageBytes = cachedImageBytes as byte [];
        }
        else // Get the image from the project/build directory.
        {   
          // Determine the base path from config file if provided.
          string imagePath = ConfigurationSettings.AppSettings["imagePath"];
          if ( imagePath == null || imagePath.Length == 0 )
          {
            // If not provided, default to:
            imagePath = _imagePath;
          }
 
          // Replace tokens in the provided path with the project and label.
          imagePath = string.Format(imagePath, project, label, revision);
 
          // If the path is relative, combine with the current base directory.
          if ( !Path.IsPathRooted(imagePath) )
          {
            imagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, imagePath);          
          }
 
 
          try
          { // Get the image stream from the provided path.
            using ( FileStream fs = new FileStream(Path.Combine(imagePath, name), FileMode.Open, FileAccess.Read) )
            {
              using(Image inputImage = Image.FromStream(fs))
              {
                using(Image outputImage = new Bitmap(inputImage))
                { 
                  using(MemoryStream stream = new MemoryStream())
                  {
                    outputImage.Save(stream, ImageFormat.Jpeg);
                    imageBytes = stream.GetBuffer();
                  }
 
                  ctx.Cache.Add(cacheKey, imageBytes, null,
                    DateTime.MaxValue, new TimeSpan(2, 0, 0),
                    CacheItemPriority.Normal, null);   
                }
              }
            }
          }
          catch ( Exception )
          {
            throw;
          }
        }
 
        ctx.Response.Cache.SetCacheability(HttpCacheability.Public);
        ctx.Response.ContentType = "image/jpg";
        ctx.Response.BufferOutput = false;
        ctx.Response.OutputStream.Write(imageBytes, 0, imageBytes.Length);
      }  
    }
    catch ( Exception )
    {
      throw;
    }
    finally
    {
      ctx.Response.End();    
    }
  }
}

Save that file as image.ashx and drop it into the correct folder. Most likely that is C:\Program Files\CruiseControl.NET\webdashboard.

image

Reports: The Results!

This is what we are passing image handler when we look at a report.

<img src="http://robz.homedns.org:8081/ccnet/image.ashx?project=c:\CodeDrop\Bombali&amp;label=17&amp;revision=108&amp;name=VisualNDependView.png" />

It can take that information and find our images:

image

Then we sit back and watch the image handler do it's thing and show us images.

image

image

Nice. By the way, UppercuT does all of this and has instructions and files that you can use that are already ready to take advantage of NDepend images in CC.NET. UppercuT also has a detailed explanation of getting set up with CC.NET.

 

kick it on DotNetKicks.com

UppercuT - Automated Builds - TeamCity Integration Coming

imageThis is a quick update to note that TeamCity is on it's way to being supported. 

I was given a patch for this and I am about verify that it works (it came from a trusted source through, so I am pretty sure it will).  You know what the greatest part of the patch was?

It was one line of code.

<property name="version.build" value="${environment::get-variable('build.number')}" if="${environment::variable-exists('build.number')}" />

We don't even need a setting to determine if the build server is CruiseControl.NET or TeamCity, just one line to look for a variable and set our build version if it exists.

With this knowledge you shall build.

 

UppercuT - Automated Builds - Getting Started Part 8 (Next Steps)

In Part 1 we downloaded or built from source control. In Part 2 we added UppercuT to our project. In Part 3 we set up the UppercuT configuration. In Part 4 we updated our reference folders if we needed to. In Part 5 we built our code successfully. In Part 6, we checked into source control. In Part 7, we  automatically ignored folders for SVN. What are the next steps to take advantage of the power of UppercuT?

The Power of UppercuT

UppercuT comes with many great features! You now have automated build goodness; why not take a look at what else you can do? Some of these features will help you better maintain your code or even do less work to get the same results.

VersionBuilder

VersionBuilder allows you to tie your DLLs back to both a build and a revision number in source control. A common problem many of us have is versioning our DLL assemblies and keeping track of what’s in production versus what’s in source control. If you rock with Subversion, UppercuT has this problem solved UppercuT automatically generates an assembly version file for you during build. All you need to do is hook every project up to it.

See more in the VersionBuilder document [http://uppercut.googlecode.com/svn/trunk/docs/VersionBuilder.doc] or at http://ferventcoder.com/archive/2009/05/21/uppercut---automated-builds---versionbuilder.aspx

Integration with Continuous Integration Server (like Team City or CruiseControl.NET)

Having automated builds with UppercuT is good, but it’s even better once you get a continuous integration server to automatically check your code out on changes and run UppercuT for you!

See more in the CruiseControl.NET Integration Document [http://uppercut.googlecode.com/svn/trunk/docs/IntegrateUppercuTWithCruiseControl.NET.doc] or at http://ferventcoder.com/archive/2009/05/21/uppercut---automated-builds---cruisecontrol.net-integration.aspx

Get samples here: http://uppercut.googlecode.com/svn/trunk/docs/Samples/CC.NET/

Implement Custom Tasks if necessary

What good is a build framework if you can’t extend it? That is why we planned a way to allow you to hook right into UppercuT at certain points with Custom Tasks.

See more in the Custom Tasks Document [http://uppercut.googlecode.com/svn/trunk/docs/CustomTasks.doc] or at http://ferventcoder.com/archive/2009/05/21/uppercut---automated-builds---custom-tasks.aspx.

ConfigBuilder

How much maintenance are you doing on configuration files? What happens when you have to update a configuration? You usually have to update it in multiple places. ConfigBuilder allows you to get away from that and only maintain a template file that looks just like the configuration file, but with pointers to environment variables.

See more in the ConfigBuilder Document [http://uppercut.googlecode.com/svn/trunk/docs/ConfigBuilder.doc] or at http://ferventcoder.com/archive/2009/05/17/uppercut---automated-builds---the-configbuilder.aspx.

DeploymentBuilder

How much maintenance are you doing on deployment batch files (if you use scripted deployments)? Would you rather maintain just one file? That is where DeploymentBuilder comes in. It allows you to maintain a template file in much the same way as ConfigBuilder.

See more in the DeploymentBuilder Document [http://uppercut.googlecode.com/svn/trunk/docs/DeploymentBuilder.doc] or at http://ferventcoder.com/archive/2009/05/19/uppercut---automated-builds---deploymentbuilder.aspx.

Other Features

More features are being added to UppercuT. Stay tuned for a roadmap of what features are expected to be in 1.0.

Resources

 

Ask Questions / Learn About Changes & New Versions

If you have questions, you want to know about new features, or you want to get more involved, feel free to join the group. http://groups.google.com/group/uppercut-users

UppercuT - Getting Started Series

Part 0 - Prerequisites
Part 1 - Get UppercuT
Part 2 - Add UppercuT to your project
Part 3 - Configure UppercuT.config
Part 4 - A note about the external tools / libraries
Part 5 - Build It!
Part 6 - Source Control / What NOT to check in
Part 7 - Setting up TortoiseSVN to Globally ignore UppercuT output folders and files
Part 8 - Next Steps

With this knowledge you shall build.

kick it on DotNetKicks.com

UppercuT - Automated Builds - Getting Started Part 7 (TortoiseSVN Global Ignore List)

In Part 1 we downloaded or built from source control. In Part 2 we added UppercuT to our project. In Part 3 we set up the UppercuT configuration. In Part 4 we updated our reference folders if we needed to. In Part 5 we built our code successfully. In Part 6, we checked into source control. This is a recommendation on automatically ignoring folders for SVN.

TortoiseSVN Global Ignore List

Because TortoiseSVN is the most commonly used client, it’s worth mentioning the Global Ignore list. You benefit when using it because you don’t have to manually exclude those files/folders that UppercuT creates.

1. Right click on anything in explorer. Select [TortoiseSVN]->[Settings].

 clip_image002_thumb[1]

2. On the General tab, in the Subversion section, you will find {Global ignore pattern:}.

 clip_image004_thumb[1]

3. Add *\build_output *\build_output\* *\code_drop *\code_drop\* SolutionVersion.cs SolutionVersion.vb to it.

4. Click {Apply}. Click {OK}.

5. This is the full ignore pattern:

*.suo *\bin *\obj *\bin\* *\obj\* *.resharper *.user _ReSharper* *.cache *.log *.vspscc *.vssscc *\build_output *\build_output\* *\code_drop *\code_drop\* SolutionVersion.cs SolutionVersion.vb

UppercuT - Getting Started Series

Part 0 - Prerequisites
Part 1 - Get UppercuT
Part 2 - Add UppercuT to your project
Part 3 - Configure UppercuT.config
Part 4 - A note about the external tools / libraries
Part 5 - Build It!
Part 6 - Source Control / What NOT to check in
Part 7 - Setting up TortoiseSVN to Globally ignore UppercuT output folders and files
Part 8 - Next Steps

With this knowledge you shall build.

kick it on DotNetKicks.com

UppercuT - Automated Builds - Getting Started Part 6 (Source Control & What NOT to Check In)

In Part 1 we downloaded or built from source control. In Part 2 we added UppercuT to our project. In Part 3 we set up the UppercuT configuration. In Part 4 we updated our reference folders if we needed to. In Part 5 we built our code successfully. Now we are ready get this into source control. Let's UppercuT our code!

 

Artifacts of the Build

UppercuT outputs some files and folders that should never be checked into source control. These are basically the same as what is in your bin directories with some differences. These folders/files should be excluded from source control.

 clip_image006_thumb[1]

build_output

The build_output folder is like the bin folder, but it’s the bin folder that puts every project in the solution’s output in this folder. Why not call it bin? We didn’t want to interfere with those projects that might have a top level bin folder.

code_drop

The code_drop folder is the nice packaging of the built application so that it is ready for deployment. Why code_drop? That’s a great question. The answer is that we had a lot of thoughts about what to call it, but in the end, code_drop seemed to make sense so we came back to it.

SolutionVersion.cs/SolutionVersion.vb

The SolutionVersion file is the file that changes with every build. It puts into it all of the common assembly elements. You can reference this file (using a link - see VersionBuilder) in every project and get the benefit of automatic versioning of your DLLs. If you are not using subversion or a continuous integration server, you can still get benefits of all of the other common elements by using the SolutionVersion file.

NOTE: A Visual Studio build will not work without SolutionVersion present (build.bat has been run at least once). Some people find it easier to go ahead and check that in on OSS projects to reduce the amount of confusion.

 

Check it In

Once we are building successfully, we need to get our changes updated in source control. NOTE: This is based on Subversion.

1. Open a commit dialog. Do not check in unversioned files. We have some files/folders that we don’t want to check in that are artifacts of the build.

 clip_image002_thumb[3]

2. We make sure {Show unversioned files} is unchecked. Click {OK}.

 clip_image004_thumb[1]

 UppercuT - Getting Started Series

Part 0 - Prerequisites
Part 1 - Get UppercuT
Part 2 - Add UppercuT to your project
Part 3 - Configure UppercuT.config
Part 4 - A note about the external tools / libraries
Part 5 - Build It!
Part 6 - Source Control / What NOT to check in
Part 7 - Setting up TortoiseSVN to Globally ignore UppercuT output folders and files
Part 8 - Next Steps

With this knowledge you shall build.

kick it on DotNetKicks.com

UppercuT - Automated Builds - Getting Started Part 5 (Build IT!)

 

In Part 1 we downloaded or built from source control. In Part 2 we added UppercuT to our project. In Part 3 we set up the UppercuT configuration. In Part 4 we updated our reference folders if we needed to. Now we are ready to build. Let's UppercuT our code!

 

BUILD IT! What You’ve Been Waiting For

 

1. Open a command line in the current folder. There is an excellent tool called StExBar that will allow you to do this by pressing {Control} + {M}.

 clip_image002_thumb1

2. Type build. Press {Enter}.

3. Now watch UppercuT in action.

 clip_image004_thumb1

 clip_image006_thumb1 

5. If your build succeeds, it’s time to check it in!

UppercuT - Getting Started Series

Part 0 - Prerequisites
Part 1 - Get UppercuT
Part 2 - Add UppercuT to your project
Part 3 - Configure UppercuT.config
Part 4 - A note about the external tools / libraries
Part 5 - Build It!
Part 6 - Source Control / What NOT to check in
Part 7 - Setting up TortoiseSVN to Globally ignore UppercuT output folders and files
Part 8 - Next Steps

With this knowledge you shall build.

kick it on DotNetKicks.com

UppercuT - Automated Builds - Getting Started Part 4 (External Libraries / Tools)

In Part 1 we downloaded or built from source control. In Part 2 we added UppercuT to our project. In Part 3 we set up the UppercuT configuration. This is a small update into where you keep your external references.  If you keep them where UppercuT defaults to, you can skip this step.

 

External Libraries/Tools

It’s important to note that not everyone keeps their references to external libraries (lib) in the same location in source control. That’s fine, but it requires a little additional work. In the configuration, you will want to edit where to find the tools UppercuT references.

1. If you are not using the same location for any item that UppercuT references in the lib folder, you will want to update the locations of those items.

2. Open UppercuT.config in your favorite editor and scroll to the bottom. Three items here are pointing to lib\tools and lib\references (based on a relative path from the BuildScripts\analyzers folder).

 

 clip_image002

3. Update those locations to where you put the items.

4. Notice if you are using NUnit, there is a line commented out. You can comment out the MbUnit line and uncomment the NUnit line.

5. The most important change is the reference location of NAnt in all of the .bat files. Right click on each of them and select [Edit] or open them in your favorite editor.

  clip_image002[1]

 6. Find the reference to nant.exe. This location is from where the bat file currently sits. Leave %DIR% on the left and update the reference location to NAnt.

 clip_image006

7. The test.bat file has 3 places to change. Make sure you change all of them.

  clip_image008

8. Close those files.

UppercuT - Getting Started Series

Part 0 - Prerequisites
Part 1 - Get UppercuT
Part 2 - Add UppercuT to your project
Part 3 - Configure UppercuT.config
Part 4 - A note about the external tools / libraries
Part 5 - Build It!
Part 6 - Source Control / What NOT to check in
Part 7 - Setting up TortoiseSVN to Globally ignore UppercuT output folders and files
Part 8 - Next Steps

With this knowledge you shall build.

kick it on DotNetKicks.com

UppercuT - Automated Builds - Getting Started Part 3 (Configure UppercuT.config)

In Part 1 we downloaded or built from source control. In Part 2 we added UppercuT to our project. Now we need to edit the UppercuT configuration. Let’s UppercuT our code!

UppercuT.config

1. Navigate to the Settings folder and open the UppercuT.config file in your favorite editor.

  clip_image002_thumb[1]

2. Take a moment to familiarize yourself with all of the options available in the configuration file.

3. Copy the name of the solution file (minus .sln).

  clip_image002[5]_thumb

4. Select the current value of the project.name property. Currently it is __SOLUTION_NAME_WITHOUT_SLN_EXTENSION__.

 clip_image004_thumb[1]

5. Paste the solution name you copied.

 clip_image006_thumb[1]

6. Find and copy the url to the project in source control (provided you have a url). Otherwise just use http://something. At the time of writing this document, the revision side of VersionBuilder only works with Subversion repositories.

 clip_image008_thumb[1]

7. Select the current value of the repository.path property. Currently it is __REPOSITORY_PATH__.

 clip_image010_thumb[1]

8. Paste the url you copied. Remember that this should be to the top level of the repository, even if you are in the trunk or a branch.

 clip_image012_thumb[1]

9. Select the current value of the company.name property. Currently it is __COMPANY_NAME__.

 clip_image014_thumb[1]

 clip_image016_thumb[1]

The solution name is MoneyQIFGenerator.sln, so we include it as the project name without the .sln extension. The repository path is not down to a trunk or a branch, but at the very top level of the repository. The company is either a company you work for or your own personal company if you are open source.

There are more parts to the configuration. There is a full explanation of the other options available here: UppercuT - Automated Builds - UppercuT.config

UppercuT - Getting Started Series

Part 0 - Prerequisites
Part 1 - Get UppercuT
Part 2 - Add UppercuT to your project
Part 3 - Configure UppercuT.config
Part 4 - A note about the external tools / libraries
Part 5 - Build It!
Part 6 - Source Control / What NOT to check in
Part 7 - Setting up TortoiseSVN to Globally ignore UppercuT output folders and files
Part 8 - Next Steps

With this knowledge you shall build.

kick it on DotNetKicks.com

UppercuT - Automated Builds - Getting Started Part 2 (Add UppercuT to Your Project)

 

In Part 1 we downloaded or built from source control. We are now ready to add UppercuT to our project. Let’s UppercuT our code!

Add UppercuT to Your Project

 

1. We open the folder at the top level of the project (usually just under trunk or a branch). Below you can see we have a project called MoneyQIFGenerator and it has no automated build love yet.

2. We already have a references folder (lib) so we are going to do something differently when bringing in UppercuT. For any existing project this could be 3rdParty, ThirdParty, References, External, lib, libs, etc. This is where you keep your external references and tools and where we will ultimately put parts of UppercuT. The remainder of the time we are going to call this third party references folder lib.

 clip_image002_thumb[1]

3. We pull up the folder where we have downloaded or compiled UppercuT.

 clip_image004_thumb[1]

4. We select everything except the lib folder. We already have a lib folder so we are going to bring the items in this folder over in pieces. If we are adding this to a brand new project we select the lib folder as well and bring it over in whole.

 clip_image006_thumb[1]

5. Select [Edit]->[Copy] in the UppercuT folder.

 clip_image008_thumb[1]

6. Go to the project folder. Select [Edit]->[Paste]. 

 clip_image010_thumb[1]

7. We should now have all of these new folders and files ready to add to source control.

 clip_image012_thumb[1]

8. If we brought over the lib folder, we can skip the next few steps. If we are adding to a project that already had a references folder, we go back to UppercuT’s folder and into the lib folder. 

 clip_image014_thumb[1]

9. Open the lib folder on the project. This could be 3rdParty, ThirdParty, References, External, lib, libs, etc. This is where you keep your external references and tools.

  clip_image016_thumb[1]

10. In the references folder (UppercuT side), copy either the MbUnit or NUnit folder over to the project’s references folder. If you already have the references to your test framework (as we do below), there is nothing to do (unless there are missing components).

 clip_image018_thumb[1] clip_image020_thumb[1]

11. In the tools folder (UppercuT side), we have NAnt and NCover. If we already have these referenced, we don’t need to copy them over. If we don’t have these referenced, bring over the entire tools folder into the lib folder. You can see that we don’t have either of these in the project, so we bring over the entire tools folder.

  clip_image024_thumb[1]clip_image022_thumb

 clip_image026_thumb[1]

12. Now we need to add all of these files to source control. If we are using TortoiseSVN, we right click in the top level folder (but not on a file, click in the white space). Select [TortoiseSVN]->[Add…].

 clip_image028_thumb[1]

13. Make sure all items are selected.

14. If you already have a build_output folder, a code_drop folder, or a SolutionVersion.cs/SolutionVersion.vb file, uncheck those entire folders and that file. You would only have these the first time if you have already tried to build. These are items we never want in source control (they are generated items).

 clip_image030_thumb[1]

15. Click {OK}.

16. The items are being staged to be committed to source control.

 clip_image032_thumb[1]

17. With Subversion, this is basically what we should see as a result.

 clip_image034_thumb[1]

UppercuT - Getting Started Series

Part 0 - Prerequisites
Part 1 - Get UppercuT
Part 2 - Add UppercuT to your project
Part 3 - Configure UppercuT.config
Part 4 - A note about the external tools / libraries
Part 5 - Build It!
Part 6 - Source Control / What NOT to check in
Part 7 - Setting up TortoiseSVN to Globally ignore UppercuT output folders and files
Part 8 - Next Steps

With this knowledge you shall build.

kick it on DotNetKicks.com

UppercuT - Automated Builds - Getting Started Part 1 (Get UppercuT)

So you've decided to UppercuT your code and you want to get started.

You are making a step in the right direction when you choose to use automated builds. As you read through this, you will see how easy it is to get into the world of automated builds. As you read through some of the other documents, you will learn just how powerful UppercuT is.

The first thing you need to do is download or pull the source to your computer and build it. 

Get UppercuT

Download

1. Head out to http://code.google.com/p/uppercut/downloads/list and download the latest.

 clip_image002

2. One thing to note, when you do download the zip file, the very first thing you will want to do (before extracting) is right click on that file and select [Properties]. On the General tab click {Unblock} if you have it. Otherwise you may have to unblock each file one at a time later.

 clip_image004

 clip_image006

3. Unzip the files. What we will need to bring into a project is in the UppercuT folder.

 clip_image008

Get the Source

1. The other way to get UppercuT is to point your favorite SVN client at http://uppercut.googlecode.com/svn/trunk/.

2. Once it has completed downloading, just click on the build.bat (or open a command line in this directory and type build).

3. Once it has completed, there is a folder called code_drop. This is one of the artifact folders of UppercuT. We will talk about that later. For now, navigate to the folder. What we will need to bring into a project is in the UppercuT folder.

 clip_image010

UppercuT - Getting Started Series

Part 0 - Prerequisites
Part 1 - Get UppercuT
Part 2 - Add UppercuT to your project
Part 3 - Configure UppercuT.config
Part 4 - A note about the external tools / libraries
Part 5 - Build It!
Part 6 - Source Control / What NOT to check in
Part 7 - Setting up TortoiseSVN to Globally ignore UppercuT output folders and files
Part 8 - Next Steps

With this knowledge you shall build.

kick it on DotNetKicks.com

UppercuT - Automated Builds - Custom Tasks

UppercuT provides hook points to custom tasks so that you can customize UppercuT without ever having to touch the files in BuildScripts. This makes it extremely easy to upgrade UppercuT versions when you keep your custom build scripts separated from UppercuT’s build scripts.

To add custom tasks, all you need to do is create them in a folder next to BuildScripts called BuildScripts.Custom.

These are the points were custom tasks are called (in order):

  • _compile.build calls BuildTasks.Custom\_compile.build just before it completes if the custom file exists (remember all of these are going back one directory, BuildTasks and BuildTasks.Custom should sit next to each other).
  • _ndepend.build calls BuildTasks.Custom\analyzers\_ndepend.build just before it completes if the custom file exists.
  • _analyze.build calls BuildTasks.Custom\_analyze.build just before it completes if the custom file exists.
  • _package.build calls BuildTasks.Custom\_package.build just before it completes if the custom file exists.
  • __master.build calls BuildTasks.Custom\__master.build just before it completes if the custom file exists (note the double underscore here).

If you add one of these files, you can call off to any custom tasks or other NAnt files you want.

What’s the best way to go about doing this? Make a copy of the task you want custom tasks with. Most of the time, people want to customize _package.build in some way.

Customize Package.Build

1. Go to the BuildScripts folder and select _package.build. Right click and select [Copy].

  Creating a custom task by starting from a task

2. Create a BuildScripts.Custom folder next to BuildScripts if one does not already exist.

  Creating the BuildScripts custom directory

3. In the BuildScripts.Custom folder, copy in the _package.build.

  BuildScripts custom directory

4. Open the newly copied file for editing. Remove all of the properties except:

<property name="dirs.current" value="${directory::get-parent-directory(project::get-buildfile-path())}" />
<property name="dirs.build" value="${dirs.current}\..\build_output" />
<property name="dirs.drop" value="${dirs.current}\..\code_drop" overwrite="false" />
<property name="app.drop.folder" value="app" overwrite="false" />

5. Remove all of the targets except for go and one that has copying in it. Change the name of the target you are keeping to something more appropriate. You can see here that I have renamed my target to add_setup_files.

<target name="add_setup_files">
  <echo message="Packaging setup files to ${dirs.drop}\app\Setup."/>
  <copy todir="${dirs.drop}\${app.drop.folder}\Setup">
    <fileset basedir="${dirs.build}\..\Setup">
      <include name="**/*.*" />
    </fileset>
  </copy>
</target>
6. In target “go”, set the depends property to just the remaining other targets in the custom packager file.
<target name="go" depends="add_setup_files" description="Packaging" />


7. This is the BuildScripts.Custom\_package.build file after our edits.

<?xml version="1.0" encoding="utf-8" ?>
<project name="Packager" default="go">
  <property name="dirs.current" value="${directory::get-parent-directory(project::get-buildfile-path())}" />
  <property name="dirs.build" value="${dirs.current}\..\build_output" />
  <property name="dirs.drop" value="${dirs.current}\..\code_drop" overwrite="false" />
  <property name="app.drop.folder" value="app" overwrite="false" />

  <target name="go" depends="add_setup_files" description="Packaging" />

  <target name="add_setup_files">
    <echo message="Packaging setup files to ${dirs.drop}\app\Setup."/>
    <copy todir="${dirs.drop}\${app.drop.folder}\Setup">
      <fileset basedir="${dirs.build}\..\Setup">
        <include name="**/*.*" />
      </fileset>
    </copy>
  </target>

</project>

8. And you can see when we call build.bat, our custom task is called!

command window showing call to custom task

 

With this knowledge you shall build.

 
kick it on DotNetKicks.com

UppercuT - Automated Builds - VersionBuilder

UppercuT comes with VersionBuilder. A common problem many of us have is versioning our DLL assemblies and keeping track of what’s in production versus what’s in source control. If you rock with Subversion, UppercuT has this problem solved. So how do you take advantage of VersionBuilder?

UppercuT automatically generates an assembly version file for you during build. All you need to do is hook every project up to it.

Notice in the same directory the solution is in, after you run build.bat, there is a file named SolutionVersion.vb or SolutionVersion.cs.

Folder Structure pointing out SolutionVersion file

Hook It Up

1. In every project in Visual Studio, you will need to create a link to that file.

  Project Structure in Solution Explorer

2. Right click on the project in Solution Explorer, select {Add}->{Existing Item…}.

  Add Existing item...

3. Read the next two steps before you do this or you may do it incorrectly. We have to create a LINK to this file, not actually add it.

4. Locate the SolutionVersion file and click ONLY to select it. This file is generated to sit next to your Solution file.

    Finding SolutionVersion

5. On the right of {Add} there is a little drop down you can click. Click on it and select [Add As Link].

    Add as Link

6. The image should have a little arrow in it when it is added.

    link to SolutionVersion.cs

7. Now remember to add this to every code project that you can.

8. Build your project in Visual Studio. You should get quite a few build errors.

9. Open every AssemblyInfo.vb or AssemblyInfo.cs file you have in the project and delete out everything except for GUID (keep it). If you have added anything here besides what is standard (strong named assemblies, etc), you will want to keep those.

  assembly only has guid

10. Next time you run build.bat, you get a revision number in your DLL.

  Version shows 0.0.0.100

11. The next time CruiseControl.NET (or at some point, other CI servers) runs a build, you get the build number in the DLL file as well.

  Build server version shows 0.0.5.101

 With this knowledge you shall build.

kick it on DotNetKicks.com

StExBar - A Great Add-on for Windows Explorer

One of the best utilities that I have been using recently is StExBar. It's a great utility that comes from Stefan's Tools ( http://tools.tortoisesvn.net/ ). From the site:

The StExBar provides many useful commands for your everyday use of Windows explorer. And you can add as many custom commands on your own as you like.

StExBar screenshot

Have you ever needed to open a console window while you were using the explorer? And to have that console already set to the directory you're showing in explorer right now? Well, StExBar provides that with one simple mouseclick. There's also a hotkey defined for this: simply press Ctrl-M to open the console.

It does a bunch of other great things as well.  Check out the images below and download here: http://code.google.com/p/stexbar/downloads/list

My Favorite Commands

Control + M: Opens command window pointing to the folder (unless network location)

Control + Shift + N: Creates new folders

Control + Shift + R: Renames all files that match a particular statement to something else

Control + Shift + H: Show system and hidden files

Rename

clip_image002

clip_image004

clip_image006

Search using the lightweight console

clip_image008

clip_image010



kick it on DotNetKicks.com

UppercuT - Automated Builds - CruiseControl.NET Integration

So now you are rolling with UppercuT, but you don’t yet have Continuous Integration (CI). You can make that happen with CruiseControl.NET (or any other CI server like TeamCity or Hudson).

This article is geared to CruiseControl.NET (CC.NET), although there will be future articles on other CI servers. This is specifically geared towards CC.NET 1.4 and above, because it takes advantage of preprocessors. First a few sideline notifications and then we'll get right into it.

 

UppercuT Compatibility with CC.NET Notice

To use UppercuT on CC.NET, you either have to install the .NET Framework SDK for 3.5 OR you can upgrade to the latest version which has a more recent version of NAnt. My recommendation is to upgrade to the latest version of UppercuT. You will get additional functionality, and it will work on CC.NET without you scratching your head. Now that was just uploaded last night, so if you are one of those that grabbed it in the last two days (or in the past), you'll want to get it again. http://code.google.com/p/uppercut/downloads/list

This is what the error looks like:

<message>             [property] Target framework changed to "Microsoft .NET Framework 3.5".</message>
<message>            </message>
<message>            BUILD FAILED</message>
<message>            </message>
<message>            INTERNAL ERROR</message>
<message>            </message>
<message>            System.NullReferenceException: Object reference not set to an instance of an object.</message>
<message>               at NAnt.Core.FrameworkInfo.get_Version()</message>
<message>               at NAnt.Core.Project.UpdateTargetFrameworkProperties()</message>
<message>               at NAnt.Core.Tasks.PropertyTask.ExecuteTask()</message>
<message>               at NAnt.Core.Task.Execute()</message>
<message>               at NAnt.Core.Project.InitializeProjectDocument(XmlDocument doc)</message>
<message>               at NAnt.Core.Project.Execute()</message>
<message>               at NAnt.Core.Project.Run()</message>
<message>            </message>

It will fail silently and you will have an interesting time figuring out why. It's because NAnt 0.86 Beta1 had a bug in it that has since been corrected.

 

CC.NET Preprocessors Side Note

Preprocessors have made CC.NET, in my opinion, one of the best products for CI. Basically you can define how you want a project structured, then to add and remove projects it is one line of code!

<cb:uppercut_svn_project projectName="Bombali" queuePriority="80" svnPath="https://bombali.googlecode.com/svn/trunk/" />

This article is not about preprocessors though. There is a really good resource for that here: http://confluence.public.thoughtworks.org/display/CCNET/Configuration+Preprocessor

 

The Configuration

<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
  <!-- http://confluence.public.thoughtworks.org/display/CCNET/Configuration+Preprocessor -->
  <!-- Common Variables -->
  <cb:define working_directory="c:\CodeBuild" />
  <cb:define drop_directory="c:\CodeDrop" />

  <!-- PROJECT STRUCTURE -->
  <cb:define name="uppercut_svn_project">
    <project name="$(projectName)">
      <workingDirectory>$(working_directory)\$(projectName)</workingDirectory>
      <artifactDirectory>$(drop_directory)\$(projectName)</artifactDirectory>
      <category>$(projectName)</category>
      <queuePriority>$(queuePriority)</queuePriority>
      <triggers>
        <intervalTrigger name="continuous" seconds="60" buildCondition="IfModificationExists" />
      </triggers>
      <sourcecontrol type="svn" autoGetSource="true">
        <trunkUrl>$(svnPath)</trunkUrl>
        <workingDirectory>$(working_directory)\$(projectName)</workingDirectory>
      </sourcecontrol>
      <tasks>
        <exec>
          <executable>$(working_directory)\$(projectName)\build.bat</executable>
        </exec>
      </tasks>
      <publishers>
        <merge>
          <files>
            <file>$(working_directory)\$(projectName)\build_output\build_artifacts\mbunit\*-results.xml</file>
            <file>$(working_directory)\$(projectName)\build_output\build_artifacts\nunit\*-results.xml</file>
            <file>$(working_directory)\$(projectName)\build_output\build_artifacts\ncover\*-results.xml</file>
            <file>$(working_directory)\$(projectName)\build_output\build_artifacts\ndepend\*.xml</file>
          </files>
        </merge>
        <email from="buildserver@somewhere.com" mailhost="smtp.somewhere.com" includeDetails="TRUE">
          <users>
            <user name="YOUR NAME" group="BuildNotice" address="yourEmail@somewhere.com" />
          </users>
          <groups>
            <group name="BuildNotice" notification="change" />
          </groups>
        </email>
        <xmllogger/>
        <statistics>
          <statisticList>
            <firstMatch name="Svn Revision" xpath="//modifications/modification/changeNumber" />
            <firstMatch name="ILInstructions" xpath="//ApplicationMetrics/@NILInstruction" />
            <firstMatch name="LinesOfCode" xpath="//ApplicationMetrics/@NbLinesOfCode" />
            <firstMatch name="LinesOfComment" xpath="//ApplicationMetrics/@NbLinesOfComment" />
          </statisticList>
        </statistics>
        <modificationHistory onlyLogWhenChangesFound="true" />
        <rss/>
      </publishers>
    </project>
  </cb:define>

  <cb:uppercut_svn_project projectName="Bombali" queuePriority="80" svnPath="https://bombali.googlecode.com/svn/trunk/" />
  <cb:uppercut_svn_project projectName="UppercuT" queuePriority="80" svnPath="http://uppercut.googlecode.com/svn/trunk/" />

</cruisecontrol>

 

Cruise Control.NET Setup

1. On the build server we are going to create two folders, CodeBuild and CodeDrop (suggestion is not the C: drive, but another drive that is much bigger).

  clip_image002_thumb[1]

2. Right click on CodeDrop and Select [Properties].

  clip_image004_thumb

3. Select the [Sharing] tab and Click on {Share this folder}. Click {OK}. NOTE: We are leaving share permissions as ReadOnly to keep anyone from making changes to the files after they are built.

  clip_image006_thumb[1]

4. You will now have the little sharing icon under it.

  clip_image008_thumb

5. In the CodeBuild folder, when CC.NET gets the latest revision of the code, it puts it there.

  clip_image010_thumb[1]

6. If we make a change to source, CC.NET will trigger off and get the latest changes to the code and put them in the CodeBuild folder.

    a. I get notified something has changed  clip_image012_thumb

    b. I open CCTray to check it out (or just hover, it will tell me what it is building).

        clip_image014_thumb

    c. I can head out to the site to check it out.

        clip_image016_thumb[1]

    d. If we are successful, the build goes green.

        clip_image018_thumb

7. In the CodeDrop folder, you get something a little different than you may have been expecting. But it's very good!

  clip_image002[7]_thumb[1]

8. What? Where’s my build? Well, let’s explore what we see here. One of these folders is named B2-R99. That stands for Build 2 Revision 99. So what you are seeing is that you get a different drop for every build!

9. In each folder I have a build, ready for deployment. And it’s read only (so someone can’t change the files)!

  clip_image022_thumb[1]

10. We’re all ready to go with this package at this revision!

 

CruiseControl.NET Build Information

On CruiseControl.NET I can get information about this current build. Test, NCover and NDepend reports for every build (NDepend provided it is licensed and installed to the proper directory on the build server)! Note: You will need to update the dashboard.config file to see all of these (coming later).

  clip_image024_thumb[1]

  clip_image002[5]_thumb[1]

With this knowledge you shall build.


kick it on DotNetKicks.com
Twitter