How to trigger a build in TFS 2015 using REST API

2020-01-29 08:23发布

问题:

I have TFS 2015 RC2 installed on-premise. I'm trying to use REST API to queue a build in a vNext definiton.

I'm using the code sample from VSO with slight modifications (mostly change of URL and authentication method to work with on-premise TFS).

There are two REST API calls I'm using.

The first is: GET http://mytfssrv:8080/tfs/DefaultCollection/myproject/_apis/build/definitions/

Which returns all specified project build definitions: build definition with ID 1, which is a XAML build definition I'm not interested to queue in and build definition with ID 2, which is vNext build definition - that's where I I want to queue my build

Note that I omitted the ?api-version=1.0 part - that's because if I don't, I get only the XAML build definition.

The second call is to queue a new build in the vNext build definition:

POST http://mytfssrv:8080/tfs/DefaultCollection/myptoject/_apis/build/requests?api-version=1.0

with the following data:

{"definition":{"id":**2**},"reason":"Manual","priority":"Normal","queuePosition":0,"queueTime":"0001-01-01T00:00:00","requestedBy":null,"id":0,"status":null,"url":null,"builds":null}

The response I get from the server is:

TF215016: The build definition 2 does not exist. Specify a valid build definition and try again.

I tried changing the API version, changing the post data in various ways but never succeeded.

Any idea how to cure TFS from its DID?

回答1:

TFS 2015 RC2 uses a new API (version 2.0-preview.2). The VSO sample I mentioned in the question is outdated and not relevant when you wish to queue a new build.

Currently, there is no documentation but the web portal uses REST API so just Fiddler away.

Here is the code:

var buildRequestPOSTData =
                    new BuildRequest()
                    {
                        Definition = new Definition()
                        {
                            Id = firstBuildDefinition.Id
                        },
                        Project = new Project { Id = "project guid" },
                        Queue = new Queue {  Id = 1 },
                        Reason = 1,
                        sourceBranch = "$Branch"
                    };

                responseBody = await QueueBuildAsync(client, buildRequestPOSTData, _baseUrl + "build/Builds");

And here is the class with new parameters for build requests:

public class BuildRequest
{
    [JsonProperty(PropertyName = "definition")]
    public Definition Definition { get; set; }

    [JsonProperty(PropertyName = "demands")]
    public string Demands { get; set; }

    [JsonProperty(PropertyName = "parameters")]
    public IEnumerable<string> Parameters { get; set; }

    [JsonProperty(PropertyName = "project")]
    public Project Project { get; set; }

    [JsonProperty(PropertyName = "queue")]
    public Queue Queue { get; set; }

    [JsonProperty(PropertyName = "reason")]
    public int Reason { get; set; }

    [JsonProperty(PropertyName = "sourceBranch")]
    public string sourceBranch { get; set; }

    [JsonProperty(PropertyName = "sourceVersion")]
    public string RequestedBy { get; set; }
}

public class Definition
{
    [JsonProperty(PropertyName = "id")]
    public int Id { get; set; }
}

public class Queue
{
    [JsonProperty(PropertyName = "id")]
    public int Id { get; set; }
}

public class Project
{
    [JsonProperty(PropertyName = "id")]
    public string Id { get; set; }
}


回答2:

This works like a charm without REST

var tfsurl = new Uri("http://localhost:8080/tfs/<***projectname***>/");    
var ttpc = new TfsTeamProjectCollection(tfsurl);
var bhc = ttpc.GetClient<BuildHttpClient>();
var builds = bhc.GetBuildsAsync("<***projectname***>").Result;
var build = builds
    .Where(x => x != null && x.Definition.Name.Equals("***buildDefinitionName***>"))
    .OrderByDescending(y => y.LastChangedDate)
    .FirstOrDefault();

bhc.QueueBuildAsync(build);


回答3:

This is "example of code example" that I required in bounty.

using Microsoft.TeamFoundation.Build.WebApi;
using Microsoft.VisualStudio.Services.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
internal class TfsBuildHelper
{
    private readonly VssConnection connection;

    private readonly BuildHttpClient client;

    internal TfsBuildHelper(Uri tpcUrl)
    {
        this.connection = new VssConnection(tpcUrl, new VssClientCredentials(true));
        this.client = connection.GetClient<BuildHttpClient>();
    }

    /// <summary>
    /// Returns the build definitions for a specific team project.
    /// </summary>
    public async Task<IEnumerable<DefinitionReference>> GetBuildDefinitionsFromTeamProject(string teamProject)
    {
        return await this.client.GetDefinitionsAsync(project: teamProject, type: DefinitionType.Build);
    }

    /// <summary>
    /// Return build numbers for specific team project and build definition.
    /// </summary>
    public async Task<IEnumerable<string>> GetAvailableBuildNumbers(string teamProject, string buildDefinition)
    {
        var builds = await this.client.GetBuildsAsync(project: teamProject, type: DefinitionType.Build);
        return builds.Select(b => b.BuildNumber);
    }
}


标签: c# rest tfs