Search code examples
c#tfstfs-2015tfs-workitemworkitem

TFS .NET client libraries finding merge related work items


I want to build a Query App that, which will query a branch in TFS, and retrieve all work items and display it as Master Detail report as such:

User Story:30669    [Closed]    Ongoing Support and Maintenance
    Task:31566      [Closed]    Upgrade latest version of client libraries
    Bug:30905       [Closed]    Executing Error "The given Key was not present in the dictionary"
User Story:30351    [Closed]    Add new Function
    Task:28188      [Closed]    Implement new Function

This will give us a good idea, of what work we have done on a given branch, and what will be in a build if we choose to build.

So currently I can retrieve all the work items for a branch between dates, excluding merges. I want to include merges, but I am struggling to understand TFS client interface.

This is what I have so far: The BranchModel, ChangesetModel, UserStories, and TaskBugs are classes to help me arrange WorkItem objects for the output report:

        const String c_collectionUri = "http://tfsServer:81/tfs/ProjectCollection";
        const String c_projectName = "Project";

        using (TfsTeamProjectCollection tpc = 
               new TfsTeamProjectCollection(new Uri(c_collectionUri)))
        {
            VersionControlServer vcServer =
                 tpc.GetService<VersionControlServer>();
            WorkItemStore workItemStore = tpc.GetService<WorkItemStore>();

            // Fetch the branch history
            var history = vcServer.QueryHistory(@"$/ProjectCollection/Project/Branch1/Source", RecursionType.Full)
                .Where(h => h.CreationDate >= new DateTime(2018, 1, 1) && h.CreationDate <= new DateTime(2018, 1, 5));

            BranchModel branch = new BranchModel("Branch1");

            // Get the changesets, for from the fetched history
            List<Changeset> changesets = new List<Changeset>();
            foreach (Changeset changeset in history)
            {
                changesets.Add(changeset);

                // TODO: Add code to get Changesets related to merge
            }

            // Get the WorkItems from Changesets Fetched 
            foreach (Changeset changeset in changesets)
            {
                ChangesetModel changesetModel = branch.AddChangeset(changeset);

                foreach (WorkItem workItem in changeset.WorkItems)
                {
                    //  Fetch the UserStory for a Bug/Task
                    foreach (var linkedItem in workItem.Links)
                    {
                        RelatedLink relatedItem = linkedItem as RelatedLink;
                        WorkItem userStory = null;

                        if (relatedItem != null)
                            userStory = GetWorkItem(workItemStore, c_projectName, relatedItem.RelatedWorkItemId);

                        if (userStory != null)
                        {
                            var userStoryModel = branch.AddUserStory(userStory);
                            var taskBugModel = userStoryModel.Add(workItem);
                        }
                    }
                }

            }

            // Finally print the report
            Console.WriteLine();
            Console.WriteLine("Related Work:");
            Console.WriteLine("=".PadLeft(80, '='));

            foreach (var userStory in branch.UserStories)
            {
                Console.WriteLine(userStory.Value.ToString());

                foreach (var taskBug in userStory.Value.TaskBugs)
                {
                    Console.WriteLine(taskBug.Value.ToString());
                }
            }

And the Method for GetWorkItem:

    void WorkItem GetWorkItem(WorkItemStore workItemStore, string c_projectName, int workitemID)
    {
        return workItemStore.Projects[c_projectName].Store.GetWorkItem(workitemID);
    }

I would like to know, for a Changeset that happens to be a merge, how to get it's related work items related to that merge.


Solution

  • You cannot get the related work items directly from the merge changeset. You need to get the merge history (version from , version to), then retrieve the related work items from the version from and version to changesets.

    You can use the VersionControlServer.GetChangesForChangeset Method to get the merge history for the merge changeset. Then Get the WorkItems from the history Changesets Fetched.

    Below sample for your reference to get the merge changeset history:

    static void Main(string[] args)
            {
                TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri("http://server:8080/tfs/DefaultCollection"));
                new System.Net.NetworkCredential("username", "password");
                tpc.EnsureAuthenticated();
                VersionControlServer vcs = tpc.GetService<VersionControlServer>();
    
                int cid = 376;
    
                //List<IChangesetSummary> changeSets = InformationNodeConverters.GetAssociatedChangesets(build);
                IEnumerable<Change> changes = vcs.GetChangesForChangeset(cid, false, Int32.MaxValue, null, null, true);
    
                foreach (Change change in changes)
                {
                    if ((change.ChangeType & ChangeType.Merge) == 0) continue;
                    foreach (var m in change.MergeSources)
                    {
                        Console.WriteLine("{0} {1} {2} {3}", change.Item.ChangesetId, m.ServerItem, m.VersionFrom, m.VersionTo);
                    }                   
                }
                Console.ReadLine();
            }