我需要以编程方式更新 vNext Build Definition。需要以编程方式更新构建定义的原因是我们正在运行 Team Foundation Server 2015 的 RTM 版本,并且从该版本开始,vNext Build Definitions 的某些部分未向 Web GUI 公开,并且(目前)没有其他方法可以更改它们。(假设您希望将数据库保持在受支持状态,并拒绝直接修改数据库。)
我们的公司环境和所有机器最近都经历了域更改。TFS 服务器已顺利移至新域。但是,vNext Build 定义在 URL 字段中对旧服务器名称有内部引用,其中仍包含旧域名。
到目前为止,我有以下代码,它应该更新某个项目的每个构建定义的 URL。对 GetDefinitonsAsync 的调用清楚地向我返回了正确的构建 DefinitionReferences,但 UpdateDefinitionAsync 似乎没有任何效果。
List<DefinitionReference> bds = new List<DefinitionReference>();
.
.
.
{
Uri tfsURI = new Uri("http://<tfsserver>:8080/tfs/<collection>");
WindowsCredential wc = new WindowsCredential(true);
BuildHttpClient bhc = new BuildHttpClient(tfsURI, new VssCredentials(wc));
var task = Task.Run(async () => { bds = await bhc.GetDefinitionsAsync(project: "projectname"); });
task.Wait();
foreach (var bd in bds)
{
BuildDefinition b = (BuildDefinition)bd;
b.Url = b.Url.Replace("<server>.<olddomain>", "<server>.<newdomain>");
var task1 = Task.Run(async () => { await bhc.UpdateDefinitionAsync(b); });
task1.Wait();
}
}
此代码片段编译并运行无错误。但是,当我事后检查构建定义时,它尚未更新,仍与之前一样。调试器未看到任何异常,也没有相关的事件查看器或 DebugView 消息。
关于上面的代码片段,我不确定是否应该通过将 DefinitionReference(子类)转换为 BuildDefinition 来获取需要传递给 UpdateDefinition 的 BuildDefinition,但是在 BuildHttpClient 类中我没有看到任何接近的内容可以从 DefinitonReference 给我一个 BuildDefiniton。
任何帮助都将不胜感激。谢谢!
答案1
为了用代码详细说明我上次的评论,
public partial class Form1 : Form
{
List<DefinitionReference> bds = new List<DefinitionReference>();
List<BuildDefinitionRevision> bdrs = new List<BuildDefinitionRevision>();
Dictionary<string, BuildDefinition> defs = new Dictionary<string, BuildDefinition>();
public Form1()
{
InitializeComponent();
//Connect to TFS vNext API
Uri tfsURI = new Uri("http://<servername>:8080/tfs/<collectionname>");
WindowsCredential wc = new WindowsCredential(true);
Microsoft.TeamFoundation.Build.WebApi.BuildHttpClient bhc = new Microsoft.TeamFoundation.Build.WebApi.BuildHttpClient(tfsURI, new VssCredentials(wc));
//Populate builddefinitionreference list for the project
var task = Task.Run(async () => { bds = await bhc.GetDefinitionsAsync(project: "<projectname>"); });
task.Wait();
foreach (var bd in bds)
{
Log(bd.Revision.ToString());
Log(bd.Url);
//Populate the definition revision reference list for this one build definition
var task1 = Task.Run(async () => { bdrs = await bhc.GetDefinitionRevisionsAsync(project: bd.Project.Id, definitionId: bd.Id); });
task1.Wait();
//Go through the revisions of this one builddefinition. In this case I am only interested
//In updating the latest revision so I'm saving a copy of the last one.
string LastDefinitionUrl = "";
foreach (var bdr in bdrs)
{
Log(string.Format("Name: {0}, Revision: {1}, Comment: {2}, Url: {3}", bdr.Name, bdr.Revision, bdr.Comment, bdr.DefinitionUrl));
LastDefinitionUrl = bdr.DefinitionUrl;
}
//Get the JSON for the complete BuildDefinition class. The list above only contains
//DefinitonReference class.
var client = new WebClient();
client.UseDefaultCredentials = true;
var json = client.DownloadString(LastDefinitionUrl);
//Convert the JSON to an actual builddefinition
BuildDefinition result = JsonConvert.DeserializeObject<BuildDefinition>(json);
//modify result here, if desired...
//Save the builddefinition classes in a dictionary for this project as I construct them
defs.Add(bd.Name, result);
//Save the changes. (i.e. this creates a new revision)
var task2 = Task.Run(async () => { await bhc.UpdateDefinitionAsync(result, definitionId: bd.Id, project: bd.Project.Id); });
task2.Wait();
}
}