【问题标题】:TFS Build 2.0 C#, howto add variables to the build/Pass Msbuild argsTFS Build 2.0 C#,如何将变量添加到构建/传递 Msbuild 参数
【发布时间】:2017-11-30 18:44:04
【问题描述】:

我正在尝试将参数传递给 MSBuild 2.0。经过研究,我似乎需要使用变量来执行此操作,但我无法弄清楚如何将其合并到下面的队列请求中。我已经尝试过参数,但这似乎不起作用。这是我想告诉 MSBuild @" /p:OctoPackPackageVersion=" + releaseNumber.这适用于使用 IBuildRequest.ProcessParameters 的 XAML 构建。

var buildClient = new BuildHttpClient(new Uri(collectionURL), new 
VssCredentials(true));
var res = await buildClient.QueueBuildAsync(new Build
            {
                Definition = new DefinitionReference
                {
                    Id = targetBuild.Id
                },
                Project = targetBuild.Project,
                SourceVersion = ChangeSetNumber,
                Parameters = buildArg

            });
            return res.Id.ToString();

【问题讨论】:

  • 您现在使用的是哪个版本,XAML 还是 vNext?您的意思是您无法弄清楚如何在 vNext 构建中使用它?
  • Patrick,我们已将我们的定义从 XAML 转换为可编写脚本(随 TFS 2015 引入)。当我们使用 XAML 构建定义时,我使用 IBuildRequest.ProcessParameters 来传递上面列出的 octo 构建 arg,它有效,但是我不知道如何通过可编写脚本的构建传递它。在上面的代码中,我尝试将其传递给参数字段,但构建成功但似乎没有查看该参数。我尝试使用下面链接中的其他字段,但这些字段也不起作用。 visualstudio.com/en-us/docs/build/define/options
  • 队列请求的用途是什么?您只是想传递 octo version 参数吗?你能用一些脚本吗?有关变量的详细信息,请参阅下面的答案。

标签: tfs build tfs-2015


【解决方案1】:

vNext 构建系统与旧版 XAML 构建系统不同,您不能在构建定义中直接将变量传递给构建任务。您使用的代码在构建队列之前更新了构建定义,这意味着如果变量发生变化,构建定义可能会不断变化。

解决方法是在构建定义中添加一个变量,例如“var1”,然后将此变量用作 MSBuild 任务的参数: 这样,您将能够在将构建排队时将值传递给“var1”变量,而无需更新构建定义。

Build build = new Build();
build.Parameters = "{\"var1\":\"/p:OctoPackPackageVersion=version2\"}";

// OR using Newtonsoft.Json.JsonConvert
var dict = new Dictionary<string, string>{{"var1", "/p:OctoPackPackageVersion=version2"}};
build.Parameters = JsonConvert.SerializeObject(dict)

【讨论】:

  • 太棒了,我知道我错过了一些东西。谢谢埃迪,这非常有效。
【解决方案2】:

我找到了这个解决方案,它非常适合我。为了方便构建定义,我设置了自定义参数,而不在服务器上更新:

foreach (var variable in targetBuildDef.Variables.Where(p => p.Value.AllowOverride))
        {
            var customVar = variables.FirstOrDefault(p => p.Key == variable.Key);
            if (customVar == null)
                continue;
            variable.Value.Value = customVar.Value.TrimEnd('\\');
        }

然后在构建参数中设置变量值:

        using (TfsTeamProjectCollection ttpc = new TfsTeamProjectCollection(new Uri(tFSCollectionUri)))
        {
            using (BuildHttpClient buildServer = ttpc.GetClient<BuildHttpClient>())
            {
                var requestedBuild = new Build
                {
                    Definition = targetBuildDef,
                    Project = targetBuildDef.Project
                };
                var dic = targetBuildDef.Variables.Where(z => z.Value.AllowOverride).Select(x => new KeyValuePair<string, string>(x.Key, x.Value.Value));
                var paramString = $"{{{string.Join(",", dic.Select(p => $@"""{p.Key}"":""{p.Value}"""))}}}";
                var jsonParams = HttpUtility.JavaScriptStringEncode(paramString).Replace(@"\""", @"""");
                requestedBuild.Parameters = jsonParams;
                var queuedBuild = buildServer.QueueBuildAsync(requestedBuild).Result;

【讨论】:

    【解决方案3】:

    首先,TFS2015 上的新版本称为 vNext build 而不是 MSbuild 2.0。

    你要找的应该是Build variables。变量为您提供了一种方便的方法,可以将关键数据位放入构建过程的各个部分。对于选中排队时允许框的变量,您可以启用允许您的团队在手动排队构建时修改值。

    一些教程可能有助于使用变量:

    【讨论】:

    • 谢谢帕特里克,是的,正如我上面提到的,我看到这需要使用变量传递,但我不确定如何在 c# 而不是 powershell 中执行。我已将它作为队列时间添加到构建定义规范中,但我不确定如何将此变量传递给 QueueBuildAsync。我查看了文档,也找不到这个。
    • @KiritChandran 我不太确定您要传递哪些参数。您只是想从 C# 排队构建吗?此外,如果您将 QueueBuildAsync 与旧的 TFS API 一起使用,则与 XAML 构建相同。恐怕这不适用于 vNext 构建。也许这就是根本原因。需要用到Rest API,看看这个教程How to trigger a build in TFS 2015 using REST API&tech.en.tanaka733.net/entry/…
    【解决方案4】:

    Patrick,我能够通过更新构建定义找到解决我的问题的方法。这绝对不是理想的,但它有效。正如您在下面看到的,我正在尝试添加到已经存在的 msbuild args 中。如果您知道更好的方法,请告诉我。非常感谢您抽出时间来查看我的问题。

     public static async Task<string> QueueNewBuild(string project, BuildDefinitionReference targetBuild, string collectionURL, string ChangeSetNumber, string ReleaseNumber, bool CreateRelease)
        {
            var buildClient = new BuildHttpClient(new Uri(collectionURL), new VssCredentials(true));
            await Task.Delay(1000).ConfigureAwait(false);
            var buildDef = await buildClient.GetDefinitionAsync(targetBuild.Project.Id, targetBuild.Id);
            BuildDefinitionVariable OrigMSbuildvar = buildDef.Variables["MSBuildArgs"];
            buildDef.Variables["MSBuildArgs"].Value = OrigMSbuildvar.Value + " /p:OctoPackPackageVersion=" + ReleaseNumber.ToString();
    
            await Task.Delay(1000).ConfigureAwait(false);
            buildDef = await buildClient.UpdateDefinitionAsync(buildDef);
    
            await Task.Delay(1000).ConfigureAwait(false);
            Build build = new Build
            {
                Definition = new DefinitionReference
                {
                    Id = targetBuild.Id
                },
                Project = targetBuild.Project,
                SourceVersion = ChangeSetNumber
            };
    
            await Task.Delay(1000).ConfigureAwait(false);
            var res = await buildClient.QueueBuildAsync(build);
            buildDef.Variables["MSBuildArgs"].Value = OrigMSbuildvar.Value;           
            await Task.Delay(1000).ConfigureAwait(false);
            buildDef = await buildClient.UpdateDefinitionAsync(buildDef);
            return res.Id.ToString();
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-18
      • 2014-08-10
      • 2017-08-21
      • 2017-08-06
      • 2016-12-09
      • 2012-02-20
      • 1970-01-01
      相关资源
      最近更新 更多