IgorShare Thoughts and Ideas

Consulting and Training

Archive for December, 2010

Teaching TFS custom activity to work with the Svn, Cvs, Git and other source control command line tools

Posted by Igor Moochnick on 12/27/2010

After the SharpSvn fiasco (described in the previous post), I’ve decided temporarily put this dependency loading issue aside and, instead of running native Svn client, to use one of the command-line Svn interfaces. I’ve tried to keep the activity interface generic enough so you can configure it to use any of the available command-line source control clients (not only Svn but Cvs, Git, Mercurial, etc…)

As a first step the following 4 common and mostly changed parameters were identified:

  1. Source location (usually a Url)
  2. Destination for check-out
  3. Username
  4. Password

This list defined all the input parameters for the Svn custom activity (plus extra one that carries the the command line template):

        [RequiredArgument]
        public InArgument<string> SvnToolPath { get; set; }

        [RequiredArgument]
        public InArgument<string> SvnCommandArgs { get; set; }

        [RequiredArgument]
        public InArgument<string> DestinationPath { get; set; }

        [RequiredArgument]
        public InArgument<string> SvnPath { get; set; }

        [RequiredArgument]
        public InArgument<svncredentials> SvnCredentials { get; set; }

The rest of the activity takes care of building a command line from a provided template by replacing the placeholders with the provided parameter values and executing the external process:

namespace SvnActivityLib
{
    [BuildActivity(HostEnvironmentOption.All)]
    [BuildExtension(HostEnvironmentOption.All)]
    [Designer(typeof(SvnActivityDesigner))] 
    public sealed class SvnActivity : CodeActivity
    {
        [RequiredArgument]
        public InArgument<string> SvnToolPath { get; set; }

        [RequiredArgument]
        public InArgument<string> SvnCommandArgs { get; set; }

        [RequiredArgument]
        public InArgument<string> DestinationPath { get; set; }

        [RequiredArgument]
        public InArgument<string> SvnPath { get; set; }

        [RequiredArgument]
        public InArgument<svncredentials> SvnCredentials { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            TrackMessage(context, "Starting SVN action");

            string destinationPath = context.GetValue(this.DestinationPath);
            string svnPath = context.GetValue(this.SvnPath);
            string svnToolPath = context.GetValue(this.SvnToolPath);
            string svnCommandArgs = context.GetValue(this.SvnCommandArgs);
            SvnCredentials svnCredentials = context.GetValue(this.SvnCredentials);

            string svnCommand = Regex.Replace(svnCommandArgs, "{uri}", svnPath);
            svnCommand = Regex.Replace(svnCommand, "{destination}", destinationPath);
            svnCommand = Regex.Replace(svnCommand, "{username}", svnCredentials.Username);
            TrackMessage(context, "svn command: " + svnCommand);

            // Never reveal the password!
            svnCommand = Regex.Replace(svnCommand, "{password}", svnCredentials.Password);

            if (File.Exists(svnToolPath))
            {
                var process = Process.Start(svnToolPath, svnCommand);
                if (process != null)
                {
                    process.WaitForExit();
                    process.Close();
                }
            }

            TrackMessage(context, "End SVN action");
        }
    }
}

To provide a nice UI element with the Svn logo, a custom designer was added (note the “Designer” attribude on top of the SvnActivity class). Here is the designer’s XAML:

<sap:ActivityDesigner x:Class="SvnActivityLib.SvnActivityDesigner"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
    xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    Collapsible="False" 
    ExpandState="False" 
    UseLayoutRounding="False" 
    d:DesignHeight="22" d:DesignWidth="200" mc:Ignorable="d">
    <sap:ActivityDesigner.Icon>
        <DrawingBrush>
            <DrawingBrush.Drawing>
                <ImageDrawing>
                    <ImageDrawing.Rect>
                        <Rect Location="0,0" Size="16,16" ></Rect>
                    </ImageDrawing.Rect>
                    <ImageDrawing.ImageSource>
                        <BitmapImage UriSource="Resources\Subversion.png" ></BitmapImage>
                    </ImageDrawing.ImageSource>
                </ImageDrawing>
            </DrawingBrush.Drawing>
        </DrawingBrush>
    </sap:ActivityDesigner.Icon>
 </sap:ActivityDesigner>

 

The Build Template, hosting this activity, will requre the following addition to it’s Arguments list:

image

as well as a couple of extra entries in the metadata:

image

After the activity was build and checked in to the CustomActivities location (see the previous post) I was able to configure new values in the build definition:

image

Notice the “Svn arguments” parameter that provides a command line template.

In the build definition metadata I’ve configured only 2 parameters to appear during the build submission (SvnPath and SvnCredentials) so they can be configured in both places (during the editing and the submission), but the rest of the parameters are configured to appear only during the build editing step. This allows any developer to provide his own “patch” source location and his own credentials during the build submission. If your security model doesn’t allow this – make sure to modify the metadata section accordingly.

This is it for now – I’ll talk about the whole credentials mystery in the next post.

Posted in ALM, C#, Continous Integration, Source Control, TFS, Tutorials, Workflows | 1 Comment »

Visual Studio ALM Community can become a reality–Please vote !!!

Posted by Igor Moochnick on 12/27/2010

If you’re interested in the ALM tools, especially on the Microsoft environment, and you have questions or you want to share your ideas with the community – here is your chance! 

Go to the Stack Exchange Area 51 and vote for the Visual Studio ALM community site.

image

Posted in ALM, TFS | Leave a Comment »

Can TFS be useful if the sources are in Subversion (SVN)? Or how to run integration and nightly builds on TFS from SVN?

Posted by Igor Moochnick on 12/26/2010

This is the question that I’ve been asked multiple times during my Microsoft ALM tools presentations and trainings. So I’ve decided to post a series of articles that will show the path that we had to walk to teach the TFS to run our builds from SVN.

This will be helpful for you especially if you have a similar configuration – source code location in SVN but the development tools are still Visual Studio and MSBuild. The projects are combined into the solution files (.sln), etc… I hope you got the picture.

[Disclaimer: To continue you should be familiar with the TFS build workflow and the basics of the TFS administration]

After quite some search I was unable to find any activities that enable the communication with the SVN (except for a custom MSBuild Svn task) so I’ve decided to build my own…

Read the rest of this entry »

Posted in C#, TFS, Tutorials, Workflows | 9 Comments »

Team Development with TFS Guide

Posted by Igor Moochnick on 12/25/2010

A bit outdated but still helpful in many ways is the Patterns & Practices Team Development with TFS Guide (2007)

Posted in ALM, TFS | Leave a Comment »