【问题标题】:TFS server API only list the XAML build definitionsTFS 服务器 API 仅列出 XAML 生成定义
【发布时间】: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();
        }
    }
}

【问题讨论】:

    标签: tfs tfsbuild


    【解决方案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 对象上?
      猜你喜欢
      • 1970-01-01
      • 2016-07-09
      • 1970-01-01
      • 2017-09-22
      • 2016-10-24
      • 1970-01-01
      • 1970-01-01
      • 2015-06-05
      • 1970-01-01
      相关资源
      最近更新 更多