Monday, October 1, 2007

Setting off a CC.NET build from NAnt

One of the new features in CruiseControl.NET are integration queues with priorities.  By default, all projects can execute concurrently, but sometimes, I want to have a master build execute first, then dependent builds next.  This is fairly easy to do, using the integration queues, priorities, and force build publishers.

However, I have a strange situation where I actually need to force a build from a NAnt script (don't ask).  There aren't any command-line tools to execute CCNET builds, so I couldn't use the <exec> task to accomplish this.  Instead, I'll create a custom NAnt task.  To do this, I'll need to create a new C# project and reference three key assemblies:

  • NAnt.Core.dll
  • ThoughtWorks.CruiseControl.Core.dll
  • ThoughtWorks.CruiseControl.Remote.dll

From there, it's just a matter of creating a custom task to call into the CCNET API:

[TaskName("ccnet")]
public class CCNet : Task
{
    private string _server;
    private int _portNumber = 21234;
    private string _project;

    [TaskAttribute("server", Required = true)]
    public string Server
    {
        get { return _server; }
        set { _server = value; }
    }

    [TaskAttribute("portnumber", Required = false)]
    public int PortNumber
    {
        get { return _portNumber; }
        set { _portNumber = value; }
    }

    [TaskAttribute("project", Required = true)]
    public string ProjectName
    {
        get { return _project; }
        set { _project = value; }
    }

    protected override void ExecuteTask()
    {
        RemoteCruiseManagerFactory factory = new RemoteCruiseManagerFactory();
        string url = string.Format("tcp://{0}:{1}/CruiseManager.rem", Server, PortNumber);
        ICruiseManager mgr = factory.GetCruiseManager(url);

        string proj = mgr.GetProject(ProjectName);

        mgr.ForceBuild(ProjectName);
    }
}

The custom NAnt task needs at least two pieces of information to connect to the CCNET server:

  • Server name
  • Project name

If the remoting port is different than the default (21234), I'll need to specify that as well.  Now I can execute a CCNET build with this simple NAnt task:

<ccnet server="buildserver" project="Ecommerce CI" />

I'd still rather use the integration queues, priorities, and publishers, but the NAnt task will work for me in a more complex scenario.

No comments: