Almost four years ago I wrote a post on how to create a build definition programmatically using the TFS 2010 API. The code is partyl still valid, but since a lot of the information in a build definition is dependent on the build process template, the code in the blog
does not work properly for the TFS 2013 default build templates. In addition, since the introduction of Git in TFS 2013, there are some other differences in how you create a build definition for a Git team project compared to a TFVC team project.
So, in this post I will show an updated version of the code for creating a build defintion. I will actually show two samples, one for the GitTemplate.12.xaml and one for the TfvcTemplate.xaml which are the default template used in TFS 2013.
Creating a Git Build definition (GitTemplate.12.xaml)
Here is the code for creating a build definition using the GitTemplate.12.xaml build process template
//Create build definition and give it a name and desription IBuildDefinition buildDef = buildServer.CreateBuildDefinition(tp); buildDef.Name = "ATestBuild"; buildDef.Description = "A description for this build defintion"; buildDef.ContinuousIntegrationType = ContinuousIntegrationType.Individual; //CI //Controller and default build process template buildDef.BuildController = buildServer.GetBuildController("Hosted Build Controller"); var defaultTemplate = buildServer.QueryProcessTemplates(tp).First(p => p.TemplateType == ProcessTemplateType.Default); buildDef.Process = defaultTemplate; //Drop location buildDef.DefaultDropLocation = "#/"; //set to server drop //Source Settings var provider = buildDef.CreateInitialSourceProvider("TFGIT"); provider.Fields["RepositoryName"] = "Git"; provider.Fields["DefaultBranch"] = "refs/heads/master"; provider.Fields["CIBranches"] = "refs/heads/master"; provider.Fields["RepositoryUrl"] = url + "/_git/Git"; buildDef.SetSourceProvider(provider); //Process params var process = WorkflowHelpers.DeserializeProcessParameters(buildDef.ProcessParameters); //What to build process.Add("ProjectsToBuild", new[]{"Test.sln"}); process.Add("ConfigurationsToBuild", new[]{"Mixed Platforms|Debug"}); //Advanced build settings var buildParams = new Dictionary<string, string>(); buildParams.Add("PreActionScriptPath", "/prebuild.ps1"); buildParams.Add("PostActionScriptPath", "/postbuild.ps1"); var param = new BuildParameter(buildParams); process.Add("AdvancedBuildSettings", param); //test settings var testParams = new Dictionary<string, object> { { "AssemblyFileSpec", "*.exe" }, { "HasRunSettingsFile", true }, { "ExecutionPlatform", "X86" }, { "FailBuildOnFailure", true }, { "RunName", "MyTestRunName" }, { "HasTestCaseFilter", false }, { "TestCaseFilter", null } }; var runSettingsForTestRun = new Dictionary<string, object> { { "HasRunSettingsFile", true }, { "ServerRunSettingsFile", "" }, { "TypeRunSettings", "CodeCoverageEnabled" } }; testParams.Add("RunSettingsForTestRun", runSettingsForTestRun); process.Add("AutomatedTests", new[]{ new BuildParameter(testParams)}); //Symbol settings process.Add("SymbolStorePath", @"\serversymbolssomepath"); buildDef.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(process); //Retention policy buildDef.RetentionPolicyList.Clear(); buildDef.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.Succeeded, 10, DeleteOptions.All); buildDef.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.Failed, 10, DeleteOptions.All); buildDef.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.Stopped, 1, DeleteOptions.All); buildDef.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.PartiallySucceeded, 10, DeleteOptions.All); //Lets save it buildDef.Save();
Some things to note here:
- The IBuildDefinitionSourceProvider interface is new in TFS 2013, and the reason for it is of course to abstract the differences between TFVC and Git source control. As you can see, we use the “TFGIT”
to select the correct provider, and then we use the Fields property to populate it with information
- The process parameters are created by using dictionaires, with the corresponding key and values. If you are familiar with the GitTemplate.12.xaml, you will recognize the name of these parameters.
- As for drop locations, in TFS 2013 you can select between no drop location, a drop folder (share) or a server drop, which means the output is stored inside TFS and accessible from the web access.
In the sample above, we specify #/ which (not that obvious) means a server drop. If you want to use a share drop location, just specify the server path for the DefaultDropLocation
Creating a TFVC Build definition (TfvcTemplate.12.xaml)
AS it turns out, creating a TFVC build definition using the TfvcTemplate.12.xaml is almost identical, since the build team went to great effort and abstracted away most differences. The only difference in fact, at least when it comes to the most common settings is how you define the workspace mappings. And this code is the same as it was in TFS 2010/2012. In addition, you don’t need to create a source provider, because there is nothing that needs to be configured other than the workspace.
Here is the full sample for TFVC:
//Create build definition and give it a name and desription IBuildDefinition buildDef = buildServer.CreateBuildDefinition(tp); buildDef.Name = "ATestBuild"; buildDef.Description = "A description for this build defintion"; buildDef.ContinuousIntegrationType = ContinuousIntegrationType.Individual; //CI //Controller and default build process template buildDef.BuildController = buildServer.GetBuildController("Hosted Build Controller"); var defaultTemplate = buildServer.QueryProcessTemplates(tp).First(p => p.TemplateType == ProcessTemplateType.Default); buildDef.Process = defaultTemplate; //Drop location buildDef.DefaultDropLocation = "#/"; //set to server drop //Source Settings buildDef.Workspace.AddMapping("$/Path/project.sln", "$(SourceDir)", WorkspaceMappingType.Map); buildDef.Workspace.AddMapping("$/OtherPath/", "", WorkspaceMappingType.Cloak); //Process params var process = WorkflowHelpers.DeserializeProcessParameters(buildDef.ProcessParameters); //What to build process.Add("ProjectsToBuild", new[]{"Test.sln"}); process.Add("ConfigurationsToBuild", new[]{"Mixed Platforms|Debug"}); //Advanced build settings var buildParams = new Dictionary<string, string>(); buildParams.Add("PreActionScriptPath", "/prebuild.ps1"); buildParams.Add("PostActionScriptPath", "/postbuild.ps1"); var param = new BuildParameter(buildParams); process.Add("AdvancedBuildSettings", param); //test settings var testParams = new Dictionary<string, object> { { "AssemblyFileSpec", "*.exe" }, { "HasRunSettingsFile", true }, { "ExecutionPlatform", "X86" }, { "FailBuildOnFailure", true }, { "RunName", "MyTestRunName" }, { "HasTestCaseFilter", false }, { "TestCaseFilter", null } }; var runSettingsForTestRun = new Dictionary<string, object> { { "HasRunSettingsFile", true }, { "ServerRunSettingsFile", "" }, { "TypeRunSettings", "CodeCoverageEnabled" } }; testParams.Add("RunSettingsForTestRun", runSettingsForTestRun); process.Add("AutomatedTests", new[]{ new BuildParameter(testParams)}); //Symbol settings process.Add("SymbolStorePath", @"\serversymbolssomepath"); buildDef.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(process); //Retention policy buildDef.RetentionPolicyList.Clear(); buildDef.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.Succeeded, 10, DeleteOptions.All); buildDef.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.Failed, 10, DeleteOptions.All); buildDef.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.Stopped, 1, DeleteOptions.All); buildDef.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.PartiallySucceeded, 10, DeleteOptions.All); //Lets save it buildDef.Save();
Hope you find this useful!