Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TFS 2010: How to produce a changelog (ie. list of work items) between two releases of the application using labels?

I'm looking for a way to automatically produce a changelog (actually a list of workitems) between two releases of my application. I have two versions of my application, v1 and v2, each is identified by a label in TFS 2010 (LABEL1 and LABEL2) that I manually created before building the setups of my app. I have a branching system, which means I have a trunk were most of bugs are fixed, and a branch where patches are applied mostly using merges from the trunk (but there are also some fixes on the branch only that do not concern the trunk). The two versions of my application (v1 and v2) are versions from the branch.

I would like TFS 2010 to be able to return the list of bugs that were fixed (ie. the list of work items with type = Bug that are closed and verified) between these two labels.

I tried to achieve this using the web UI of TFS 2010, or using Visual Studio, but I didn't find any way.

Then I tried to ask tf.exe for a history using the following command line:

tf history /server:http://server_url/collection_name "$/project_path" /version:LLABEL1~LLABEL2 /recursive /noprompt /format:brief

where LABEL1 is the label that has been associated with the source code of the v1 of the application, and LABEL2 the label that has been associated with the source code of the v2 of the application. It actually fails in two ways: - the command line only returns a list of changesets, not a list of associated closed work items - the list of changesets only contains the changesets that I applied on the branch itself, not the changesets that I also applied and the trunk and then merged to the branch. Setting or not the "/slotmode" parameter doesn't change anything.

There I tried to write a piece of C# code to retrieve the list of workitems (not the list of changesets):

var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://server_url/collection_name"));

VersionControlServer controlServer = tfs.GetService<VersionControlServer>();
VersionControlServer vcs = tfs.GetService<VersionControlServer>();

VersionSpec sFrom = VersionSpec.ParseSingleSpec("LLABEL1", null);
VersionSpec sTo = VersionSpec.ParseSingleSpec("LLABEL2", null);

var changesets = vcs.QueryHistory(
    "$/project_path",
    sTo,
    0,
    RecursionType.Full,
    null,
    sFrom,
    sTo,
    int.MaxValue,
    true,
    false); // Slotmode to false

Dictionary<int, WorkItem> dico = new Dictionary<int, WorkItem>();
foreach (Changeset set in changesets)
{
    foreach (WorkItem zz in set.WorkItems)
    {
        if (!dico.ContainsKey(zz.Id))
        {
            dico.Add(zz.Id, zz);
        }
    }
}

foreach (KeyValuePair<int, WorkItem> pair in dico.OrderBy(z => z.Key))
{
    Console.WriteLine(string.Format("ID: {0}, Title: {1}", pair.Key, pair.Value.Title));
}

This actually works, I get the list of workitems between my two labels which is actually what I wanted. But only workitems associated to changesets that were committed on the branch itself are taken into account: the workitems of type "Bug" that were solved on the trunk then merged to the branch don't appear. Slotmode doesn't change anything.

Then I finally tried to replace VersionSpecs that were defined by a label with VersionSpecs that are defined by changesets:

VersionSpec sFrom = VersionSpec.ParseSingleSpec("C5083", null);
VersionSpec sTo = VersionSpec.ParseSingleSpec("C5276", null);

And my code finally works.

So my question is: how could I get the same result with labels, which are the TFS objects I use to identify a version? If it's not possible, how should I identify a version in TFS 2010? Thx.

Btw I found some questions on stackoverflow, but none of them gave me answers with labels. For instance: Question example

like image 822
ken2k Avatar asked Dec 08 '11 09:12

ken2k


2 Answers

I think http://tfschangelog.codeplex.com/ can possibly help you here.

TFS ChangeLog applicatoin allows users to automatically generate release notes from TFS. Users will have to provide information on thier project, branch and changeset range and then TFS ChangeLog application will extract information from each changeset in a given range and all the associated workitems to such changesets. i.e. it will travel from starting changeset upto ending changeset and will extract data about each changeset along with associated workitems in an XML file.

Users can then use their own transformation logic including filter, sorting, styling, output formatting, etc. to generate Release Notes Report.

Another thing I would like to add here will be related to Labels in TFS. Labels are basically assigned / associated with changesets. Currently, TFS ChangeLog application does not support Labels to define starting and ending point but it does support changeset which can be used as a workaround solution.

Hope this is useful.

like image 113
Dharmesh Shah Avatar answered Nov 11 '22 21:11

Dharmesh Shah


In general, the absolute method of defining points in time in any SCM is clearly the checkin-id.
Using labels to abstract this, is in TFS not the optimum as discussed here & here. A better approach is to use builds instead, especially in a modern CI environment.

In order to retrieve the max changeset that was contained in a given build you 'd have to do something like this:

using System;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;

namespace GetChangesetsFromBuild
{
    class Program
    {
        static void Main()
        {
            TfsTeamProjectCollection tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://TFSServer:8080/Name"));
            IBuildServer bs = (IBuildServer)tpc.GetService(typeof(IBuildServer));

            IBuildDetail build = bs.GetAllBuildDetails(new Uri("vstfs:///..."));

            List<IChangesetSummary> associatedChangesets = InformationNodeConverters.GetAssociatedChangesets(build);

            int idMax = associatedChangesets[0].ChangesetId; 
        }
    }
}


A difficulty with the above is to retrieve the BuildUri of the builds you are interested in. In order to get this information you could do something like this:

IBuildDetail[] builds = bs.QueryBuilds("TeamPorjectName", "yourBuildDefinitionName")

and then retrieve the Uri's that are important to you.

This is also a good vehicle if you eventually insist on using labels: Besides Uri, each build[] has also a LabelName.

like image 23
pantelif Avatar answered Nov 11 '22 23:11

pantelif