Navigation

Search

Categories

 

On this page

[Build Knowledge] Promoting your build
[DDD6] Testing Your Applications With MbUnit with Ben Hall
[DDD6] Dynamic Languages on .NET with Michael Foord
[DDD6] Grok Talks
[DDD6] Microsoft Codename "Astoria" with Guy Smith Ferrier
[DDD6] Introduction to Silverlight 1.1 with Chris Hay
[DDD6] Why IronRuby? with Dave Verwer
Comments working now
[Build Knowledge] Versioning
Where's all the posts?
Google Reader Minimalistic

Archive

Blogroll

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 8
This Year: 2
This Month: 0
This Week: 0
Comments: 6

Sign In
Pick a theme:

 Wednesday, December 05, 2007
Wednesday, December 05, 2007 12:14:16 PM (GMT Standard Time, UTC+00:00) ( )

If there’s one thing that you should ask your self across everything you do it’s “How can we test this”. Deployments are often overlooked as so infrequent that it doesn’t need to be fully tested or automated. I’ll show you how to setup a simple promotion system using CruiseControl.Net and NAnt.

Here are the symtoms that you need to improve how your deploying your applications.

  1. You can’t remember if you deployed some fix or feature and have to check to see if you did.
  2. You don’t remember when you actually deployed but remember it was around march last year.
  3. You’re the only person that knows how to deploy.
  4. You’ve accidently deployed a the application built in debug.

What you’ll need

  1. Download and install CruiseControl.Net
  2. Read thru the last article where we covered versioning with NAnt and CruiseControl.Net

You can download the code from google code at

http://sleepoverrated.googlecode.com/svn/

If you have a Subversion Client like TortoiseSVN then you can just check out all the code.

The Enviroments

BK02Enviroments

We’ll be using three server enviroments here, each one could be a web server or a windows form or anything but today it’ll just be a command line application. The Application prints its version number and the enviroment name from a config file. Hopefully after we’re thru here you can scale this system out to whatever your needs are.

NAnt Configuration

We will need two builds one for Current (our Continuous Integration) and one for Development. The only difference is that Current is compiled in debug and development is compiled in release mode. Its good practise to start compiling in debug on your Continuous Integration enviroment so that you can generate Code Coverage reports using NCover.

The only promotion we’re showing here is for staging since you should really seperate your promotion to live into another process to prevent accidental promotions.

buildknowledge.build

This is a variation of the last articles build file.

The main differences are:

  1. There’s a debug property so we can set the compile mode
  2. the expand.template.file lets us generate a config file by replacing tokens in config\app.config.template
  3. deploy.copy lets us copy a whole directory of development to staging
  4. include buildfile lets us add more tasks specific to our different enviroments in the second build file

The actually targets we’ll be running are in the next NAnt file so these are just lower level tasks

<?xml version="1.0" encoding="utf-8"?>
<!--EXTERNAL_PROPERTIES: target.dir;source.dir;AppConfig.EnviromentName;AppConfig.Directory-->
<project name="BuildKnowledge" default="current">    
    
    <!-- add tasks in from the enviroments build file -->
    <include buildfile="buildknowledge.enviroments.build"/>
    
    <!-- initialize properties -->
    <property name="debug" value="false" />
    <property name="target.dir" value="build" />
    <property name="source.dir" value="" />
    
    <target name="init" description="clean out build dirs">
        <delete dir="build" />
        <mkdir dir="build" />    
        <delete dir="${target.dir}" />
        <mkdir dir="${target.dir}" />    
    </target>
    
    <target name="asminfo" description="generating the AssemblyInfo.cs">
        <if test="${property::exists('CCNetLabel') == false}">
            <property name="CCNetLabel" value="0.0.0.1" />
        </if>
    
        <asminfo output="build\AssemblyInfo.cs" language="CSharp">
            <imports>
                <import namespace="System" />
                <import namespace="System.Reflection" />
                <import namespace="System.EnterpriseServices" />
                <import namespace="System.Runtime.InteropServices" />
            </imports>
            <attributes>
                <attribute type="ComVisibleAttribute" value="false" />
                <attribute type="CLSCompliantAttribute" value="true" />
                <attribute type="AssemblyVersionAttribute" value="${CCNetLabel}" />
                <attribute type="AssemblyTitleAttribute" value="Build knowledge - Hello World" />
                <attribute type="ApplicationNameAttribute" value="BuildKnowledge" />
            </attributes>
            <references>
                <include name="System.EnterpriseServices.dll" />
            </references>            
        </asminfo>
    </target>
        
    <target name="compile" depends="init,asminfo" description="compiling all the code in the src dir">
        <csc output="${target.dir}\${project::get-name()}.exe" target="exe" debug="${debug}">
            <sources basedir="src">
                <include name="**/*.cs" />
                <include name="../build/AssemblyInfo.cs" />
                <exclude name="**/AssemblyInfo.cs" />
            </sources>
        </csc>    
    </target>
    
    <target name="deploy.copy" description="copy promotion of one build to the next enviroment">
        <if test="${directory::exists(target.dir) == false}">
            <mkdir dir="${target.dir}" />
        </if>
        <copy todir="${target.dir}" overwrite="true">
            <fileset basedir="${source.dir}">
                <include name="**/*" />
                <exclude name="*.config" />
            </fileset>
        </copy>
    </target>
    
    <target name="load.settings" description="load all the enviroment settings">
        <if test="${file::exists('config\' + properties)}">
          <echo message="Loading ${properties}" />
          <include buildfile="config\${properties}" />
        </if>
    </target>
    
    <target name="expand.template.file" description="replace the tokens in the template file">
        <copy file="config\${target}.template" tofile="config\${target}" overwrite="true" >
            <filterchain>
                <replacetokens>    
                    <token key="AppConfig.EnviromentName" value="${AppConfig.EnviromentName}" />
                </replacetokens>
            </filterchain>
        </copy>    
    </target>
    
    <target name="deploy.config" description="create the config file and deploy it">
        <property name="target" value="app.config" />
        <call target="expand.template.file" />
        <copy file="config\${target}" tofile="${AppConfig.Directory}\${project::get-name()}.exe.config" />
    </target>
</project>

buildknowledge.enviroments.build

Here’s our enviroments, each one will used by CruiseControl.Net as a different project. We have a file for each enviroment with all the settings we’ll be using. This lets you quickly change the connectionstring but today all we’re using it for is the the name of the Enviroment and its directory.

  1. Current – debug compile, generate config
  2. Development – release compile, generate config
  3. Staging – copy development, generate config
<?xml version="1.0" encoding="utf-8"?>
<project name="BuildKnowledgeEnviroments">    
    
    <target name="current" description="starting Continous Integration build">        
        <property name="properties" value="current.enviroment.xml" />
        <call target ="load.settings" />

        <property name="debug" value="true" />
        <property name="target.dir" value="${AppConfig.Directory}" />
        <call target="compile" />
        
        <call target="deploy.config" />
    </target>

    <target name="development" description="starting Development build">        
        <property name="properties" value="development.enviroment.xml" />
        <call target="load.settings" />
        
        <property name="debug" value="false" />
        <property name="target.dir" value="${AppConfig.Directory}" />
        <call target="compile" />

        <call target="deploy.config" />
    </target>
    
    <target name="staging" description="starting Staging promotion">
        <property name="properties" value="development.enviroment.xml" />
        <call target="load.settings" />
        <property name="source.dir" value="${AppConfig.Directory}" />

        <property name="properties" value="staging.enviroment.xml" />
        <call target ="load.settings" />
        <property name="target.dir" value="${AppConfig.Directory}" />

        <call target="deploy.copy" />
        
        <call target="deploy.config" />
    </target>
</project>

app.config.template

This is where we’re generating out app.config from, the @AppConfig.EnviromentName@ is the token that we’re looking for in the expand.template.file task.

<?xml version="1.0"?>
<configuration>
    <appSettings>
        <add key="EnviromentName" value="@AppConfig.EnviromentName@"/>
    </appSettings>
</configuration>

development.enviroment.xml

With the load.settings task we load in our enviroment settings files here’s the one for the development enviroment. It gives us the properties ${AppConfig.EnviromentName} and ${AppConfig.Directory} which you’ll see being used in the NAnt files.

<?xml version="1.0"?>
<properties>
    <property name="AppConfig.EnviromentName" value="Development" />
    <property name="AppConfig.Directory" value="deploy\development" />
</properties>

CruiseControl.Net Configuration

The next step is in the ccnet.config we have a different project for each enviroment and the things to notice here are

  1. Both Development and Staging are using the Remote Project Labeller to take the version number from the previous build enviroment. So Development uses Currents version number and Staging uses Developments version number. We use some trickery here because actually its still a local project but its using the tcp connection to talk to itself.
  2. Each project is using the same build file but its pointing at a different target from our enviroments file.
<cruisecontrol>
    <project name="BuildKnowledge Current">
        <tasks>
            <nant>
              <executable>C:\code\sleepoverrated\02_Build_Knowledge-Promoting_Builds\tools\nant\bin\NAnt.exe</executable>
              <baseDirectory>C:\code\sleepoverrated\02_Build_Knowledge-Promoting_Builds</baseDirectory>
              <nologo>false</nologo>
              <buildFile>buildknowledge.build</buildFile>
              <targetList>
                <target>current</target>
              </targetList>
              <buildTimeoutSeconds>1200</buildTimeoutSeconds>
            </nant>
        </tasks>
        <labeller type="iterationlabeller">
            <prefix>1.0</prefix>
            <duration>2</duration>
            <releaseStartDate>2007/11/24</releaseStartDate>
            <separator>.</separator>
        </labeller>            
    </project>
    
    <project name="BuildKnowledge Development">
        <tasks>
            <nant>
              <executable>C:\code\sleepoverrated\02_Build_Knowledge-Promoting_Builds\tools\nant\bin\NAnt.exe</executable>
              <baseDirectory>C:\code\sleepoverrated\02_Build_Knowledge-Promoting_Builds</baseDirectory>
              <nologo>false</nologo>
              <buildFile>buildknowledge.build</buildFile>
              <targetList>
                <target>development</target>
              </targetList>
              <buildTimeoutSeconds>1200</buildTimeoutSeconds>
            </nant>
        </tasks>
        <labeller type="remoteProjectLabeller">
            <project>BuildKnowledge Current</project>
            <serverUri>tcp://localhost:21234/CruiseManager.rem</serverUri>
        </labeller>            
    </project>    
    
    <project name="BuildKnowledge Staging">
        <tasks>
            <nant>
              <executable>C:\code\sleepoverrated\02_Build_Knowledge-Promoting_Builds\tools\nant\bin\NAnt.exe</executable>
              <baseDirectory>C:\code\sleepoverrated\02_Build_Knowledge-Promoting_Builds</baseDirectory>
              <nologo>false</nologo>
              <buildFile>buildknowledge.build</buildFile>
              <targetList>
                <target>staging</target>
              </targetList>
              <buildTimeoutSeconds>1200</buildTimeoutSeconds>
            </nant>
        </tasks>
        <labeller type="remoteProjectLabeller">
            <project>BuildKnowledge Development</project>
            <serverUri>tcp://localhost:21234/CruiseManager.rem</serverUri>
        </labeller>                
    </project>        
</cruisecontrol>

See it in action

Now lets see how well this works when we’re actually using it.

Building Current

since we’re not using the sourcecontrol block in CruiseControl.Net we’ll have to forcebuild the Current project but you should set it up to build everytime you check something in.

So select Current and start a force build and the version numbers start to increase just like last time.

BK02CCTray02

Checking the directory deploy\current you can see the new files we just generated. You’ll notice that here we have a pdb file because we compiled in debug.

BK02Files00

Now if we run this build we can see that its got the correct version number and its using the correct configuration file that we generated.

BK02Run01

Building Development

Now when we do a force build on Development we build a new release from code. If we were under source control it would be the latest version so there is the possibility of building while the code is being updated. If that happens you could always just rebuild development again. You could use the modificationDelaySeconds element on the project block in ccnet.config to setup a delay on building.

BK02CCTray03

If we look in the deploy\development directory we can quickly see that we’ve built in release mode because we’re missing the pdb.

BK02Files01

Running the app we can see that its using the right configuration file.

BK02Run02

Building Staging

Finally we do a force build on staging and that will copy over the last build of development and generate the config file. There’s also been some builds on Current but that won’t affect our promotion to staging. Another thing to notice is that you have the Last Build Time to quickly check the last time you deployed to staging. If you use the CruiseControl.Net web dashboard you can even see the log of all the promotions you’ve done, that way you never need to wonder what versions where or if someone did a promotion while you were off sick.

BK02CCTray04

Running the app we can see that its using the right configuration file.

BK02Run03

Comments [0] | | # 
 Sunday, November 25, 2007
Sunday, November 25, 2007 2:28:06 AM (GMT Standard Time, UTC+00:00) ( )

Ben Hall

Gallio Test Platform allows for multiple test frameworks to run thru the one platform
NUnit is a subset of MBUnit so you can just replace NUnit with MBUnit and not have to change code
Indentity Increments happen even after rollbacks
DBCC CHECKIDENT (Orders,RESEED,0)
IOC thru a property and not just in the constructor
[ExpectedArgumentNullException] passes only if there was a NullException

ForEachTest,DataFixture,ResourceXmlDataProvider
loads in a XML file with the test data
DataType = typeof(Data) in the foreach will give you intellisense (I blinked on the first example and didn't see that it didn't have it in the first place)
CustomAssertions
Watin is just like NUnitASP is actually maintained
good examples of open source projects running MBUnit are subsonic,castle, dasblog

Thanks for the TShirt Ben, I’m going to have to go thru your blog to find the new features in v3, I know theres mutliple Assertion Failures at least.

Comments [0] | | # 
Sunday, November 25, 2007 2:15:45 AM (GMT Standard Time, UTC+00:00) ( DDD6 )

Michael Foord
Resolver a financial tool written in IronPython
IronPython supports "from namespace import *" like java does
Magic Methods are dynamically interpretted like __init
dynamic typing and duck typing
Easy to Test because of monkey patching,mocking, no compile
late binding
variables are just references to actual memory

x = 1  so x = 1
y = x  so x = 1, y = 1
x = 2  so x = 2, y = 1

"import clr" brings in type methods
python used in youtube, google
stackless python for Eve online
byte code compiled like c#
_name means you shouldn't mess with it but its not protected
self equivalent to this
DLR Languages include VbX,Vista Smalltalk, managed JS, IronLUA, IronLisp,IronRuby,IronPython 
DLR Console (uses silverlight 1.1 alpha)
can use python code mixed with other DLR languages and have access to the same variables
Web IDE
Multiline strings are enclosed with triple quotes """
*args, **keywargs  - dictionary??

Comments [0] | | # 
Sunday, November 25, 2007 1:58:09 AM (GMT Standard Time, UTC+00:00) ( )

Gordon Mackie – releasable Web Controls

Make your properties appear cleanly in the Properties panel
Description Attribute on Properties
Use a Category Attribute or the Property will end up in the Misc Category
Browsable(false) Attribute keeps the Property from showing in the Property Panel
ToolboxBitmap Attribute lets you have an icon for your control
*add the bitmaps in a subfolder and set them to embedded resourse files
*add an empty code file to force compilation in visual studio
DefaultValue Attribute lets you use Reset in the context menu for the control in designer
Setup a method to reset to get around literal Default values
bool ShouldSerializeMyPropertyName //where MyPropertyName is your property
void ResetMyPropertyName
Default Event is the double click in designer
ToolboxItemFilter Attribute lets you show under contexts
Bindable Attribute avoid unneccissary binding, bind on change
Refresh Properties All - recalcalutes all dependant properties
generate documentation with sandcastle
SDK tools to register and install tools
TypeConverters,TypeEditors

Abid Quereshi - Story Based Estimating

Stacey Diagram showing predictability
velocities are good for hard to predict scenarios
must indicate Return on Investment per story
Each story has a Priority, Time Cost in Units, Client Value
Scooby Doo Respose to estimating "I don't know"

Guy Smith Ferrier - Why Extension Methods will rule the world

(this RegionInfo regioninfo)
Extension methods are public, static, have the Extension Attribute (or a this)
could inherit Extension in 2.0 but it won't compile in 2.0, but it will run if you compile it on the 3.5 compiler targetted at the 2.0 runtime
web sites compile at runtime so you need 3.5 for extension methods
They get around sealed classes, the work of the devil
Great if you don't own all the source code your using.

Alex Mackey - Development in Dubai

issues with unicode,date format, date display, db collation, text flow
Don't assume anything
Names are difficult to format there's more than just first and last names
working hours change during holy week and there's different holidays
icons and images mean different things
racial information won't be volunteered
photos don't help much when women were head coverring
server hosting is problematic due to climate
export restrictions
you can be barred from leaving Saudi Arabia if you have a local disagreement outstanding
health and safety issues in the workplace
equipment will always get delayed in customs
Dell in the UAE are slow
printers have different catridges there
fax is preferrable because the post is slow
staffing problems with people going native and getting frustrated with being away
skype.com is blocked but not the actual service

Ben - Powershell

lists are actually objects and are querible
you can pipe on top of pipes
export-csv,import-csv,format-table

Peter Ibbotson - Reflection

Store ProperyInfo and reference instead of looking it up each time
Setup a delegate of GetGetMethod() and reference that for a large speed up
if its a field you need to use dynamic methods
Comments [0] | | # 
Sunday, November 25, 2007 1:21:22 AM (GMT Standard Time, UTC+00:00) ( )

Guy Smith Ferrier

Astoria is a web service provider that lets you serialize your entities out to the client as JSON or XML

client side data
Popfly is microsoft mash up engine
his .net internationalization book
astoria.mslivelabs.com
astoria was the first RESTful web service
May 2007 CTP, Dec 2007 CTP, Beta 1 Q108, RTM mid 2008
doesn't work with the RTM... back to Beta 2
there was a slide with the requirements for an install
its a protocol and an extensible WCF service
builds on top of HTTP for tunneling, URI Protocol
security is coming in the future but theres no cross domain support right now and you can use forms/windows authentication
works well with the Entity Framework
Northwind.svc/Customers!key
has a query language in the url that supports where,order by, paged results
Dec 2007 CTP will turn of security by default to prevent database dumps thru Astoria
theres a WSDL like page on the root node using $sys_getedmdata in the Sept CTP and $metadata in Dec CTP
JSON supported on all versions (can eval easily in js)
can use HTTP,Remoting,COM because its part of the WCF
could use remoting in silverlight via partial trust in 3.5
ADO.Net Entity Model is a .Net version of DDL
supports accees to Stored Procedures
"it" is equivalent to this in the Entity Framework
can add custom methods to the URI
can access astoria straight from a web request so that we can support mixed enviroments
Astoria client library handles querying and mapping
WebDataContext,WebDataQuery
WebDataDen.exe will generate the proxy classes for us
runs the IQueriable interface so it can deal with anything thru LINQ
support for scalar returns and better concurrency coming in the future

Thanks Guy

Comments [0] | | # 
Sunday, November 25, 2007 12:58:49 AM (GMT Standard Time, UTC+00:00) ( )

Chris Hay

Interactions (using c# behind XAML) are new to 1.1
windows mobile will be supported in the future (here's hoping android too)
Silverlight 1.1 will hopefully ship in summer 2008
1.1 doesn't work with Visual Studio 2008 RTM so use Beta2 until the upcoming Silverlight 1.1 CTP refresh
"Add Silverlight Link" on a web site doesn't copy silverlight.js into your project
you can't edit and continue with a silverlight project you have to recompile
There's no Global styling yet
lots of XAML demos
TransformGroup allows you to do multiple transforms
can't group shapes like WPF so you have to stick your shapes in a canvas instead
no content support like WPF yet
blend 1.0 is for WPF only so use the blend beta instead
Silverlight Pad
there's no 3D acceleration with silverlight so you can work with multiple platforms (why not use an OpenGL wrapper on *nix)
all 3D is run off CPU power
Demos sounds (I was just telling a friend how embedded midi was going to make a come back)

Thanks Chris I didn’t have many notes on this one since there were a lot of XAML demos, too bad I missed the second session.

Comments [0] | | # 
Sunday, November 25, 2007 12:39:59 AM (GMT Standard Time, UTC+00:00) ( )

Dave Verwer

Ruby had the first beta in 1995

Iron Ruby is branched from 1.8.x branch of ruby modulo
DLR is just a layer on top of the CLR, still compules to IL
IronRuby is a blind implementation for clean IP
ruby bridge by john lam was an early use of the CLR in Ruby
the DLR came out of IronPython work
IronRuby has two developers working on it at microsoft
rubyforge subversion repository is a mirror of  the internal microsoft codebase
you can run regular ruby code in IronRuby

Optional Punctuation
semi colons, returns, braces, etc.
you can determine which puntuation you need to make your code readable
immutable string declarations are done like :init which is the string "init"
immutable strings are never disposed

Syntactic sugar
Optional Punctuation makes Domain Specific Languages more forgiving for syntax and easier to write
Sigils prefixing variable names to add description
Sigils include local, $global, @instance, @@class, Constant
sigils determine scope and are optional
ruby strongly typed but can redeclare vars
shorthand Range.new(1,100) 0..100
%w(words in an array) will create an array that is seperated by spaces
using an immutable string as a hashtable key can cause collisions
puts var unless x.nil?  this will handle null cases
strings can be single or double quotes and nest the other type without using escape characters (when its mixed you need them though)
theres no character type natively but you can use the .Net Char type
big numbers can be assigned dynamically you don't need to worry about exceeding the maximum value
no native decimal type support but you can use the .net decimal type
can alias methods on a class level so you don't have to program in american
blocks in ruby are lambda methods,anonymous delegates in c# and closures in js
core language contruct - heavy use of delegates
there are no for loops you just use the times block

a for loop
10.times do {print "Hello"}   this print Hello 10 times

a foreach loop
["a","b"].each do |letter|
  puts letter
end

file.each_line do |line|
  line =~ /regex/
end

a try catch
begin
  ...
ensure
  ...
end

yield keyword exists like c#
=== is the match operator and compares as well as it can

mixed matching in case statements
case i
  when MyClass
    ...
  when 1..100
    ...
  when /^[a-z]*$/
    ...
end

Mixins
like c# extension methods
String.module_eval do

you can redefine a class to override or add a mixin

  class String
    def capitalize_all
   ...
 end
  end
 
  class String
    undef length
  end
  
Linguistics library in ruby (blew my mind, not hard to do just nice to have done for you already)
 
individually extend instances of objects

in.extend(JPEGMethods)  

class ReverseString
  def method_missing(method_name)
    ...
  end
end

method_missing is used to do dynamic querying of database based on what the current class is and that its trying to do a find
 
customer.find_by_email_or_name

this makes intellisense a hard problem
naming is underscore seperated and lowercase
name mangling allows the CLR namespaces to be available with Ruby naming conventions

Thanks Dave

Comments [0] | | # 
 Sunday, November 18, 2007
Sunday, November 18, 2007 10:14:47 AM (GMT Standard Time, UTC+00:00) ( )
I just realized comments weren't working, but they are now so go for it.

Technorati Profile
Comments [0] | | # 
 Saturday, November 17, 2007
Saturday, November 17, 2007 7:13:28 PM (GMT Standard Time, UTC+00:00) ( )

Today I’ll show you how to use NAnt and Cruise Control.Net to Version your application.

What you’ll need

  1. NAnt A .Net Build tool. We’re going to use this to compile our Hello World Application and set the version number.
  2. Cruise Control.Net A Continious Integration Server that lets us start NAnt and makes our version number.

Our Application

Theres nothing much to our application it just shows the Assembly Version at command line.

using System;
using System.Reflection;

namespace BuildKnowledge.CmdLine
{
  class Program
  {
    static void Main(string[] args)
    {
      Console.Out.WriteLine("Hello World v" + Assembly.GetExecutingAssembly().GetName(false).Version);
    }
  }
}

NAnt Build file

Lets look at the build file

<?xml version="1.0" encoding="utf-8"?>
<project name="BuildKnowledge" default="compile"

  <target name="init">
    <delete dir="build"
/>
    <
mkdir dir="build"
/>
  </
target
>

  <target name="asminfo">
   
<if test="${property::exists('CCNetLabel') == false}">
     
<
property name="CCNetLabel" value="1.0.0.1" />
   
</
if>
   
<
asminfo output="build\AssemblyInfo.cs" language="CSharp">
     
<
imports>
       
<
import namespace="System" />
        <
import namespace="System.Reflection" />
        <
import namespace="System.EnterpriseServices" />
        <
import namespace="System.Runtime.InteropServices" />
      </
imports>
      <attributes>
        <attribute type="AssemblyVersionAttribute" value="${CCNetLabel}" />
        <
attribute type="AssemblyTitleAttribute" value="Build knowledge - Hello World" />
        <
attribute type="ApplicationNameAttribute" value="BuildKnowledge" />
      </
attributes>
      <
references>
        <
include name="System.EnterpriseServices.dll" />
      </
references>
    </
asminfo>
  </
target>

  <target name="compile" depends="init,asminfo">
    <
csc output="build\${project::get-name()}.exe" target="exe" debug="false">
      <
sources basedir="src">
        <
include name="**/*.cs" />
        <
include name="../build/AssemblyInfo.cs" />
        <
exclude name="**/AssemblyInfo.cs" />
      </
sources>
    </
csc>
  </
target>

</project>

This is the BuildKnowledge.build file that will run our build. Here’s the steps we’re taking

  • [init] Create a directory called build
  • [asminfo] Generate the AssemblyInfo.cs
  • [compile] Compile BuildKnowledge.exe

The important thing to see is CCNetLabel which is a property that CCNet is going to send down to the NAnt task. This is called an Integration Property and there are additional properties for things like the build time just check the list.

Cruise Control .Net Configuration

Once you’ve installed cruise control you’ll want to update ccnet.config to add this project. You’ll need to update the nant task with the correct paths to where your files are located. In an actual setting we’d actually have a sourcecontrol block that automatically triggers the build and updates the working copy on the build server. For now we’ll just trigger the build manually which isn’t truely Continious Integration but it’ll work for this example. The Labeller Block is where we come up with the version number for the assembly and it will show up on Cruise Control.Net and it will be sent down to NAnt.

<cruisecontrol>
  <
project name="BuildKnowledge Current">
    <
tasks>
      <
nant>
        <
executable>C:\nant\bin\NAnt.exe</executable>
        <
baseDirectory>C:\code\BuildKnowledge</baseDirectory>
        <
nologo>false</nologo>
        <
buildFile>buildknowledge.build</buildFile>
        <
targetList>
          <
target>compile</target>
        </
targetList>
        <
buildTimeoutSeconds>1200</buildTimeoutSeconds>
      </
nant>
    </
tasks>
    <
labeller type="iterationlabeller">
      <
prefix>1.0</prefix>
      <
duration>2</duration>
      <
releaseStartDate>2007/11/24</releaseStartDate>
      <
separator>.</separator>
    </
labeller>
  </
project>
</
cruisecontrol>

The End Result

Once you have everything setup you’ll need to

  1. Start up server\ccnet.exe to start CCNet in where you installed CCNet (or you can start the service).
  2. Install cctray\cctray.exe and add the BuildKnowledge Current project from your localhost.
  3. Force Build the project
  4. Run our BuildKnowledge.exe in the build folder

Build version

Thats all you have to do to add version numbers I hope you’ve gotten something out of this, we’ll be coverring more advanced topics next time.

Download the code: BuildKnowledge01.zip (4 KB)

Comments [1] | | # 
 Wednesday, November 14, 2007
Wednesday, November 14, 2007 5:00:18 PM (GMT Standard Time, UTC+00:00) ( )
So I finally moved over to actually blogging software but you might be wonderring where all the posts went to. Don't worry they're still around and I'm still posting in there.

Go checkout Sleepoverrated Stream via [Tumblr]

You can currently see it in the right hand nav but its not that obvious so I'll fix that in the upcoming site design.

Comments [0] | | # 
 Tuesday, November 13, 2007
Tuesday, November 13, 2007 9:56:27 PM (GMT Standard Time, UTC+00:00) ( )

Here’s a greasmonkey script I created to let you use google reader in full screen that has since been featured Greasemonkey script at LifeHacker.

In order to get access to the settings and search you can toggle back to the normal layout by pressing W.

If you have anything you’d like added please add a comment, I’ve heard it works well with Better GMail when displaying Google Reader on the same page.

Download at User Scripts

Install Greasemonkey

Keyboard shortcuts that come in handy are

w - toggle fullscreen (shows search bar again)

g t - go to tag
g u - go to subscription
g s - go to starred items

j - next item
k - prev item
s - star item

u - toggle left sidebar

Comments [4] | | #