我目前正在设置Team Foundation Server 2010,并且在执行构建时发现了一个非常奇怪的行为:
情况说明: 我们有2个分支
所有开发人员仅将代码签入开发分支。每天一次,构建管理器将一些更改集合并到Main分支。在开发阶段,每次检查都会持续构建。在主分支上,每天一次(在夜晚)触发构建。
现在假设变更集1-100在下午5点合并到Main brach中,将changeset 101作为合并操作。一些开发人员在5点钟之后检查变更集102-106进入开发分支。现在在晚上11点,每日构建将自动触发并在Main分支上运行。 Main分支的最后一个变更集是变更集101.但是,构建详细信息显示变更集106:
我可以想象这种行为是有意的,因为如果你查看主分支上的变更集106,你实际上会得到变更集101的内容。但是如果这个构建摘要显示正确的数字,它将更具可读性
问题1:有没有办法操纵SourceGetVersion信息的输出?也许通过构建过程模板?
TFS表现奇怪的第二种情况更糟糕: 排队新构建时,可以选择输入“获取版本”参数,如下图所示:
如果我现在点击“队列”,则会触发构建,并且AGAIN构建详细信息会输出变更集106,尽管我专门将其设置为获取变更集76.
问题2:这是一个错误吗?是否有修补程序或其他东西来解决这个问题?或者是否有必须设置的选项标志?
我希望有人知道更多。我真的不相信这是一个错误,因为它是一个至关重要的功能,其他人之前必须遇到它。
感谢您的帮助!! 基督教
编辑1
团队项目的文件夹结构是:
$项目名
构建仅拉取主分支及其下方的所有内容。
编辑2
以下是构建定义中“工作区”选项卡的图片:
答案 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#代码完成):
(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”表示该版本是变更集。
我希望有人发现这段“代码”很有用!
基督教