TFS2010 - SourceGetVersion上出现了错误的变更集

时间:2011-11-30 07:57:49

标签: tfs tfs2010 build-process

我目前正在设置Team Foundation Server 2010,并且在执行构建时发现了一个非常奇怪的行为:

情况说明: 我们有2个分支

  • 开发
  • 主要

所有开发人员仅将代码签入开发分支。每天一次,构建管理器将一些更改集合并到Main分支。在开发阶段,每次检查都会持续构建。在主分支上,每天一次(在夜晚)触发构建。

现在假设变更集1-100在下午5点合并到Main brach中,将changeset 101作为合并操作。一些开发人员在5点钟之后检查变更集102-106进入开发分支。现在在晚上11点,每日构建将自动触发并在Main分支上运行。 Main分支的最后一个变更集是变更集101.但是,构建详细信息显示变更集106:

enter image description here

我可以想象这种行为是有意的,因为如果你查看主分支上的变更集106,你实际上会得到变更集101的内容。但是如果这个构建摘要显示正确的数字,它将更具可读性

问题1:有没有办法操纵SourceGetVersion信息的输出?也许通过构建过程模板?

TFS表现奇怪的第二种情况更糟糕: 排队新构建时,可以选择输入“获取版本”参数,如下图所示:

enter image description here

如果我现在点击“队列”,则会触发构建,并且AGAIN构建详细信息会输出变更集106,尽管我专门将其设置为获取变更集76.

问题2:这是一个错误吗?是否有修补程序或其他东西来解决这个问题?或者是否有必须设置的选项标志?

我希望有人知道更多。我真的不相信这是一个错误,因为它是一个至关重要的功能,其他人之前必须遇到它。

感谢您的帮助!! 基督教

编辑1

团队项目的文件夹结构是:

$项目名

  • BuildProcessTemplates
  • 文档
  • 源码
    • 开发< - 这是一个分支
      • 的3rdParty
      • 来源
    • Main< - 这是一个分支
      • 的3rdParty
      • 来源

构建仅拉取主分支及其下方的所有内容。

编辑2

以下是构建定义中“工作区”选项卡的图片: enter image description here

1 个答案:

答案 0 :(得分:22)

最后我发现了发生了什么:

基本上可以在我的图片1中看到的变更集始终是整个团队项目集合的最新变更集。它是“IBUildDetails”类型的对象“BuildDetails”上的属性“SourceGetVersion”。

我认为这是一个可以解决的错误: 如果将BuildDetails.SourceGetVersion(这是一个字符串)更改为其他值,则构建摘要将显示更新的字符串。此外,它会正确保存到集合数据库中。

为了添加正确的变更集号,我所做的是创建了一个自定义构建活动,它将应该构建的分支作为输入参数。它输出正确的变更集。活动通过连接到TFS并下载历史记录来找出正确的变更集。然后它查看历史记录中的所有项目并输出最大的变更集编号。以下是该活动的代码:

using System.Activities;
using System.Collections;
using System.Net;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.Build.Client;

namespace SourceGetVersionActivity
{
    [BuildActivity(HostEnvironmentOption.All)]
    public sealed class SourceGetVersionActivity : CodeActivity<string>
    {
        // Define an activity input argument of type string
        public InArgument<string> Branch { get; set; }

        // If your activity returns a value, derive from CodeActivity<TResult>
        // and return the value from the Execute method.
        protected override string Execute(CodeActivityContext context)
        {
            // Obtain the runtime value of the Text input argument
            string branch = context.GetValue(this.Branch);

            ICredentials account = new NetworkCredential("Useranme", "password", "domain");

            // connect / authenticate with tfs
            TeamFoundationServer tfs = new TeamFoundationServer("http://tfs:8080/tfs/CollectionName", account);
            tfs.Authenticate();

            // get the version control service
            VersionControlServer versionControl = (VersionControlServer)tfs.GetService(typeof(VersionControlServer));

            IEnumerable changesets = versionControl.QueryHistory(branch, VersionSpec.Latest, 0, RecursionType.Full,
                null, null, null, int.MaxValue, false, false, false, false);

            int maxVersion = 0;

            foreach (Changeset c in changesets)
            {
                if (c.ChangesetId > maxVersion)
                {
                    maxVersion = c.ChangesetId;
                }
            }

            return string.Concat('C', maxVersion.ToString());
        }
    }
}

我尽快调用此活动(在GetBuild活动之后)。

基本上在BuildProcessTemplate中我添加了一个Argument(string)“Branch”,它需要填充一个指向正在构建的顶层文件夹的字符串。自定义活动将其作为输入并输出一个字符串,该字符串是正确的变更集ID。然后,BuildDetail.SourceGetVersion属性将被正确的变更集ID覆盖。

我觉得很奇怪,没有其他人似乎遇到过这个问题。我在互联网上找不到任何有同样问题的人。无论如何,我希望这个答案能帮助将来的其他人。

编辑 - 直接在Workflow Foundation中编写上述代码:

要使用更紧凑的代码获取正确的变更集并避免自定义活动,还可以直接使用Workflow Foundation。下面是“代码”(完全按照上面的C#代码完成):

enter image description here

(1)GetTeamProjectCollection活动获取当前集合。我将它保存在 TeamProjectCollection 变量中(参见图片底部)。重要提示:需要在此序列中定义变量,如果在外部作用域中定义,则会发生错误:“无法序列化类型'Microsoft.TeamFoundation.Client.TfsTeamProjectCollection'。验证类型是否为公共类型且是否具有默认构造函数或实例描述符。“

(2)“TeamProjectCollection.GetService(Of VersionControlServer).QueryHistory(Branch,VersionSpec.Latest,0,RecursionType.Full,Nothing,Nothing,Nothing,Integer.MaxValue,False,False,False)中的Foreach”changeset“ .Cast(Of Changeset)()“ Foreach循环的TypeArgument是“Microsoft.TeamFoundation.VersionControl.Client.Changeset”。 此表达式从集合中获取版本控制对象,将其称为“QueryHistory”方法,该方法返回包含所有更改集的IEnumerable。

(3)因此,我们迭代所有变更集并查看ChangesetId。然后将最大ChangesetId保存到变量“maxId”。

(4)最后,BuildDetails.SourceGetVersion =“C”+ maxId.ToString()。 “C”表示该版本是变更集。

我希望有人发现这段“代码”很有用!

基督教