IgorShare Thoughts and Ideas

Consulting and Training

Archive for the ‘Workflows’ Category

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.

Advertisements

Posted in ALM, C#, Continous Integration, Source Control, TFS, Tutorials, Workflows | 1 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 »

Now I have ALL of the Microsoft developer certifications – long journey is over!!!

Posted by Igor Moochnick on 09/09/2009

Now I own the full deck of the Microsoft certifications and I can sit back and relax (beer is in order ;-). Unfortunately, in the startup world that I operate most of the time, it’s not very recognizable achievement, but it’s nice to put these logos on my presentation slide decks and, especially now, I have a very powerful bragging rights – I have ALL of the Microsoft developers certifications !!!

It was a lengthy path and, I should add, a very confusing one. It wasn’t very obvious what certification is a prerequisite to which one and, I must add, I’ve made a couple of mistakes on the road until I’ve discovered a developer’s certification map by Jorgen Thelin that put everything in order and cleared all the confusions.

ms-cert-path-mcpd_4[1]

Posted in .NET, ADO.Net, ASP.NET, C#, Community, Thoughts, WCF, Workflows, WPF | 6 Comments »

Error Handling in Workflows

Posted by Igor Moochnick on 02/09/2009

Note a great article by Matt Milner in the latest (Feb’09) MSDN about different ways of Error Handling in Workflows.

Posted in .NET, Workflows | Leave a Comment »

TechValley CodeCamp, thank you!

Posted by Igor Moochnick on 04/21/2008

This Saturday I was talking about Workflows at TechValley CodeCamp. The organizers (Andrew Badera and Griffith Townsend) did a terrific job making this happen. It’s their first CodeCamp in TechValley and I’d like to wish them more success in the future and that they’ll finally fix the CodeCamp registration site.  [ BTW: The food was way better than at Waltham CodeCamp 😆 ]

Useful links:

Presentation slides – CodeCamp_Workflows.ppsx

Presentation code – CodeCamp_Workflows.zip

Posted in C#, Presentations, Thoughts, Tutorials, Workflows | Leave a Comment »

70-504 – Congratulations to … me again ?!!!

Posted by Igor Moochnick on 04/19/2008

MCTS_WF

Just got a confirmation that I’ve passed the 70-504 TS: Workflow Foundation.

And, you can guess, I’m heading to a bar for some beers 🙂 – this becomes a habit and, at this rate, I can become an alcoholic too 😆

Posted in C#, Presentations, Thoughts, Tutorials, Visual Studio, Workflows | 2 Comments »

Albany, NY – see you there

Posted by Igor Moochnick on 04/16/2008

So, finally all my plans have crystallized and I’ll be talking in Albany, NY this weekend about the Workflows.

In this talk I’ll cover the ways you can extend your applications and projects with Workflow Foundation SDK. Use cases where the WF will give you more power and flexibility to solve you project’s problems.

I’ll be covering how you can extend the WF via creation of your own custom activities, designers and designer hosts.

 

For more information check the CodeCamp’s site: http://techvalleycodecamp.com/

See you there.

Posted in Presentations, Tutorials, Workflows | Leave a Comment »

CodeCamp (Waltham, MA) was a great success

Posted by Igor Moochnick on 04/06/2008

The last 2 days we had CodeCamp #9 in Waltham. It was a great success – 555 registered  participants (I swear it was 5 more than allowed 550). A lot of great presentations and presenters. I want personally thank the organizers and the participants.

I’ve given 4 presentations – 2 intro sessions and 2 in-depth session. Audience was great, engaging, friendly and asked a lot of good questions.

You’re welcome to download the presentations and the source code. Feel free to ask questions over the e-mail.

  1. PowerShell – extending your projects with PowerShell “To Infinity … and Beyond” (samples source code)
  2. Workflows are … not only for Business (samples source code)

I hope to see all of you next CodeCamp or during User Group meetings.

Posted in Pash, PowerShell, Presentations, Software, Thoughts, Tutorials, Workflows | 1 Comment »

Miguel Castro and Mark Dunn on the Marriage of WF and WCF

Posted by Igor Moochnick on 02/21/2008

Check out new Show #103 on DnrTv:

Miguel Castro and Mark Dunn on the Marriage of WF and WCF

Posted in Tutorials, Workflows | 1 Comment »

PowerShell Rules Engine: How-To Technical Details

Posted by Igor Moochnick on 02/15/2008

In my recent article, Marrying Workflows into PowerShell (Part 1 of 2), PowerShell Rules Engine, I’ve shown an example of how to use a Rule Set editor, shipped with Workflows Foundation, in your own application and how to evaluate rules against managed objects. Actually, PowerShell was used as a specific example of how to use this technology.

I haven’t invented anything new and this information is readily available from different public sources, but, I think, it’ll be better if I’ll explain how it works for the readers of this blog.

There are 3 simple steps to get this technology to work for you:

  1. Create and edit rule sets via the Rule Set Dialog and serialize the rules into an XML
  2. Load (deserialize) the Rule Set from an XML file
  3. Evaluate/apply the rules against your own objects

The step #1 is implemented in the ShowDialog function:

   1: public static RuleSet ShowRulesDialog(Type targetType, RuleSet ruleSetIn, string rulesFileName)
   2: {
   3:     RuleSet ruleSet = ruleSetIn ?? new RuleSet();
   4:     RuleSetDialog ruleSetDialog = new RuleSetDialog(targetType, null, ruleSet);
   5:     DialogResult dr = ruleSetDialog.ShowDialog();
   6:     if (dr == DialogResult.OK)
   7:     {
   8:         ruleSet = ruleSetDialog.RuleSet;
   9:         if (ruleSet == null)
  10:             return null;
  11:  
  12:         XmlTextWriter writer = new XmlTextWriter(rulesFileName, Encoding.Unicode);
  13:  
  14:         WorkflowMarkupSerializer serializer = new WorkflowMarkupSerializer();
  15:         serializer.Serialize(writer, ruleSet);
  16:  
  17:         writer.Flush();
  18:         writer.Close();
  19:     }
  20:  
  21:     return ruleSet;
  22: }

 

Note line #3 – if you’ll provide a valid instance of a Rule Set – the editor will allow you to edit it, if you don’t have a Rule Set, provide a new instance in the editor will fill it in with your new rules. In the line #15 the newly edited Rule Set is written (serialized) to an XML file with WorkflowMarkupSerializer.

The step #2 is implemented in the LoadRules function:

   1: public static RuleSet LoadRules(string rulesFileName)
   2: {
   3:     if (File.Exists(rulesFileName))
   4:     {
   5:         FileStream fs = new FileStream(rulesFileName, FileMode.Open);
   6:         StreamReader sr = new StreamReader(fs);
   7:         string serializedRuleSet = sr.ReadToEnd();
   8:         WorkflowMarkupSerializer serializer = new WorkflowMarkupSerializer();
   9:         StringReader stringReader = new StringReader(serializedRuleSet);
  10:         XmlTextReader reader = new XmlTextReader(stringReader);
  11:         var ruleSet = serializer.Deserialize(reader) as RuleSet;
  12:         fs.Close();
  13:  
  14:         return ruleSet;
  15:     }
  16:     return null;
  17: }

 

Note that this function is doing a reverse Rule Set deserialization with the WorkflowMarkupSerializer and returning a Rule Set instance (if everything wen right).

The last, and the most important step #3, is executed in the Run-Rules CmdLet. It evaluates the rules against each and every PSObject in the command pipeline.

   1: // Validate the rules
   2: RuleValidation validation = new RuleValidation(typeof(PSCurrentItem), null);
   3: ruleSet.Validate(validation);
   4: if (validation.Errors.Count != 0)
   5: {
   6:     foreach (ValidationError error in validation.Errors)
   7:         WriteWarning(string.Format("Validation Error: {0}", error.ErrorText));
   8: }
   9: if (validation.Errors.Count != 0)
  10:     return;
  11:  
  12: ...
  13:  
  14: var psObject = new PSCurrentItem() { CurrentItem = this.CurrentItem, Runtime = this };
  15:  
  16: // Execute the rules against the object
  17: RuleExecution execution = new RuleExecution(validation, psObject);
  18: ruleSet.Execute(execution);
  19:  
  20: if (! psObject.StopProcessing)
  21:     WriteObject(CurrentItem);

First the rule set is validated against the target type (lines #2-3), the same type used while creating the rule set in the first time (line #4 in ShowRulesDialog). Then the rules are applied to the managed object (lines #17-18). The rules can modify the object which can change the flow of the logic. In line #20 the code checks if the StopProcesing flag was set or cleared which forces the object to be written back to the command pipe or omitted.

Hope this post was educational and showed how easy it is to use the Rule Set editor in your applications.

Posted in C#, PowerShell, Tutorials, Workflows | 1 Comment »

 
%d bloggers like this: