我想使用Powershell调用Team Build。我想覆盖默认的MSBuild参数并指定GIT更改密钥。我无法相信这是多么困难。
指定MSBuild参数很难,因为它是XML中的Json。
以下适用于我的本地笔记本电脑,但不适用于我的TeamCity Build Server。
$buildserver = $tfs.GetService([Microsoft.TeamFoundation.Build.Client.IBuildServer])
$definition = $buildserver.GetBuildDefinition($teamProject, $buildDefinition)
# Deserialize ProcessParameters from the definition
$ProcessParameters = [Microsoft.TeamFoundation.Build.Workflow.WorkflowHelpers]::DeserializeProcessParameters($definition.ProcessParameters)
$AdvancedBuildSettings = $ProcessParameters['AdvancedBuildSettings'].json | ConvertFrom-Json
$AdvancedBuildSettings.MSBuildArguments = "/p:one=parm1 /p:two='parm2'"
$ProcessParameters['AdvancedBuildSettings'].json = $AdvancedBuildSettings | ConvertTo-Json
$request = $definition.CreateBuildRequest()
$request.ProcessParameters = [Microsoft.TeamFoundation.Build.Workflow.WorkflowHelpers]::SerializeProcessParameters($ProcessParameters)
$QueuedBuild = $buildserver.QueueBuild($request)
但是我无法弄清楚我需要安装什么才能安装Microsoft.TeamFoundation.Build.Workflow.dll所以我在使用Deserialize Serialize帮助程序调用时只是自己动手做了。
但是,访问CheckoutOverrides设置更糟糕。我能得到它的唯一方法是在定义中删除一个值,因为它不在XML中。一旦我将其删除,XML就基于类型的数组而言非常讨厌。这是一个样本:
<Dictionary x:TypeArguments="x:String, x:Object" xmlns="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:mtbc="clr-namespace:Microsoft.TeamFoundation.Build.Common;assembly=Microsoft.TeamFoundation.Build.Common" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<x:Array x:Key="ProjectsToBuild" Type="x:String">
<x:String>\TeamCityToTeamBuild\PullTeamCityBuild.proj</x:String>
</x:Array>
<x:Boolean x:Key="CleanRepository">False</x:Boolean>
<mtbc:BuildParameter x:Key="AdvancedBuildSettings">
{
"MSBuildArguments": " /p:TeamCityProjectId=\u0027%teamcity.project.id%\u0027 /p:TeamCityBuildNumber=%build.number% /p:TeamCityBuildOutput=\u0027\\\\scs40vptmcapp04.medassets.com\\D$\\work\\1f7b2c812110928e\u0027",
"MSBuildPlatform": "Auto",
"PreActionScriptPath": "",
"PreActionScriptArguments": "",
"PostActionScriptPath": "",
"PostActionScriptArguments": "",
"RunCodeAnalysis": "AsConfigured"
}
</mtbc:BuildParameter>
<mtbc:BuildParameter x:Key="AgentSettings">{"MaxExecutionTime":"00:00:00","MaxWaitTime":"04:00:00","Name":"*","Tags":[],"TagComparison":"MatchAtLeast"}</mtbc:BuildParameter>
<x:String x:Key="CheckoutOverride">SetIt</x:String>
</Dictionary>
因为这是一个String,所以它是String Element下的一个键。将XPath与doc上的命名空间一起使用,此代码如下所示:
$ProcessParametersDoc = [xml]$definition.ProcessParameters
$ns = New-Object System.Xml.XmlNamespaceManager($ProcessParametersDoc.NameTable)
$ns.AddNamespace('x',"http://schemas.microsoft.com/winfx/2006/xaml")
$CheckoutOverridesNode = $ProcessParametersDoc.SelectSingleNode("//x:String[@x:Key='CheckoutOverride']",$ns)
$CheckoutOverridesNode.InnerText = $VersionControlNumber
如果它不存在则灵活地创建String数组将成为另一个层次的荒谬。
以下代码可以工作(仍然需要添加代码来处理CheckoutOverride缺少的String节点),但它就像用钳子拉动母鸡的牙齿一样。
$tfs = [Microsoft.TeamFoundation.Client.TeamFoundationServerFactory]::GetServer($serverName)
$buildserver = $tfs.GetService([Microsoft.TeamFoundation.Build.Client.IBuildServer])
$definition = $buildserver.GetBuildDefinition($teamProject, $buildDefinition)
$ProcessParametersDoc = [xml]$definition.ProcessParameters
$AdvancedBuildSettingsNode = $ProcessParametersDoc.Dictionary.BuildParameter | ?{$_.Key -eq 'AdvancedBuildSettings'}
$AdvancedBuildSettings = $AdvancedBuildSettingsNode.InnerXml | ConvertFrom-Json
$MsBuildArgs = " /p:Arg1='Arg1Value'"
$MsBuildArgs += " /p:Arg2='Arg2Value'"
$AdvancedBuildSettings.MSBuildArguments = $MsBuildArgs
$AdvancedBuildSettingsNode.InnerXml = $AdvancedBuildSettings | ConvertTo-Json
$CheckoutOverridesNode = $ProcessParametersDoc.Dictionary.BuildParameter | ?{$_.Key -eq 'CheckoutOverrides'}
$ns = New-Object System.Xml.XmlNamespaceManager($ProcessParametersDoc.NameTable)
$ns.AddNamespace('x',"http://schemas.microsoft.com/winfx/2006/xaml")
$CheckoutOverridesNode = $ProcessParametersDoc.SelectSingleNode("//x:String[@x:Key='CheckoutOverride']",$ns)
$CheckoutOverridesNode.InnerText = $VersionControlNumber
$request = $definition.CreateBuildRequest()
$request.ProcessParameters = $ProcessParametersDoc.OuterXml
$QueuedBuild = $buildserver.QueueBuild($request)
我删除了一些代码来处理缺少XML节点的情况,使其更具可读性。即便如此,这是稳定的吗?有没有更好的办法?我只是担心,即使我稳定了代码,它也可能会破坏下一版本的TFS。