TFS 服务器 API 仅列出 XAML 生成定义

Posted

技术标签:

【中文标题】TFS 服务器 API 仅列出 XAML 生成定义【英文标题】:TFS server API only list the XAML build definitions 【发布时间】:2017-01-09 14:28:55 【问题描述】:

我正在尝试从 TFS2015 构建定义中获取信息。我们有大约 100 个 XAML 格式的构建定义和大约 50 个新的 2015 格式。 该服务器是内部 Team Foundation Server。 (Microsoft Visual Studio 团队基础服务器 版本 15.105.25910.0)

我没有使用其他 API,而是使用此处推荐的 Microsoft.TeamFoundationServer.ExtendedClient:https://blogs.msdn.microsoft.com/buckh/2015/08/10/nuget-packages-for-tfs-and-visual-studio-online-net-client-object-model/。

这是我的代码示例:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Serilog;

namespace TFSExperiment

    class Program
    
        // see https://blogs.msdn.microsoft.com/buckh/2015/08/10/nuget-packages-for-tfs-and-visual-studio-online-net-client-object-model/
        //Needs nuget package Install-Package Microsoft.TeamFoundationServer.ExtendedClient -Version 14.102.0
        // to use serilogg: Install-Package  Serilog ; Install-Package Serilog.Sinks.RollingFile
        static void Main(string[] args)
        
          var  myLog = new LoggerConfiguration()
                .WriteTo.RollingFile("..\\..\\Applog\\mylog-Date.log").CreateLogger();          
             TfsConfigurationServer configurationServer =
                TfsConfigurationServerFactory.GetConfigurationServer(new Uri("https://tfs.inhouseserver2015.org/tfs/"));
            ReadOnlyCollection<CatalogNode> collectionNodes =
                configurationServer.CatalogNode.QueryChildren(new[] CatalogResourceTypes.ProjectCollection, false,
                    CatalogQueryOptions.None);
            CatalogNode defultTfsCol = collectionNodes.AsQueryable().Single(c=>c.Resource.DisplayName.Equals("DefaultCollection"));
            Console.WriteLine(defultTfsCol.Resource.DisplayName);
                TfsTeamProjectCollection tfsProjectCollection =
                configurationServer.GetTeamProjectCollection(new Guid(defultTfsCol.Resource.Properties["InstanceId"]));
                tfsProjectCollection.Authenticate();
                var buildServer = (IBuildServer)tfsProjectCollection.GetService(typeof(IBuildServer));                
                ReadOnlyCollection<CatalogNode> projectNodes = defultTfsCol.QueryChildren(
                   new[]  CatalogResourceTypes.TeamProject ,
                   false, CatalogQueryOptions.None);
                foreach (var proj in projectNodes)
                
                    var buildDefinitionList = new List<IBuildDefinition>(buildServer.QueryBuildDefinitions(proj.Resource.DisplayName));
                    foreach (var buildDef in buildDefinitionList)
                                           
                        Console.WriteLine(buildDef.Name);                   
                        myLog.Information($"buildDef.Id --buildDef.Name --buildDef.BuildServer.BuildServerVersion ");
                    
                            
            Console.WriteLine(" Hit any key to exit ");
            Console.ReadKey();
        
    

【问题讨论】:

【参考方案1】:

正如 Eddie - MSFT 和 Tore Østergaard 的回答,我不得不使用其余的 api。但看起来我还必须使用旧的 api 从 builddefinitions 中获取所有信息。从 restapi 我得到了构建的名称,但没有得到 xaml 构建的深度信息。

我想从指出 Octopus Deploy 项目名称的变量中收集信息。我在这里发布代码以防有人遇到类似问题。

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Build.WebApi;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Newtonsoft.Json;
using Serilog;
using Serilog.Core;


namespace ListOctopusProjectsAndTfsBuilds

    class Program
    
        // see https://blogs.msdn.microsoft.com/buckh/2015/08/10/nuget-packages-for-tfs-and-visual-studio-online-net-client-object-model/
        //Needs nuget package Install-Package Microsoft.TeamFoundationServer.ExtendedClient -Version 14.102.0
        // to use serilogg: Install-Package  Serilog ; Install-Package Serilog.Sinks.RollingFile

        static Logger _myLog = new LoggerConfiguration()
                .WriteTo.RollingFile($"..\\..\\Applog\\myBuildDeflog-DateTime.Now:yyyyMMddHHHHmmss.log").CreateLogger();
        static void Main(string[] args)
        
            Console.WriteLine("Start looking for BuildDefs");
            Dictionary<string, string> octopusDeployDictionary = GetvNextBuildDefVariable( new Uri("https://inhouseserver2015/tfs/DefaultCollection"), "YourTfsProject", "OctoProj");
            Dictionary<string, string> octopusDeployXamlDictionary = GetXamlBuildDefVariable(new Uri("https://inhouseserver2015/tfs/DefaultCollection"), "YourTfsProject", "ArgOctopusProjectsToPublish");
            Console.WriteLine("Builds vnext defs -- Octopus project");
            foreach (var cd in octopusDeployDictionary)
            
                Console.WriteLine($"cd.Key; cd.Value");
            
            Console.WriteLine("Builds xaml defs -- Octopus project");
            foreach (var cd in octopusDeployXamlDictionary)
            
                Console.WriteLine($"cd.Key; cd.Value");
            
            Console.ReadLine();
        

        private static Dictionary<string, string> GetXamlBuildDefVariable(Uri tfsUri, string tfsProject, string buildDefVar)
        
            var collection = tfsUri.LocalPath.Split('/')[2];
            //Define Reg expression ahead so it can faster parse xml and find the Octopus Deploy projectname. 
            Regex findArgOctopusProjectsToPublish = null;
            try
            
                findArgOctopusProjectsToPublish = new Regex($"x:Key=\"buildDefVar\".*<x:String>([^<]*)",
                    RegexOptions.IgnoreCase | RegexOptions.Singleline);
            
            catch (ArgumentException ex)
            
                _myLog.Error(ex, "Error with RegularExpression syntax");
            
            Dictionary<string, string> tfsVarBuildDefDict = new Dictionary<string, string>();
            TfsConfigurationServer configurationServer =
                TfsConfigurationServerFactory.GetConfigurationServer(tfsUri));
            ReadOnlyCollection<CatalogNode> collectionNodes =
                configurationServer.CatalogNode.QueryChildren(new[] CatalogResourceTypes.ProjectCollection, false,
                    CatalogQueryOptions.None);
            CatalogNode defultTfsCol =
                collectionNodes.AsQueryable().Single(c => c.Resource.DisplayName.Equals(collection));
            TfsTeamProjectCollection tfsProjectCollection =
                configurationServer.GetTeamProjectCollection(new Guid(defultTfsCol.Resource.Properties["InstanceId"]));
            tfsProjectCollection.Authenticate();
            var buildServer = (IBuildServer) tfsProjectCollection.GetService(typeof(IBuildServer));
            ReadOnlyCollection<CatalogNode> projectNodes = defultTfsCol.QueryChildren(
                new[] CatalogResourceTypes.TeamProject,
                false, CatalogQueryOptions.None);

                var buildDefinitionList =
                    new List<IBuildDefinition>(buildServer.QueryBuildDefinitions(tfsProject));
                foreach (var buildDef in buildDefinitionList)
                
                Debug.Assert(findArgOctopusProjectsToPublish != null, "findArgOctopusProjectsToPublish != null");
                var octopusProjectsToPublish =
                        findArgOctopusProjectsToPublish?.Match(buildDef.ProcessParameters).Groups[1].Value;
                    if (octopusProjectsToPublish.IsNullOrEmpty())
                    
                        octopusProjectsToPublish = "NoOctopus Projekt";
                    
                tfsVarBuildDefDict.Add(buildDef.Name, octopusProjectsToPublish);
                    _myLog.Information($"buildDef.Id --buildDef.Name --buildDef.BuildServer.BuildServerVersion ");
                

            return tfsVarBuildDefDict;
        

        private static Dictionary<string, string> GetvNextBuildDefVariable(Uri tfsUri,string tfsProject,string buildDefVar)
        
            Dictionary<string, string> tfsVarBuildDefDict = new Dictionary<string, string>();
            TfsTeamProjectCollection ttpc =
                new TfsTeamProjectCollection(tfsUri);
            BuildHttpClient bhc = ttpc.GetClient<BuildHttpClient>();
            var definitions = bhc.GetDefinitionsAsync(project: tfsProject);
            var client = new WebClient UseDefaultCredentials = true;
            foreach (var buildDef in definitions.Result)
            
                if (buildDef.Type == DefinitionType.Build)
                
                    var json = client.DownloadString(buildDef.Url);
                    BuildDefinition result = JsonConvert.DeserializeObject<BuildDefinition>(json);
                    if (result.Variables.ContainsKey(buildDefVar))
                    
                        tfsVarBuildDefDict.Add(buildDef.Name, result.Variables[buildDefVar].Value.ToString());
                        _myLog.Information($"buildDef.Name Octoproject: result.Variables[buildDefVar].Value.ToString()");
                    
                
                else
                
                    _myLog.Information($"buildDef.Name BuildType  buildDef.Type ");
                
            
            return tfsVarBuildDefDict;
        
    

【讨论】:

【参考方案2】:

您正在使用只能获取 XAML 构建的旧版 soap API。

假设您已安装最新的 .NET Client Libraries,您可以使用库中的 Rest API 来获取 XAML 和 vNext 构建,如下所示:

using System;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Build.WebApi;

namespace ConsoleApplication1

    class Program
    
        static void Main(string[] args)
        
            Uri tfsurl = new Uri("http://xxxx:8080/tfs/CollectionName");
            TfsTeamProjectCollection ttpc = new TfsTeamProjectCollection(tfsurl);
            BuildHttpClient bhc = ttpc.GetClient<BuildHttpClient>();
            List<Build> builds = bhc.GetBuildsAsync("ProjectName").Result;
            foreach (Build bu in builds)
            
                Console.WriteLine(bu.BuildNumber);
            
            Console.ReadLine();
        
    

【讨论】:

您好,谢谢。我需要关于 xaml 构建时没有得到的变量的构建定义信息。我不得不使用booth api:s。【参考方案3】:

Microsoft.TeamFoundationServer.ExtendedClient 中的 API 主要用于提供与 XAML 构建的向后兼容性。据我所知,他们不支持 Build vNext,因为它们是在他们的时代之前编写的。

正如您提供的链接所建议的那样,REST API 是未来的遵循方式。

【讨论】:

好吧,也许我读得太快了,我读到了有关 Microsoft.TeamFoundationServer.ExtendedClient 的信息:“..因为目前 TFS 2015 或 VSO 中并非每个 API 都可以作为 REST API 使用,所以会有一些案例你必须在哪里使用这个包......”所以我认为一切都在这个里面。 (因此名称扩展“ 我尝试了Rest API,但没有让Windows身份验证工作我只有System.Net.Http.HttpRequestException:响应状态代码不表示成功:401(未授权)。 你试过设置 UseDefaultCredentials = true;在您的 WebClient 对象上?

以上是关于TFS 服务器 API 仅列出 XAML 生成定义的主要内容,如果未能解决你的问题,请参考以下文章

从 2012 年升级 TFS 并处理 Xaml 构建服务器

TFS 2017 版本 - 没有机器组和部署组

TFS2017持续集成构建

为啥用于获取 TFVC 变更集的 TFS Rest API 仅返回 256 个项目?

tfvctemplate.12.xaml 构建模板在 Azure DevOps 2019 中不起作用

如何在 VSTS 仪表板小部件中使用 REST API 从 TFS 获取构建定义?