Introduction
This tip shows how to queue new build request for DEV/SIT/UAT/PROD using the same build definition file without changing the actual build definition.
Problem
I faced a challenge when queuing a new build with custom parameters using TFS API. I found the solution. So the question will come up as to how do I deserialize this change and serialize it back into a definition, build request. When I created a build definition, I will set it to a particular build configuration like Dev or SIT or UAT or PROD. Let's assume I set to Dev. If I want to build it for UAT, I have to change the build definition manually. It is a very time consuming process to make a change every time because other properties like staging location, server drop folder are different for different build configurations.
Solution
I am here proving the solution, how to queue new build request by changing the build definition attributes at runtime as per the specific environments.
Using the Code
DLL references are required to connect to TFS programmatically.
Create a new Windows Forms Application project and add reference to TFS Common and client DLLs.
Note: If Microsoft.TeamFoundation.Client
and Microsoft.TeamFoundation.Common
do not appear on the .NET tab of the References dialog box, use the Browse tab to add the assemblies.
You can find them at %ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0 OR %ProgramFiles%\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v2.0.
using Microsoft.TeamFoundation;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.Build;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Build.Common;
using System.Security.Principal;
using Microsoft.TeamFoundation.Build.Workflow;
namespace MyTestCustomBuild
{
class Program
{
static void Main(string[] args)
{
string ChangesetNo = "23456";
Uri collectionUri = new Uri("https://TFSUrl:8080/tfs");
TfsTeamProjectCollection tfs = new TfsTeamProjectCollection
(collectionUri, System.Net.CredentialCache.DefaultNetworkCredentials, new UICredentialsProvider());
WindowsIdentity user = WindowsIdentity.GetCurrent();
tfs.EnsureAuthenticated();
if (tfs.HasAuthenticated)
{
WorkItemStore workItemStore = tfs.GetService<WorkItemStore>();
Project teamProject = workItemStore.Projects["TFSProjName"];
IBuildServer buildServer = tfs.GetService(typeof(IBuildServer)) as IBuildServer;
IBuildDefinition buildDef = buildServer.GetBuildDefinition(teamProject.Name, "MyTestBuild");
IBuildRequest req = buildDef.CreateBuildRequest();
req.GetOption = GetOption.Custom;
req.CustomGetVersion = "C" + ChangesetNo.Trim();
req.DropLocation = @"\\Server\StagingLocation\";
req.ProcessParameters = UpdateBuildConfiguration(buildDef);
req.ProcessParameters = UpdateServerDropFolder(buildDef);
buildServer.QueueBuild(req);
}
}
}
}
It must be serializable using the XAML serialization engine if you want to add custom types as process parameters.
Below function will change the build configuration:
private static string UpdateBuildConfiguration(IBuildDefinition rqBuildDef)
{
var process = WorkflowHelpers.DeserializeProcessParameters(rqBuildDef.ProcessParameters);
BuildSettings buildSettings = new BuildSettings();
buildSettings = (Microsoft.TeamFoundation.Build.Workflow.Activities.BuildSettings)process["BuildSettings"];
BuildSettings newbuildSettings = new BuildSettings();
newbuildSettings = buildSettings;
if (newbuildSettings.HasPlatformConfigurations)
{
newbuildSettings.PlatformConfigurations[0].Configuration = "UAT";
}
process.Remove("BuildSettings");
process.Add("BuildSettings", newbuildSettings);
rqBuildDef.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(process);
return rqBuildDef.ProcessParameters;
}
Below function will change the server drop folder:
private static string UpdateServerDropFolder(IBuildDefinition rqBuildDef)
{
var process = WorkflowHelpers.DeserializeProcessParameters(rqBuildDef.ProcessParameters);
string ProjectName = process["ProjectName"].ToString();
process["ServerDropFolder"] = @"\\WebServer\Folder\Web\";
rqBuildDef.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(process);
return rqBuildDef.ProcessParameters;
}