3
votes

I'm using the .NET Client Libraries for VSTS/TFS 2015 to programmatically create a build definition based off of a template that I've grabbed in another team project.

I can get a build definition template (2.0) by using:

BuildDefinitionTemplate builddeftemplate = buildHttpClient.GetTemplateAsync(teamProject, templateId).Result;

And I can create a build definition by using:

BuildDefinition builddef = new BuildDefinition();
builddef.Project = newTeamProject;

But there doesn't look like a way to pass in a template as a property of the build definition, nor create a build definition from the template.

When looking at the documentation for the REST API, the GET request actually looks like it returns a lot of JSON:

{
  "id": "vsBuild",
  "name": "Visual Studio",
  "canDelete": false,
  "category": "Build",
  "iconTaskId": "71a9a2d3-a98a-4caa-96ab-affca411ecda",
  "description": "Build and run tests using Visual Studio. This template requires that Visual Studio be installed on the build agent.",
  "template": {
    "build": [
      {
        "enabled": true,
        "continueOnError": false,
        "alwaysRun": false,
        "task": {
          "id": "71a9a2d3-a98a-4caa-96ab-affca411ecda",
          "versionSpec": "*"
        },
        "inputs": {
          "solution": "**\\*.sln",
          "msbuildLocation": "",
          "vsLocation": "",
          "msbuildArgs": "",
          "platform": "$(BuildPlatform)",
          "configuration": "$(BuildConfiguration)",
          "clean": "false"
        }
      },
      ...

So I think that it might be possible to only grab parts of the returned template as a JSON object and pass through a POST of the build definition with those parts, but it seems like that would have to solely be the REST API route.

Is this possible with the .NET Client Libraries? Or is there an easier way that I might have missed?

1
What's the type of the build you'd like to create build definition? vNext or XAML?Eddie Chen - MSFT
vNext. I think that Patrick (below) was able to give a workaround solution, the challenge definitely is the reference to the old team project that causes problems to create a build definition, although this would definitely be an amazing addition to the REST API in the future.m00nbeam360.0

1 Answers

3
votes

There isn't a way to pass in a template as a property of the build definition. However, there's another way to achieve it. You can clone/import/export build definition between team projects through .net libraries.

    var cred = new VssCredentials(new WindowsCredential(new NetworkCredential(username, password)));
    var buildClient = new BuildHttpClient(new Uri(collectionURL, UriKind.Absolute), cred);
     
    var buildDef = (await buildClient.GetDefinitionAsync(sourceProj, buildDefId)) as BuildDefinition;
     
    buildDef.Project = null;
    buildDef.Name += "_clone";
     
    await buildClient.CreateDefinitionAsync(buildDef, targetProj);

From above code you can authenticate to the team server and retreive the build definition object from the source project by the providing project name and the build definition id.

And then you need to remove the reference to the project. Since build definition contains a reference to the project it would not be possible to import it into a different project. Finally create a new build definition in target project providing the definition objecte retreived from previous project.

Next step is to export the build definition to a file so we can latter import it. By using a json serializer to serialize the build definition and save it to a file.

   var buildDef = (await buildClient.GetDefinitionAsync(project, buildDefId)) as BuildDefinition;
   buildDef.Project = null;
   File.WriteAllText(filePath, JsonConvert.SerializeObject(buildDef));

Finally add a import method, more details please refer this link

if (!File.Exists(filePath))
      throw new FileNotFoundException("File does not exist!", filePath);
    Console.WriteLine($"Importing build definition from file '{filePath}' to '{project}' project.");
    var buildDef = JsonConvert.DeserializeObject<BuildDefinition>(File.ReadAllText(filePath));
    buildDef.Name = newBuildName;
    await buildClient.CreateDefinitionAsync(buildDef, project);