Можно ли получить значения пользовательских возможностей агента сборки TFS на этапах сборки?

Я пытаюсь написать шаг сборки в TFS, который опирается на знание того, где агент сборки хранит nuget.exe (стандартный шаг nuget-install искажает порядок аргументов таким образом, что нарушает выполнение сборки, поэтому я хочу запустите исполняемый файл самостоятельно, используя один из шагов batch/shell/ps).

Казалось бы, настройка возможности агента сборки с этим путем имеет смысл, но я не могу сослаться на это значение ни на одном из своих шагов сборки, и я не могу найти ничего полезного в MSDN.

Я ожидаю, что это будет что-то вроде $(Env.MyUserCapability), но оно никогда не преобразуется в значение.

Можно ли получить значение возможности на этапе сборки? И если да, то как вы это делаете? И если нет, то что является жизнеспособной альтернативой?


person Izzy    schedule 08.05.2017    source источник


Ответы (2)


Определяемые пользователем возможности — это только метаданные. Но вы можете установить глобальную переменную среды (например, NUGET) и указать для нее путь к nuget.exe, когда вы перезапустите агент, среда всей машины будет обнаружена как возможность, и вы сможете ее использовать.

Если вы пишете пользовательскую задачу, вы также можете добавить nuget.exe к задаче, которая будет загружена исполняющему агенту.

person Martin Ullrich    schedule 08.05.2017
comment
Да, я думал об этом... тогда я могу использовать возможность, чтобы сигнализировать, что эта глобальная переменная среды установлена. Просто кажется такой тратой времени не позволять шагу сборки получать доступ к значениям там ... И как вы получаете к нему доступ, если вы не возражаете? - person Izzy; 08.05.2017
comment
Включенная задача имеет встроенный nuget.exe, если вы пишете задачу (а не только командный шаг), вы можете сделать то же самое. - person Martin Ullrich; 08.05.2017
comment
%GLOBAL_VAR_NAME% (facepalm) Но вы также можете указать его как пользовательскую переменную, если вы знаете, от имени какого пользователя работает агент сборки. - person Izzy; 08.05.2017
comment
Да, конечно. мне просто нравятся они глобальные, чтобы каждый мог ввести-pssession на сервер сборки для диагностики проблем. - person Martin Ullrich; 08.05.2017

ОБНОВЛЕНИЕ: я сделал из этого общедоступное расширение.

ОБНОВЛЕНИЕ: это работает в Azure DevOps 2019.

В TFS 2018u1 работает следующее:

Import-Module "Microsoft.TeamFoundation.DistributedTask.Task.Common"
Import-Module "Microsoft.TeamFoundation.DistributedTask.Task.Internal"
Add-Type -Assembly "Microsoft.TeamFoundation.DistributedTask.WebApi"

$VSS = Get-VssConnection -TaskContext $distributedTaskContext
$AgentCli = $VSS.GetClient([Microsoft.TeamFoundation.DistributedTask.WebApi.TaskAgentHttpClient])

$AgentConfig = Get-Content "$Env:AGENT_HOMEDIRECTORY\.agent" -Raw | ConvertFrom-Json
$Agent = $AgentCli.GetAgentAsync($AgentConfig.PoolId, $Env:AGENT_ID, $TRUE, $FALSE, $NULL, $NULL, [System.Threading.CancellationToken]::None).GetAwaiter().GetResult()

if($Agent.UserCapabilities.MyCapability)
{
    Write-Host "Got the capability!";
} 

Длинная строка аргументов по умолчанию, оканчивающаяся на CancellationToken::None, предназначена для совместимости с Powershell 4. PS4 не поддерживает значения по умолчанию для параметров метода, типизированного значением, PS5 поддерживает.

Этот фрагмент делает что-то очень сомнительное — он зависит от местоположения и структуры файла конфигурации агента. Это хрупко. Проблема в том, что для метода GetAgentAsync требуются как идентификатор пула, так и идентификатор агента, а первый не отображается в переменных среды. Чуть менее хакерским подходом будет проверка всех пулов и поиск нужного по идентификатору агента:

$Pools = $AgentCli.GetAgentPoolsAsync($NULL, $NULL, $NULL, $NULL, $NULL, [System.Threading.CancellationToken]::None).GetAwaiter().GetResult()
$Demands = New-Object 'System.Collections.Generic.List[string]'
foreach($Pool in $Pools)
{
    $Agent = $AgentCli.GetAgentsAsync($Pool.ID, $Env:AGENT_NAME, $TRUE, $FALSE, $NULL, $Demands, $NULL, [System.Threading.CancellationToken]::None).Result
    if($Agent -and $Agent.Id -eq $Env:AGENT_ID)
    {
        Break
    }
}

Это зависит от другой недокументированной детали реализации, а именно от того, что идентификаторы агентов уникальны в глобальном масштабе. Кажется, это держится вплоть до TFS 2018, но кто знает.


Когда вы используете $distributedTaskContext, задача подключается обратно к TFS с искусственным идентификатором пользователя, «Службой сборки коллекции проектов» (а не с учетной записью службы агента). В каждой коллекции есть один такой пользователь, они разные. Чтобы разрешить задачам, запущенным в выпусках в коллекции, запрашивать у агента возможности пользователя, необходимо предоставить роль читателя соответствующему пулу (пулам) (или всем пулам) учетной записи пользователя с именем «Служба сборки коллекции проектов (< em>TheCollectionName)" из этой коллекции.

Также похоже, что некоторые действия также предоставляют неявную роль читателя в пуле удостоверению задачи.


Кроме того, вы можете создать VssConnection с нуля с учетными данными Windows и предоставить учетным записям агента роль читателя в пуле (пулах).

person Seva Alekseyev    schedule 28.03.2018
comment
Это должно быть задачей сценария Powershell? - person TGlatzer; 12.12.2018
comment
Это может быть встроенный фрагмент внутри задачи Powershell или Powershell++. - person Seva Alekseyev; 12.12.2018
comment
Я сделал это файлом, так как встроенные фрагменты могут быть только 500 символов. Но IPMO в начале бросает модуль, который не найден. Нужны ли мне определенные вещи, установленные на агенте? - person TGlatzer; 12.12.2018
comment
Задача Powershell++ считается устаревшей, но не имеет ограничения в 500 символов :) Просто говорю. Тем не менее, все рассматриваемые модули должны присутствовать на машине агента, я не устанавливал их отдельно. Может быть, они не на пути в вашем сценарии? Со встроенными фрагментами они есть. - person Seva Alekseyev; 12.12.2018
comment
Powershell++ находится здесь: marketplace.visualstudio.com/ - person Seva Alekseyev; 12.12.2018