本地 Azure DevOps Server 中给定池的 REST Api return AGENT.BUILDDIRECTORY 值是多少?

What REST Api return AGENT.BUILDDIRECTORY value for the given pool in Azure DevOps Server on-prem?

所以我获取了构建定义:

$bd = ...

它有池 ID:

C:\> $bd.queue.pool.id

90
C:\>

现在我可以使用 Url https://myserver.com/tfs/DefaultCollection/_apis/distributedtask/pools/90/agents?includeCapabilities=true

的功能获取池数据

我确实得到了很多信息,但是 Agent.BuildDirectory 没有:

C:\> $x = Invoke-RestMethod $Url -UseDefaultCredentials

C:\> $x.value.systemCapabilities[0].PSObject.Properties.Name |? { $_ -match '^Agent' }

Agent.Name
Agent.Version
Agent.ComputerName
Agent.HomeDirectory
Agent.OS
Agent.OSArchitecture
Agent.OSVersion
C:\> 

给定一个有效的构建定义,我如何使用其余 API 为与其关联的每个本地代理获取 Agent.BuildDirectory

如果您从 UI 访问代理的功能,您会发现没有 Agent.BuildDirectory 功能,因此您无法从 REST API 获取它。此外,Agent.BuildDirectory 是代理上的本地路径,其中创建了给定构建管道的所有文件夹,格式类似于 c:\agent_work\_work,因此构建管道之间是不同的。

您可以从构建管道中获取此变量,或检查构建日志以获取路径。

我最终得到了以下函数:

function Invoke-ForEachBuildAgent(
    [Parameter(Mandatory)]$BuildDefinition,
    [Parameter(Mandatory)][scriptblock]$Action,
    [pscredential]$Credential
)
{
    function MapShare($AgentComputerName, $RemoteDirectory, $PSDrive, [pscredential]$Credential)
    {
        if ($Credential)
        {
            $Share = "\$AgentComputerName$($RemoteDirectory[0])`$"
            $Mapped = $null
            try
            {
                $Mapped = Test-Path $Share
            }
            catch
            {            
            }
            if (!$Mapped)
            {
                New-PSDrive $PSDrive FileSystem $Share -Credential $Credential > $null
            }
        }
    }

    $RelSourceFolderPath = "SourceRootMappinga33a8ed-f8fd-4c08-9f44-440ea9f20315$($BuildDefinition.Id)\SourceFolder.json"
    $PSDrive = [guid]::NewGuid().ToString('N')
    if (!$Credential -and ($env:USERNAME -ne INSERT_THE_DEFAULT_USER_NAME_HERE))
    {
        $Credential = Get-Credential -UserName INSERT_THE_DEFAULT_USER_NAME_WITH_DOMAIN_HERE -Message "Login to access the agents"
    }

    $Url = "$TfsInstanceUrl/_apis/distributedtask/pools/$($BuildDefinition.Queue.Pool.Id)/agents?includeCapabilities=true"
    (Invoke-RestMethod $Url -UseDefaultCredentials).value.systemCapabilities | Where-Object {
        $_
    } | ForEach-Object {
        try
        {
            $AgentComputerName = $_.'Agent.ComputerName'
            $AgentHomeDirectory = $_.'Agent.HomeDirectory'

            MapShare $AgentComputerName $AgentHomeDirectory $PSDrive $Credential

            $Path = "\$AgentComputerName$AgentHomeDirectory\.agent".Replace(':', '$')
            $AgentBuildDirectoryRoot = (Get-Content $Path | ConvertFrom-Json).workFolder
            
            if ($AgentBuildDirectoryRoot[0] -ne $AgentHomeDirectory[0])
            {
                Remove-PSDrive $PSDrive -ErrorAction SilentlyContinue
                MapShare $AgentComputerName $AgentBuildDirectoryRoot $PSDrive $Credential
            }

            $Path = "\$AgentComputerName$AgentBuildDirectoryRoot$RelSourceFolderPath".Replace(':', '$')
            if (!(Test-Path $Path))
            {
                return
            }

            $BuildFolderNumber = (Get-Content $Path | ConvertFrom-Json).agent_builddirectory
            $AgentBuildDirectory = [io.path]::GetFullPath("$Path\..\..\..\..$BuildFolderNumber")
            & $Action -SystemCapabilities $_ `
                -UncAgentBuildDirectory $AgentBuildDirectory `
                -AgentBuildDirectory "$AgentBuildDirectoryRoot$LastBuildFolderNumber" `
                -Credential $Credential
        }
        catch
        {
            $_.Exception
        }
        finally
        {
            Remove-PSDrive $PSDrive -ErrorAction SilentlyContinue
        }
    }
}

我很确定它只适用于本地代理。我会更新我的答案。那些托管在 Azure 中的 运行 代理一开始并不真正需要此功能。