Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Azure Devops - Get release definitions by agent pool ID

Tags:

I'm trying to find all the builds and releases that are configured to use a specific agent pool, using the .NET Client Libraries.

Assuming agentPoolId, I can get all the build definitions like this:

// _connection is of type VssConnection
using (var buildClient = _connection.GetClient<BuildHttpClient>())
{
    List<BuildDefinitionReference> allBuilds = await buildClient.GetDefinitionsAsync(projectName, top: 1000, queryOrder: DefinitionQueryOrder.DefinitionNameAscending);
    List<BuildDefinitionReference> builds = allBuilds.Where(x => HasAgentPoolId(x, agentPoolId)).ToList();
}

private bool HasAgentPoolId(BuildDefinitionReference buildDefinition, int agentPoolId)
{
    TaskAgentPoolReference pool = buildDefinition?.Queue?.Pool;

    if (pool == null)
    {
        return false;
    }

    return pool.Id.Equals(agentPoolId);
}

But I couldn't find a way to find the release definitions that have one or more environments configured to use a particular agent. Any suggestion?

like image 997
Rui Jarimba Avatar asked Apr 05 '19 14:04

Rui Jarimba


2 Answers

I was manged to get all releases by Agent Pool ID via Rest Api and not via NET Client Libraries.Hope that helps.

C# Code snippet:

public class ReleaseResponse
{
     [JsonProperty("value")]
     public List<ReleaseItem> Value { get; set; }
}

public class ReleaseItem
{
     [JsonProperty("name")]
     public string Name { get; set; }

     [JsonProperty("Id")]
     public int Id { get; set; }
}

static void Main(string[] args)
{
     string tfsURL = "TFS URL";
     string releaseDefurl = $"{tfsURL}/_apis/release/definitions?$expand=artifacts&api-version=3.2-preview.3";
     const int agentPoolID = "AGENT Pool ID";
     List<string> relevantReleases = new List<string>(); 
     WebClient client = new WebClient();
     client.UseDefaultCredentials = true;
     client.Headers.Add("Content-Type", "application/json");
     var releaseList = client.DownloadString(releaseDefurl);
     var allReleases = JsonConvert.DeserializeObject<ReleaseResponse>(releaseList).Value;
     foreach (var release in allReleases)
     {
           string releaseInfoApi = $"{tfsURL}/_apis/Release/definitions/{release.Id}";
           var getReleseInfo = client.DownloadString(releaseInfoApi);
           var releaseInfo = JsonConvert.DeserializeObject<TFSLogic.RootObject>(getReleseInfo);
           var deploymentAgents = releaseInfo.environments.ToList().Where(e => e.deployPhases.FirstOrDefault().deploymentInput.queueId == agentPoolID).Count();
           if (deploymentAgents > 0)
           {
               relevantReleases.Add(release.Name);
           }

     }

}

Find TFSLogic here : https://codebeautify.org/online-json-editor/cb7aa0d9

Powershell Code snippet:

$tfsUrl = "TFS URL"
$releaseDefurl = $tfsUrl + '/_apis/release/definitions?$expand=artifacts&api-version=3.2-preview.3'
$agentPoolID = "Agent Pool ID"
$relevantReleases = @();
$allReleasesID = (Invoke-RestMethod -Uri ($releaseDefurl) -Method Get -UseDefaultCredentials).value.id

function getReleaseByAgentPoolID($releaseID,$agentPoolID)
{
    $ReleaseInfo = Invoke-RestMethod -Uri "$tfsUrl/_apis/Release/definitions/$releaseID" -Method Get -UseDefaultCredentials

    $deploymentAgents = $ReleaseInfo.environments | % {$_.deployPhases.deploymentInput.queueId} | where {$_ -eq $agentPoolID}

    if($deploymentAgents.Count -gt 0)
    {
        return $ReleaseInfo.name
    }
}


foreach ($releaseID in $allReleasesID)
{
    $relevantReleases += getReleaseByAgentPoolID -releaseID $releaseID -agentPoolID $agentPoolID   
}

UPDATE :

It took me some time,But i was able to achieve that with azure-devops-dotnet-samples I hope this example is finally what you are looking for.

using Microsoft.VisualStudio.Services.WebApi;
using System;
using System.Linq;
using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.Clients;
using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.Contracts;
using Microsoft.VisualStudio.Services.Common;
using System.Collections.Generic;

namespace FindReleaseByAgentPoolID
{
    class Program
    {
        const int agentPoolID = 999;
        static void Main(string[] args)
        {
            var relevantReleases = new List<string>();
            VssCredentials c = new VssCredentials(new WindowsCredential(System.Net.CredentialCache.DefaultNetworkCredentials));
            var tfsURL = new Uri("TFS URL");
            var teamProjectName = "PROJECT";

            using (var connection = new VssConnection(tfsURL, c))
            using (var rmClient = connection.GetClient<ReleaseHttpClient2>())
            {
                var releases = rmClient
                    .GetReleaseDefinitionsAsync(teamProjectName, string.Empty, ReleaseDefinitionExpands.Environments)
                    .Result.ToArray();

                foreach (var release in releases)
                {
                    var r = rmClient.GetReleaseDefinitionAsync(teamProjectName, release.Id);
                    var deploymentAgents = r.Result.Environments.SelectMany(e =>
                     e.DeployPhases.Select(dp =>
                     dp.GetDeploymentInput()).Cast<DeploymentInput>()).Where(di =>
                     di.QueueId == agentPoolID).Count();

                    if (deploymentAgents > 0)
                    {
                        relevantReleases.Add(release.Name);
                    }
                }
            }
        }
    }
}
like image 153
Amit Baranes Avatar answered Oct 21 '22 10:10

Amit Baranes


Found a solution, many thanks to @amit-baranes for pointing me in the right direction.

I've changed his code sample to use the await keyword instead of using .Result, and use .OfType<DeploymentInput>() instead of .Cast<DeploymentInput>() (it was throwing some exceptions).

Oh, and the most important thing I've learned: agent pool ID and queue ID are different things!!! If you intend to use the agent pool ID to get the release definitions you'll need to get the correspondent agent queue.

Code sample:

// set agent pool Id and project name
int agentPoolId = 123456; 
string teamProjectName = ".....";

// _connection is of type VssConnection
using (var taskAgentClient = _connection.GetClient<TaskAgentHttpClient>())
using (var releaseClient = _connection.GetClient<ReleaseHttpClient2>())
{
    // please note: agent pool Id != queue Id
    // agent pool id is used to get the build definitions
    // queue Id is used to get the release definitions
    TaskAgentPool agentPool = await taskAgentClient.GetAgentPoolAsync(agentPoolId);
    List<TaskAgentQueue> queues = await taskAgentClient.GetAgentQueuesByNamesAsync(teamProjectName, queueNames: new[] { agentPool.Name });
    TaskAgentQueue queue = queues.FirstOrDefault();

    List<ReleaseDefinition> definitions = await releaseClient.GetReleaseDefinitionsAsync(teamProjectName, string.Empty, ReleaseDefinitionExpands.Environments);

    foreach (ReleaseDefinition definition in definitions)
    {
        var fullDefinition = await releaseClient.GetReleaseDefinitionAsync(teamProjectName, definition.Id);

        bool hasReleasesWithPool = fullDefinition.Environments.SelectMany(GetDeploymentInputs)
                                                              .Any(di => di.QueueId == queue.Id);

        if (hasReleasesWithPool)
        {
            Debug.WriteLine($"{definition.Name}");
        }
    }
}

private IEnumerable<DeploymentInput> GetDeploymentInputs(ReleaseDefinitionEnvironment environment)
{
    return environment.DeployPhases.Select(dp => dp.GetDeploymentInput())
                                   .OfType<DeploymentInput>();
}
like image 37
Rui Jarimba Avatar answered Oct 21 '22 08:10

Rui Jarimba