0
votes

I am trying to see if it is possible to queue a build on the same VM as another build. Note, I am in the vNext system. I know it is possible to configuration information about the agent queues. but I want to get a little more specific than that. I'm not sure if what I want falls outside of build best practices, but I'd like to ask anyway.

Consider the following setup for builds A & B:

  1. There are 4 agents: 2 on server 1, 2 on server 2 Any agent can pick up build A or build B .... I know how to set up the demands so only agents on those VMs can pick up this builds.

  2. Build A uses the rest API to queue build B, and wait for it to complete. Right now, under current configurations, the spawned build B can be picked up by any of the 3 remaining agents on (so the free agent on the same machine as build A, or any of the agents on the other server).

  3. I want to try to run build B on the same server as build A when build A launches build B. In other words, if an agent on server 1 picks up build A, I want the build B it launches to use the same server (using the other agent on the machine). Conversely, if the server 2 picks up build A, I want the build B it launches to be picked up by server 2 as well. Assuming I know things like the Agent ID, Agemt Machine Name, etc, I wanted to use the rest API in c# to simulating launching build B to try to control which machine picks it up.

  4. I could configure agents so that both builds only run on 1 machine, but I am trying to avoid running too many agents on one machine. I could configure the above 4 agents to run on 1 machine, but I want to distribute the agents as much as possible. I know it is possible to specify information about agents queues / pools etc, bot not the machine. I am trying to avoid having to restrict the number of machines that run a set of agents.

I know this may seem a bit unusual ... but I am dealing with a scenario where I want to share information between the builds that will be simplified if they run on the same machine. If build B is launched by itself, it doesn't matter what machine picks it up. If this isn't possible, I will try other ways to share information between the builds.

Is it possible to do this?

1
Sharing outputs between builds in the fashion you're describing is a really bad practice. This is a problem that's solved in the form of packages. Use packages.Daniel Mann
@DanielMann, do you mean use artifacts? Forgive me for asking, my team is still ramping up on the vNext system. In any event, a little more information would be appreciated. I know what I described seems a little kludgy, so I'm open to other ideas :). Something else worth mentioning might be that after the first build is done, whatever was shared from the second build can be deleted after the first build is done using it (I wouldn't want whatever location I use to get filled with things).Bryan Johnson
If you have Project A that relies on the output of Project B and you don't want to build Project B alongside Project A, you should use a package management tool like NuGet in conjunction with a package management feed in order to have Project A consume Project B's outputs as versioned packages. This has numerous benefits.Daniel Mann

1 Answers

-1
votes

Yes, you can achieve that by set up the demands with REST API when queue the build.

For example, you can use below PowerShell script to queue a build with the specific agent:

Param(
   [string]$collectionurl = "http://server:8080/tfs/DefaultCollection/",
   [string]$projectName = "ProjectName",
   [string]$keepForever = "true",
   [string]$BuildDefinitionId = "1",
   [string]$user = "username",
   [string]$token = "password"
)

# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))

function CreateJsonBody
{

    $value = @"
  {
  "definition": {
    "id": $BuildDefinitionId
  },

  "sourceBranch": "$/xxxx",
  "demands":["Agent.Name -equals Agent1"]
 }           

}
"@

 return $value
}

$json = CreateJsonBody

$uri = "$($collectionurl)/$($projectName)/_apis/build/builds?api-version=2.0"
$result = Invoke-RestMethod -Uri $uri -Method Post -Body $json -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

In your scenario: (Assume that Agent1 is the name of the agent, you can get it from Agent Capabilities)

  • Server1 : Agent1, Agent2
  • Server2 : Agent3, Agent4

If Build A queued with Agent1, then you an set "demands":["Agent.Name -equals Agent2"] to queue Build B.

Same thing, if Build A queued with Agent3, then you an set "demands":["Agent.Name -equals Agent4"] to queue Build B.

You can also create a simple PowerShell script and add a PowerShell step as the end of the build step in definition A, then run the PS script to queue build B once Build A completed.


If you want to queue build with the REST API in C#, then you can reference below thread:

Queue vNext build from c# using REST API (Tfs on premise)