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

Chr*_*ian 20 tfs build-process tfs2010

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

情况解释:我们有2个分支机构

  • 发展
  • 主要

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

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

在此输入图像描述

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

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

TFS行为奇怪的第二种情况甚至更糟:当排队新的构建时,可以选择输入"获取版本"参数,如下图所示:

在此输入图像描述

如果我现在点击"队列",则触发构建,并且AGAIN构建细节输出变更集106,尽管我专门设置它以获得变更集76.

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

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

谢谢你的帮助!!基督教

编辑1

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

$项目名

  • BuildProcessTemplates
  • 文档
  • 源代码
    • 发展< - 这是一个分支
      • 的3rdParty
      • 资源
    • 主< - 这是一个分支
      • 的3rdParty
      • 资源

构建只会拉动Main分支及其下方的所有内容.

编辑2

以下是构建定义中"工作区"选项卡的图片: 在此输入图像描述

Chr*_*ian 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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

在此输入图像描述

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

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

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

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

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

基督教

  • 很棒的解决方案(是的,这是一个无关紧要的评论,但解决方案保证...) (2认同)
  • 对问题和良好解决方案的重要解释,尽管它们仅适用于最新代码的构建.它们不适用于Gated Check-In构建或自定义构建,其中构建的版本不是最新版本. (2认同)