TFS 2010 API - 从合并中获取工作项

发布于 2024-12-06 16:07:35 字数 376 浏览 1 评论 0原文

我需要在 TFS 2010 中的构建完成时发送一封电子邮件,其中详细说明与已作为此构建的一部分进行编译的签入相关的工作项。通过使用构建工作流程中可用的 linkedChangesets 变量,这没有问题。

但是,在生产情况下,我们会将开发分支中的更改合并到发布分支中。此时,构建认为只有一个更改 - 就是前面提到的将开发合并到发布中。显然,这是相当无用的,因为我们需要找出合并的分支中进行了哪些更改以及关联的工作项

有谁知道如何使用 TFS 2010 API 来完成此任务?从 API 的角度来看,它的记录似乎相当少。我知道您可以在 VS2010 中扩展合并历史记录节点,但显然这不好,因为需要以编程方式收集这些数据,以便可以发送报告电子邮件。

I need to send an email on completion of a build in TFS 2010 which details the work items associated with check-ins that have been compiled as part of this build. This works no problem via use of the associatedChangesets variable available in the build workflow.

However, in a production situation, we will merge changes from our Development branch into a Release branch. At this point, the build considers there to have only been one change - which is the aforementioned merging of Development into Release. Obviously this is fairly useless as we need to find out which changes where made in the branch that was merged in, and the work items associated.

Does anyone know how to accomplish this using the TFS 2010 API? It seems to be fairly poorly documented from an API perspective. I know you can expand the merge history node in VS2010 but obviously this is no good as this data needs to be collected programatically so a report email can be sent.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

压抑⊿情绪 2024-12-13 16:07:35

好吧...我想我找到了一个解决方案,尽管它很笨重,而且说实话我不太确定它是如何工作的。但这里是——也许它会为某人指明正确的方向。

var associatedWorkItems = new List<WorkItem>();

//Passed in from the build workflow (this variable is available under the 'Run On Agent' sequence as 'associatedChangesets'
IList<Changeset> associatedChangesets = context.GetValue(BuildAssociatedChangesets);

if (associatedChangesets.Count > 0)
{
    var projectCollection =
        new TfsTeamProjectCollection(new Uri("http://localhost:8080/tfs/DefaultCollection"));
    VersionControlServer versionControlServer = projectCollection.GetService<VersionControlServer>();

    foreach (var changeset in associatedChangesets)
    {
        //In order to view the individual changes, load the changeset directly from the VCS.
        Changeset localChangeset = versionControlServer.GetChangeset(changeset.ChangesetId);

        foreach (Change change in localChangeset.Changes)
        {
            //Find out what was merged in.
            ChangesetMerge[] mergedChangesets = versionControlServer.QueryMerges(
                null,
                null,
                change.Item.ServerItem,
                new ChangesetVersionSpec(localChangeset.ChangesetId),
                new ChangesetVersionSpec(localChangeset.ChangesetId),
                null,
                RecursionType.Full);

            //Extract work item information from changesets being identified as merged.
            foreach (var changesetMerge in mergedChangesets)
            {
                Changeset actualChange = versionControlServer.GetChangeset(changesetMerge.SourceVersion);

                foreach (WorkItem item in actualChange.WorkItems)
                {
                    if (!associatedWorkItems.Exists(w => w.Id == item.Id))
                    {
                        associatedWorkItems.Add(item);
                    }
                }
            }
        }
    }
}

不要问我 QueryMerges 到底是如何工作的,但我在这里所做的只是告诉我,作为签入的变更集的一部分合并了什么。您会注意到参数 ChangesetVersionSpec 是相同的 - 这意味着我们只是查看这个变更集中的合并。

您将从 QueryMerges() 返回一组 ChangesetMerge 对象。在 ChangesetMerge 类中,有一个名为 SourceVersion 的属性 - 这是合并的原始变更集的 ChangesetId。一旦我们得到了它,我们就可以可以使用 VersionControlServer.GetChangeset() 方法加载单个集并提取 WorkItem。然后将其添加到 WorkItems 列表中,可以按照您想要的任何方式进行操作(在我的例子中是电子邮件)。我还使用了 .Exists() 检查来确保相同的 WorkItem 不会被记录两次。

请注意,即使您从构建工作流程中获得了 linkedChangesets 集合,但出于某种原因(至少对我而言),linkedChangesets 中的 Changes[] 属性code> 从未填充(因此使用 VersionControlServer.GetChangeset() 方法加载每个单独的变更集,因为这似乎实际上填充了我们需要的所有字段。

就像我说的,1.这是一个笨拙的解决方案(大量循环 - 其中一些可能是不必要的),2.我不完全理解这是如何工作的,尽管它似乎产生了所需的结果 - 我通过进行大量测试和调试得出了这个结论)最后 - 它是根据微软提供的糟糕的文档,我能想到的最好的办法就是。

希望它能帮助别人!

OK... I think I found a solution to this although it's clunky and truth be told I'm not exactly sure how it works. But here goes - maybe it will point someone in the right direction.

var associatedWorkItems = new List<WorkItem>();

//Passed in from the build workflow (this variable is available under the 'Run On Agent' sequence as 'associatedChangesets'
IList<Changeset> associatedChangesets = context.GetValue(BuildAssociatedChangesets);

if (associatedChangesets.Count > 0)
{
    var projectCollection =
        new TfsTeamProjectCollection(new Uri("http://localhost:8080/tfs/DefaultCollection"));
    VersionControlServer versionControlServer = projectCollection.GetService<VersionControlServer>();

    foreach (var changeset in associatedChangesets)
    {
        //In order to view the individual changes, load the changeset directly from the VCS.
        Changeset localChangeset = versionControlServer.GetChangeset(changeset.ChangesetId);

        foreach (Change change in localChangeset.Changes)
        {
            //Find out what was merged in.
            ChangesetMerge[] mergedChangesets = versionControlServer.QueryMerges(
                null,
                null,
                change.Item.ServerItem,
                new ChangesetVersionSpec(localChangeset.ChangesetId),
                new ChangesetVersionSpec(localChangeset.ChangesetId),
                null,
                RecursionType.Full);

            //Extract work item information from changesets being identified as merged.
            foreach (var changesetMerge in mergedChangesets)
            {
                Changeset actualChange = versionControlServer.GetChangeset(changesetMerge.SourceVersion);

                foreach (WorkItem item in actualChange.WorkItems)
                {
                    if (!associatedWorkItems.Exists(w => w.Id == item.Id))
                    {
                        associatedWorkItems.Add(item);
                    }
                }
            }
        }
    }
}

Don't ask me exactly how QueryMerges works but all I'm doing here it saying show me what what merged as a part of a changeset checked in. You'll notice that the parameters ChangesetVersionSpec are the same - this means we're just looking at merges from this one changeset.

You'll get back an array of ChangesetMerge objects from QueryMerges(). In the ChangesetMerge class there is a property called SourceVersion - this is the ChangesetId of the original changeset merged in. Once we've got that we can use the VersionControlServer.GetChangeset() method to load the individual set and extract the WorkItem. This is then added to a list of WorkItems which can be manipulated in any way you want (in my case an email). I also used the .Exists() check to make sure the same WorkItem doesn't get recorded twice.

Note that even though you have the collection associatedChangesets from the build workflow, for some reason (for me at least), the Changes[] property inside associatedChangesets was never populated (hence loading each individual changeset using the VersionControlServer.GetChangeset() method as this seems to actually populate all the fields we need.

Like I say, 1. this is a clunky solution (lots of looping - some of which is probably unecessary), 2. I don't fully understand how this works although it seems to produce the required results - I came to this conclusion by doing a lot testing and debugging) and finally - it's the best I could come up with based on the woeful documentation provided by Microsoft.

Hope it helps someone!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文