Problem:
I have a large number of build definitions I need to point
to a different branch.
Solution:
Use the attached PowerShell script.
Explanation:
Today on a call with a customer I was asked how they could
point hundreds of builds to a new branch. My obvious answer was with
PowerShell. With PowerShell we can use the entire TFS API to script whatever
we need. The attached script defines an update-BuildBranch function that takes
the following parameters:
$tfsUrl
|
This is the full URL to your Team Foundation Server collection. https://tfs.visualstudio.com/DefaultCollection/
|
$teamProject
|
This is the name of the Team Project that contains the desired build
definition.
|
$buildDefinitionName
|
This is the name of the Build Definition to update or clone.
|
$from
|
This is the portion of the Source Control Folder value to search for.
$/TeamProject/Branch
|
$to
|
This is the value to replace the $from value with.
$/TeamProject/NewBranch
|
$update
|
If present the Build Definition is updated. If not a copy of the
Build Definition is made. -update
|
function update-BuildBranch
{
[CmdletBinding()]
param(
[string] $tfsUrl,
[string] $teamProject,
[string] $buildDefinitionName,
[string] $from,
[string] $to,
[switch] $update
)
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Client")
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Build.Client")
$teamProjectCollection
= [Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory]::GetTeamProjectCollection($tfsUrl)
$buildServer
= $teamProjectCollection.GetService([type]"Microsoft.TeamFoundation.Build.Client.IBuildServer")
$buildDef
= $buildServer.QueryBuildDefinitions($teamProject)
| Where-Object
{ $_.Name
-eq $buildDefinitionName
}
if($buildDef -eq
$null)
{
Write-Error
"Build Definition was not found"
return;
}
if($from.StartsWith("$"))
{
$from
= "\"
+ $from;
}
if($update.IsPresent)
{
foreach($mapping in $buildDef.Workspace.Mappings)
{
$original
= $mapping.ServerItem
$mapping.ServerItem =
$original -replace
$from,
$to
Write-Verbose
"Updating $original to $($mapping.ServerItem)"
}
$buildDef.ProcessParameters =
$buildDef.ProcessParameters
-replace $from, $to;
$buildDef.Save();
}
else
{
$branch
= $to.Substring($to.LastIndexOf("/")
+ 1);
# Find a
name
$count
= 1;
$newName
= "$($buildDef.Name)_$branch"
while(($buildServer.QueryBuildDefinitions($teamProject) |
Where-Object { $_.Name -eq $newName }) -ne
$null)
{
$newName
= "$($buildDef.Name)_$branch`_$count"
$count++;
}
Write-Verbose
"Cloning build to $newName"
$cloneDef
= $buildServer.CreateBuildDefinition($teamProject);
$cloneDef.BuildController =
$buildDef.BuildController
$cloneDef.BatchSize = $buildDef.BatchSize;
$cloneDef.ContinuousIntegrationQuietPeriod = $buildDef.ContinuousIntegrationQuietPeriod;
$cloneDef.ContinuousIntegrationType = $buildDef.ContinuousIntegrationType;
$cloneDef.DefaultDropLocation =
$buildDef.DefaultDropLocation;
$cloneDef.Description =
$buildDef.Description;
$cloneDef.Enabled = $buildDef.Enabled;
$cloneDef.Name = $newName;
$cloneDef.Process = $buildDef.Process;
$cloneDef.ProcessParameters =
$buildDef.ProcessParameters
-replace $from, $to;
$cloneDef.QueueStatus =
$buildDef.QueueStatus;
$cloneDef.TriggerType =
$buildDef.TriggerType;
foreach($mapping in $buildDef.Workspace.Mappings)
{
$original
= $mapping.ServerItem
$newMapping
= $original
-replace $from, $to;
$cloneDef.Workspace.AddMapping($newMapping,
$mapping.LocalItem, $mapping.MappingType)
Write-Verbose
"Updating $original to $newMapping"
}
$cloneDef.Save();
}
}