Saturday, August 24, 2013

Update TFS 2012 Project Build definition after migrating from TFS 2008 via PowerShell

In this post, I just want to help those of you out there that have upgraded from 2008 and need to bulk update all of your build definitions. In this particular example, I will be updating the Build Controller, Drop location and Agent Settings of the build.

Here's is the main PS file which iterates through all projects in a specified TPC and call another PS to do the meat work..


param
(
[string] $TfsServerUri = http://TFS:8080/tfs/TPC)
$TfsSnapin = Get-PSSnapin -Name Microsoft.TeamFoundation.PowerShell -ErrorAction SilentlyContinue
if ($TfsSnapin -eq $null)
{
    Add-PSSnapin Microsoft.TeamFoundation.PowerShell
}
## Local Variables
$CurrentExecutionDir = Split-Path -parent $MyInvocation.MyCommand.Definition
[string] $LogFile = "$CurrentExecutionDir\PSSessionLog.txt"
##
If(Test-Path $LogFile) { Remove-Item -Path $LogFile }
##Connect Tfs
$TfsServer = Get-TfsServer -Name $TfsServerUri
try
{
    $TfsServer.EnsureAuthenticated()
}
catch
{
    Write-Error "Error occurred trying to connect to project collection: $_ "
    Exit-PSSession
}
##
## Enumerate all Tfs projects and perform update on build definitions
$CssService = $TfsServer.GetService([Microsoft.TeamFoundation.Server.ICommonStructureService3])
$TfsProjectList = $CssService.ListAllProjects()
foreach($teamProject in $TfsProjectList)
{
    try
    {
        .{."$CurrentExecutionDir\Update-BuildDefinitions.ps1" -TFSServerInstance $TfsServer - ProjectName $teamProject.Name -LogFile $LogFile}
    }
    catch
    {
        Write-Host ($_) -ForegroundColor Red
        Out-File $LogFile -InputObject $_ -Append
    }
}
##
Remove-PSSnapin Microsoft.TeamFoundation.PowerShell
---------------------------------------------------------------------------------------------------------------

And here is the crux PS which does the real work of updating build definitions called Update-BuildDefinitions.ps1

This PS file should be located beside the main PS file.

 
param(
$TFSServerInstance,
[string] $ProjectName,
[string] $DefaultBuildControllerName = 'ControllerNew,
[string] $DefaultBuildDropLocation = '\\IT\Temp\Build',
[string] $LogFile = 'C:\Temp\PSSessionLog.txt'
)
Add-Type -Path "C:\Program Files\Microsoft Team Foundation Server 11.0\Tools\Microsoft.TeamFoundation.Build.Workflow.dll"
#region Local Variables
$TfsServer = $TFSServerInstance
$BuildServer = $TfsServer.GetService([Microsoft.TeamFoundation.Build.Client.IBuildServer])
$ProjectBuildDefinitions = $BuildServer.QueryBuildDefinitions($ProjectName)
$BuildController = $BuildServer.GetBuildController($DefaultBuildControllerName)
$IsUpdated = $false
$ProcessParams = $null
$ProcessActivity = $null
#endregion Local Variables
#region Update Build Definitions with drop location, controller and agent
foreach($ProjectBuildDefinition in $ProjectBuildDefinitions)
{
#region Update Build definition general settings
    $ProjectBuildDefinition.DefaultDropLocation = $DefaultBuildDropLocation
    $ProjectBuildDefinition.BuildController = $BuildController
#endregion Update Build definition general settings
#region Update Agent settings nested inside Build definitions as Xaml
    $ProcessParams = $ProjectBuildDefinition.ProcessParameters
    $ProcessActivity = [Microsoft.TeamFoundation.Build.Workflow.WorkflowHelpers]::DeserializeProcessParameters($ProcessParams)
    foreach ($parameter in $ProcessActivity)
    {
        $AgentSettings = $parameter.AgentSettings
        if($ProjectBuildDefinition.FullPath.Length -gt 0)
        {
            $AgentName = "Legacy2008-" + $ProjectBuildDefinition.FullPath.Remove(0,    $ProjectBuildDefinition.FullPath.Length - 2)
            if($AgentSettings -eq $null)
            {
                $AgentSettings = New-Object -TypeName  Microsoft.TeamFoundation.Build.Workflow.Activities.AgentSettings
                $ProcessActivity.Add("AgentSettings", $AgentSettings)
            }
            $AgentSettings.Name = $AgentName
            $AgentSettings.MaxWaitTime = New-TimeSpan -Hours 04 -Minutes 00 -Seconds 00
            $ProjectBuildDefinition.ProcessParameters = [Microsoft.TeamFoundation.Build.Workflow.WorkflowHelpers]::SerializeProcessParameters($ProcessActivity)
       }
       else
       {
            Write-Host("Definition full path empty for $ProjectBuildDefinition")
        }
}
#endregion Update Agent settings nested inside Build definitions as Xaml
$IsUpdated = $true
}
if($IsUpdated -eq $true)
{
    try
    {
        $UpdatedBuildDefinitions = $BuildServer.SaveBuildDefinitions($ProjectBuildDefinitions)
        $IsUpdated = $false
        $Msg = "Updated Defaults in Build Definition for $ProjectName"
        Write-Host ($Msg) -ForegroundColor Green
        Out-File $LogFile -InputObject $Msg -Append
    }
    catch
   {
        $Msg = "Build Definition update failed for $ProjectName becuase of `n" + $_
        Write-Host ($Msg) -ForegroundColor Red
        Out-File $LogFile -InputObject $Msg -Append
        throw
    }
}
#endregion Update Build Definitions with drop location, controller and agent

No comments: