# Monday, 26 January 2015

Checkout this excellent article by Mark Rendle on running ASP.NET 5 with Linux and Docker.

http://blog.markrendle.net/fun-with-asp-net-5-and-docker/?utm_content=buffer75e54&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer



.
Tags:

Monday, 26 January 2015 10:44:30 (GMT Standard Time, UTC+00:00)  #    Comments [0]


# Thursday, 22 January 2015

If you have been keeping up to date with Visual Studio 2015 news. You may have noticed that Microsoft has started adding touch support to Visual Studio 2015. I tried it out on my iPad yesterday and it seems to work quite nicely. How did I use Visual Studio 2015 on my iPad you may ask? Just install Microsoft's Free RDP client for iPad and connected to an Azure VM with VS 2015 installed. It works quite nicely and supports gestures such as pinching to zoom and selecting text with your finger. You can also use the scroll bar to scroll down with your finger.

VS2015Ipad

I would imagine that this would even work on an Android tablet (which now has support for a mouse plugged in) which Microsoft have also released an RDP client for. Or better yet a Windows tablet where you can use VS2015 on the device itself instead of through remote desktop.

VS2015iPad



.
Tags: VS2015

Thursday, 22 January 2015 15:12:05 (GMT Standard Time, UTC+00:00)  #    Comments [0]


# Tuesday, 20 January 2015

This was one that passed me by over the festive period. If you use the online version of TFS, you can now edit code inside the repository from the web interface and add new files to the repository completely from the web interface.

http://www.visualstudio.com/en-us/news/2014-dec-17-vso

The above functionality does not appear to be included in Update 4 of the standalone version of TFS.



.
Tags: TFS | TFS Tools

Tuesday, 20 January 2015 18:25:21 (GMT Standard Time, UTC+00:00)  #    Comments [0]


If you get the above error when installing TFS 2013 Update 4. You may find the following article useful.

http://blogs.msdn.com/b/heaths/archive/2014/05/23/update-does-not-apply-or-is-blocked-by-another-condition-on-your-computer.aspx

In my case I installed another program that required Update 4. In this case because it was a test machine I installed Visual Studio 2013 and Update 4 suddenly worked.



.
Tags:

Tuesday, 20 January 2015 17:41:14 (GMT Standard Time, UTC+00:00)  #    Comments [0]


# Friday, 05 December 2014

I’ve recently completed a project working with a great development team. Every time you work on a new project even in a software coaching role you hope people learn new things from you and that you also importantly learn new things from them. 

One of the things I found interesting was getting the team to follow Test Driven Development. The reason I was so adamant about it even down to being called “Mr Test” by the team, is that I like many other developers have been on projects where any kind of automated testing had been thrown out of the window or not been given the attention it deserves. All too many times teams have said they are following test driven development and not really know what it actually means. You may have heard the following.

  • “Its only a small change there’s no need to test it”
  • “I’ll write the tests later I just want to get it done.”
  • “I’ll put a task in the backlog to write the tests”
  • “I’ll write the code and you write the tests”

TDD aside, I think the first thing that has to be understood, is why unit testing is actually important. This is the example I like to use. When we build our application, its a bit like building a house, you need to ensure you have good strong foundations before you start building those brick walls. Software development is very similar in the example below our foundation is the code we have previously written and to ensure this code does what it is supposed to we protect what we have previously done with unit tests.

Our tests are our insurance policy. They ensure that our code behaves the way it was intended long after we have left it and moved along to the next piece of development.

image

Just like building the foundations of a house you don’t necessarily realise the consequences of doing it incorrectly until later. Unit testing is very much the same, its not until later that you realise your application is falling apart and you have absolutely no idea why. Every change you make to the application fills you with dread because you have no idea what you will end up breaking next. It can also be one of the reasons a team starts off with a high velocity and then suddenly slows down and stops delivering each sprint. 

When teams start to understand the picture above, the rest usually comes together quite easily. Developers start to realise that even if they are working alone in a team of one on some internal code the value of unit testing still applies to them.

TDD should then be a natural extension after the value of unit testing is fully grasped. Test Driven Development helps us think about the intent of our code, how we are going to test our application upfront, it makes us think about the design and can encourage good design at the same time.



.
Tags: Agile | TDD

Friday, 05 December 2014 12:41:17 (GMT Standard Time, UTC+00:00)  #    Comments [0]


# Thursday, 08 May 2014

This is more for my own reference. If you use iSubscriber in your applications you may have noticed they’ve stopped working in Update 2 of TFS 2013 because they can’t find WorkItemChangedEvent.

This is now located in Microsoft.TeamFoundation.WorkItemTracking.Server which can be found here.

C:\Program Files\Microsoft Team Foundation Server 12.0\Application Tier\Web Services\bin\Microsoft.TeamFoundation.WorkItemTracking.Server.dll



.
Tags: TFS

Thursday, 08 May 2014 13:11:15 (GMT Daylight Time, UTC+01:00)  #    Comments [0]


# Tuesday, 09 July 2013

LeanKit if you haven’t heard of it is a popular Kanban board available as a service over the Internet. I’ve used it myself and seen it used on several client sites in the past. However the one question I seem to be hearing lately is “can’t we use LeanKit for our tasks and TFS for code?”.

Its a reasonable question, Team Foundation Server depending on what version you are using gives you quite a lot of functionality out of the box. You could argue that if you have TFS 2012 you wouldn’t need to use a separate KanBan board. However just because you have a KanBan board doesn’t necessarily mean you’re writing code and an organisation may have been set on LeanKit way before TFS was introduced.

So can we have both?
You certainly can, and one sleepy afternoon I decided to see if I could get the two to talk to each other. The initial  integration between the two was a lot easier than I thought it would be, anyone who is familiar with REST and the TFS API would find it a breeze! And yes it answered the question of could it be done but it also raised several more questions!

  • Why?
  • What about conflicts?
  • Does this add value?

Now the “why” is probably self explanatory from the paragraphs above. However conflicts and “Does this type of integration actually add value” weren’t that straight forward. My conundrum wasn’t getting them to work together but more what to do about someone changing something in TFS and another changing something in LeanKit?

My Solution
So I came up with the following scenario.

“If you are storing tasks and editing them in LeanKit in the first place you’re probably not that likely to want to edit them in TFS? However when you check in your code you will probably want to associate your check in with a task you have been working on.”

While I appreciate the above probably doesn’t apply to everyone, this is one way with the least amount of effort I came up with for integrating the two that could add value. There are several more that I will go into in more detail on later.

Firstly I created a program that polled LeanKit for updates (I would have preferred an event service but couldn’t find one in the LeanKit API). I’ve called my simple polling app “LeanKit Kanban Caller” it basically goes over the tasks in LeanKit and ensure they exist in TFS.

image

If a task doesn’t exist in TFS the program creates one otherwise it just updates any existing tasks if they are different.

image

The program knows which task to associate with LeanKit because I altered the default Product Backlog Item WIT from the Scrum 2.0 template in TFS 2012 to store the LeanKit ID (note this type of integration should also work with TFS 2010 on a different template).

image

For the purposes of my experiment I only mapped the title, description and size fields across but mapping others is easy. I didn’t bother with the State of the item in TFS, partly because the state in LeanKit can be changed so easily by adding more columns while in TFS its a question of editing the workflow on the WIT. While it is possible to map these to each other it would end up making your board inflexible and for the purposes of this scenario we’re not actually using that field.

I have assumed that in TFS everything is a PBI and child tasks are redundant for the purpose of this scenario.

Pros and Cons of my approach

Pros
  • The polling app can sit on any machine that has the Team Explorer client installed and has an Internet connection
  • You can associate code check-ins with tasks from your LeanKit board as they now exist in TFS
  • Using LeanKit is business as usual as no changes are made to your LeanKit board

Cons

  • Changing a task in TFS will not update the task in LeanKit
  • The states in TFS are not mapped to those in LeanKit
  • Analysis tools in TFS for the backlog have no use with this scenario.

How else could we have worked?
There are several other ways in which I could have made this solution work.

  • Treat TFS as the master and overwrite anything in LeanKit (no real value)
  • Allow updates to go both ways and make use of the datetime stamp to determine if TFS updates LeanKit or if LeanKit updates TFS (could lead to conflicts).
  • Make TFS and LeanKit responsible for different fields. This way both can update each other sound in the knowledge that no data will be overwritten.

Are there any other scenarios? If you have any suggestions I’d love to hear them.



.
Tags: LeanKit | TFS | TFS Tools

Tuesday, 09 July 2013 14:31:00 (GMT Daylight Time, UTC+01:00)  #    Comments [0]


# Thursday, 13 June 2013

A while ago I had to do a bit of work with the TFS Subscription service. The annoying problem was I needed to find a particular subscription and the tools that came out of the box weren't very helpful.  I also wanted to keep the original subscription details but just add to it. So I created this little app

image

This little app will enable you to

  • View TFS Event Subscriptions from a machine that has the TFS 2010 or TFS 2012 client installed
  • Create a new event subscription from an existing one.
  • Unsubscribe from an event

Usage

  • Type in your TFS URL in most cases this would be http://tfs:8080/tfs if you have several instances ensure you place the correct instance onto the URL the above will usually give you the default instance. If you have an instance called “test” the url would be http://tfs:8080/tfs/test .
  • Type in your TFS username and password and hit the “List Subscriptions” button.
  • Select the subscription you’d like to look at and this will be shown in more detail in the bottom right hand section of the app called “Selected Event”
  • You can now unsubscribe or create a new event from the event you just selected. Ensure you change the event first or you may get an error having duplicate events.

In the sample picture you can see I am using the app to make a change to the Scrum For Team System event service by adding more WITs to it.

Most of the credit for the example code for this app should go to Rene van Osnabrugge’s article found here all I have done is throw a GUI on the front and added a few more functions that enable me to copy events.

Before using this app I would like to point out the following (pretty standard stuff)

  • Use of this app is completely at your own risk I or my employer accept no responsibility what so ever for any unintended effects as a result of its usage. If you are worried I would recommend downloading the code and stepping through it.
  • The code is rough and ready (I created it in a hurry) and is provided as is, by all means please look at the code before running the executable.
  • Please let me know if it was at all helpful

Download the Code

Download the TFS 2010 Executable Only 

Download the TFS 2012 Executable Only



.
Tags: TFS | TFS Tools

Thursday, 13 June 2013 14:21:06 (GMT Daylight Time, UTC+01:00)  #    Comments [2]


# Thursday, 02 May 2013

My reason for looking into this particular subject was being on a client site and sitting with a BA who was feeling a bit down hearted. She couldn’t figure out how she could properly communicate to the team how a bit of the system worked so they could refer back to it for a piece of work they were currently working on. I asked her why she just didn’t document it, her response to me was “but agile mean’s you don’t write documentation”. I must admit it through me when she said that. I had always without even thinking about the methodology itself provided anything I possibly could to help a team out when they needed it. If it made their lives easier to do a job and to burn through those tasks what was the harm in that? If in doubt on how to provide a piece of information to a team or if you are wondering if it adds value, why not ask them?

For example, sometimes to help a team focus on what they are building I usually suggest taking a wireframe (if you are indeed using wireframes) or rough sketch of what they are working on and place it on the wall. I may even suggest taking a copy of the PBI and sticking it next to it, the tasks that come off that PBI can float around the wireframe and you can use bits of string (nothing high tech!) to point at the various bits they are starting on. After a while the team would start doing this themselves and use it as a handy visual aid to what they were actually working on. In the morning stand-up's they could point to the bit of functionality they were having problems with (if any). This didn’t replace the task board it helped visualise an aspect of it that they were currently working on.

The approach worked well from a top down approach of development. Another approach I found worked after they had worked their way down the wireframes is doing a rough diagram of the stack that sat underneath that wireframe that they were currently developing. They could then point their tasks at what they were working on if it helped them to communicate to the team where they were or helped them visualise what they had to do next. When I say rough it would make sense for the team to collaboratively draw this in marker pens on a white board. By doing this it enables them to change or improve it.

Talking to others about this approach..

They found it was good as long as the wireframes the team were using were those they had contributed towards creating in the first place and that the team accepted they were not set in stone i.e. they could evolve with the teams input.

Using sketches instead of wireframes, gives the idea that the design is not permanent and can be changed at any time.

It was ok as long as the wireframes were modelling what had already been produced.

It was “taken to the team”, i.e. let the team decide if it adds value and or it helps them.

What are your thoughts, are there any visual aids as a developer you may have found helpful in the past?

Please note..
I must point out that I am not an Agile coach, but have worked as a developer, lead developer or architect on several teams in the past.

.
Tags: Agile

Thursday, 02 May 2013 11:37:13 (GMT Daylight Time, UTC+01:00)  #    Comments [0]


# Tuesday, 23 April 2013

A while a go I wrote an article on how I managed to get the test results from a build that was using PSAKE to surface in TFS’s summary view. I provided one solution to this problem in that article that would “just get you by” and have since been reminded that I said I would write another article on my second solution to the problem which was the PSAKE Incubator.

Its been a long time so its taken me a while to recollect what I did and I no longer have the old dev TFS server I originally got this working on so I will provide what I have done below in order to help anyone else who is looking for a similar solution and needs a steer in the right direction.

Basically I had removed the need for a InvokeProcess in the build XAML workflow and created a new custom activity called PSAKE Incubator. This custom activity would invoke the PSAKE powershell script natively allowing you to make use of the TFS code activity context directly in your PSAKE power shell scripts. In addition the PSAKE Incubator takes its parameters as an array and passes this through to PSAKE.

Below is the code I used to create the custom workflow activity to compile it you will need to create a custom workflow activity, Ewald Hofman has a great example here . Please also note that if you do not want to modify PSAKE if memory serves correctly you may need to create a custom activity host to handle the console output from PSAKE, hope this will be of use to someone, when I get some more time I’ll try and get a TFS box setup to test this out again.

Please note the code below is used at your own risk and I would advise testing on a dev environment before using on your production system.

If you do find the code below useful, please drop me a line and let me know how it went.

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.IO;
 
 
namespace TfsWorkflowActivities
{
    using System.Activities;
    using System.Collections;
    using System.Globalization;
 
    using Microsoft.TeamFoundation.Build.Client;
    using Microsoft.TeamFoundation.Build.Workflow.Activities;
    using Microsoft.TeamFoundation.Build.Workflow.Services;
 
    [BuildActivity(HostEnvironmentOption.All)]
    public sealed class PSAKEIncubator : CodeActivity
    {
 
        public InArgument<string> TFSURL { get; set; }
        public InArgument<string> TFSTeamProject { get; set; }
        public InArgument<string> TFSBuildURI { get; set; }
        public InArgument<Hashtable> LogTargets { get; set; }
        public InArgument<string> SourceDirectory { get; set; }
 
        public InArgument<string> BuildFile { get; set; }
        public InArgument<string[]> TaskList { get; set; }
        public InArgument<Hashtable> Parameters { get; set; }
        public InArgument<Hashtable> Properties { get; set; }
        public InArgument<string> PSAKEModuleDIR { get; set; }
        public InArgument<string> LogName { get; set; }
        public InArgument<string> OutPutDir { get; set; }
 
        public OutArgument<int> ExitCode { get; set; }
 
 
        protected override void Execute(CodeActivityContext context)
        {
            IActivityTracking activityTracking = context.GetExtension<IBuildLoggingExtension>().GetActivityTracking((ActivityContext) context);
 
            context.TrackBuildMessage("PSAKEIncubator Started", BuildMessageImportance.Low);
 
            string tfsURL = context.GetValue(this.TFSURL);
            string tfsTeamProject = context.GetValue(this.TFSTeamProject);
            string tfsBuildURI = context.GetValue(this.TFSBuildURI);
            string outPutDir = context.GetValue(this.OutPutDir);
            string sourceDirectory = context.GetValue(this.SourceDirectory);
            string buildFile = context.GetValue(this.BuildFile);
            string[] taskList = context.GetValue(this.TaskList);
 
 
            Hashtable properties = context.GetValue(this.Properties);
            Hashtable parameters = context.GetValue(this.Parameters);
 
            string pSAKEModuleDIR = context.GetValue(this.PSAKEModuleDIR);
            string logName = context.GetValue(this.LogName);
 
            
 
            string arguments = String.Format("$global:tfsUrl = '{0}'\n",tfsURL);
                   arguments+= String.Format("$global:tfsTeamProject = '{0}'\n", tfsTeamProject);
                   arguments+= String.Format("$global:TfsBuildUri = '{0}'\n", tfsBuildURI);
                   arguments+= String.Format("$global:logTargets = @{{}}\n");
                   arguments+= String.Format("$global:logTargets.Add('TfsBuild', @{{verbosity='Progress'}})\n");
                   arguments += String.Format("$global:logTargets.Add('LogFile', @{{verbosity='Debug'; logDir='{0}\\_Logs'; logFilename='build-output.log'}});\n", outPutDir);
                            
 
            context.TrackBuildMessage("Source Directory:" + sourceDirectory, BuildMessageImportance.Low);
            
            // Replace the line below with the location and name of the powershell script you use to kick off your PSAKE Build
            string scriptPath = string.Format("{0}\\run-psake.ps1", Path.Combine(sourceDirectory, "BuildAndDeploy\\buildframework"));
 
            context.TrackBuildMessage("Script Path:" + scriptPath, BuildMessageImportance.Low);
            List<CommandParameter> parametersArgument = new List<CommandParameter>();
 
 
            Hashtable parametersCleaned = new Hashtable();
 
            foreach (DictionaryEntry valHash in parameters)
            {
                if (valHash.Value == null)
                {
                    parametersCleaned.Add(valHash.Key, string.Empty);
                }
                else
                {
                    parametersCleaned.Add(valHash.Key, valHash.Value);
                }
            }
 
            Hashtable propertiesCleaned = new Hashtable();
 
            foreach (DictionaryEntry valHash in properties)
            {
                if (valHash.Value == null)
                {
                    propertiesCleaned.Add(valHash.Key, string.Empty);
                }
                else
                {
                    propertiesCleaned.Add(valHash.Key, valHash.Value);
                }
            }
 
 
            parametersArgument.Add(new CommandParameter("buildFile",buildFile));
            parametersArgument.Add(new CommandParameter("tasklist",taskList));
            parametersArgument.Add(new CommandParameter("outputDir",outPutDir));
            parametersArgument.Add(new CommandParameter("parameters", parametersCleaned));
            parametersArgument.Add(new CommandParameter("properties", propertiesCleaned));
            parametersArgument.Add(new CommandParameter("psakeModuleDir",pSAKEModuleDIR));
            parametersArgument.Add(new CommandParameter("logName",logName));
 
 
            context.TrackBuildMessage("PSAKEIncubator passing arguments to RunScript", BuildMessageImportance.Low);
            int exitResult = RunScript(scriptPath,arguments,context,parametersArgument.ToArray());
 
            context.TrackBuildMessage("PSAKEIncubator exit code " + exitResult, BuildMessageImportance.Low);
            context.SetValue<int>(this.ExitCode, exitResult);
        }
 
 
        public string InformationNodeId { get; set; }
 
 
 
        private int RunScript(string scriptFile, string scriptText, CodeActivityContext context, CommandParameter[] parameters)
        {
 
            // create Powershell runspace
            string encodedCommand = scriptText;
 
            //BespokePSHost bespokePSHost = new BespokePSHost();
        
            Runspace runspace = RunspaceFactory.CreateRunspace();
 
            IActivityTracking activityTracking = context.GetExtension<IBuildLoggingExtension>().GetActivityTracking((ActivityContext)context);
            InformationNodeId = activityTracking.Node.Id.ToString("D", (IFormatProvider)CultureInfo.InvariantCulture);
 
            // open it
            context.TrackBuildMessage("PSAKEIncubator Opening runspace", BuildMessageImportance.Low);
            runspace.Open();
            
            //We set these variables so they become available in our PSAKE powershell scripts.
            // You will need to ensure these variables exist in your scripts to make use of them.
            runspace.SessionStateProxy.SetVariable("InformationNodeId", InformationNodeId);
        
            //This enables us to make use of the CodeContext directly from within PSAKE
            runspace.SessionStateProxy.SetVariable("CodeContext", context);
            // create a pipeline and feed it the script text
 
            Pipeline pipeline = runspace.CreatePipeline();
 
            context.TrackBuildMessage("PSAKEIncubator adding encoded script to pipeline", BuildMessageImportance.Low);
            pipeline.Commands.AddScript(encodedCommand);
 
 
            Command parameterCommands = new Command(scriptFile);
 
            context.TrackBuildMessage("PSAKEIncubator adding parameters to pipeline", BuildMessageImportance.Low);
            foreach (CommandParameter item in parameters)
            {
                context.TrackBuildMessage("processing param name:" + item.Name, BuildMessageImportance.Low);
 
                context.TrackBuildMessage("processing param value:" + item.Value, BuildMessageImportance.Low);
 
                if ("System.Collections.Hashtable" == item.Value.GetType().ToString())
                {
                    Hashtable hashTable = (Hashtable)item.Value;                  
                    
                   
                    foreach (DictionaryEntry valHash in hashTable)
                    {
                        string valueType = "";
 
                        if (valHash.Value != null)
                        {
                            valueType = valHash.Value.GetType().ToString();
                        }
                        else
                        {
                            valueType = "NULL";
                            //valueType = valHash.Value.GetType().ToString();
                            //valHash.Value = string.Empty;
                        }
 
                        context.TrackBuildMessage("HashVal:" + valHash.Key + ":" + valHash.Value + "(" + valueType + ")", BuildMessageImportance.Low);
                    }
 
                    context.TrackBuildMessage("---End of HASH---", BuildMessageImportance.Low);
                    
                }
 
                parameterCommands.Parameters.Add(item);
            }
 
          
            pipeline.Commands.Add(parameterCommands);
            //pipeline.Commands.Add("exit $LastExitCode;");
            pipeline.Commands.Add("Out-String");
 
            // execute the script
 
            Collection<PSObject> results = pipeline.Invoke();
 
            // close the runspace
            context.TrackBuildMessage("PSAKEIncubator closing runspace", BuildMessageImportance.Low);
            runspace.Close();
 
            // convert the script result into a single string
 
            context.TrackBuildMessage("PSAKEIncubator iterating through results", BuildMessageImportance.Low);
            StringBuilder stringBuilder = new StringBuilder();
            foreach (PSObject obj in results)
            {
                //return Convert.ToInt32(obj);
                context.TrackBuildMessage(obj.ToString(), BuildMessageImportance.Low);
                //stringBuilder.AppendLine(obj.ToString());
            }
 
            return 0;
        }
    }
}


.
Tags: PSAKE | TFS

Tuesday, 23 April 2013 14:07:51 (GMT Daylight Time, UTC+01:00)  #    Comments [0]