Repository: dotnet/runtime
File: .github/skills/azdo-helix-failures/scripts/Get-HelixFailures.ps1 (PowerShell)

Code before:
    }
}

function Get-HelixWorkItemDetails {
    param([string]$JobId, [string]$WorkItemName)

    $url = "https://helix.dot.net/api/2019-06-17/jobs/$JobId/workitems/$WorkItemName"

    try {
        $response = Invoke-CachedRestMethod -Uri $url -TimeoutSec $TimeoutSec -AsJson

        # Workaround for https://github.com/dotnet/dnceng/issues/6072:
        # Helix API returns incorrect file URIs for files in subdirectories
        # (e.g., xharness-output/testResults.xml). Rebuild URI from FileName.
        if ($response -and $response.Files) {
            $encodedWorkItem = [uri]::EscapeDataString($WorkItemName)
            foreach ($file in $response.Files) {
                if ($file.FileName -and $file.FileName -match '/') {
                    $encodedFileName = ($file.FileName -split '/' | ForEach-Object { [uri]::EscapeDataString($_) }) -join '/'
                    $file.Uri = "https://helix.dot.net/api/jobs/$JobId/workitems/$encodedWorkItem/files/$encodedFileName`?api-version=2019-06-17"
                }
            }
        }

        return $response
    }
    catch {
        Write-Warning "Failed to fetch work item ${WorkItemName}: $_"
        return $null
    }
}

function Get-HelixConsoleLog {
    param([string]$Url)

    try {
        $response = Invoke-CachedRestMethod -Uri $Url -TimeoutSec $TimeoutSec
        return $response
    }
    catch {
        Write-Warning "Failed to fetch Helix log from ${Url}: $_"
        return $null
    }
}

function Find-WorkItemsWithBinlogs {
    <#
    .SYNOPSIS
        Scans work items in a Helix job to find which ones contain binlog files.
    .DESCRIPTION
        Not all work items produce binlogs - only build/publish tests do.

Review comment (bug):
The new URI-rebuild logic correctly URL-encodes `$WorkItemName` into `$encodedWorkItem`, but the initial work-item details request still uses the unencoded `$WorkItemName` in `$url`. To keep behavior consistent and avoid failures for work item names containing characters that must be escaped, build `$url` using the encoded work item name as well.

Code after:
        return $response
    }
    catch {
        Write-Warning "Failed to fetch work items for job ${JobId}: $_"
        return $null
    }
}

function Get-HelixWorkItemDetails {
    param([string]$JobId, [string]$WorkItemName)

    $url = "https://helix.dot.net/api/2019-06-17/jobs/$JobId/workitems/$WorkItemName"

    try {
        $response = Invoke-CachedRestMethod -Uri $url -TimeoutSec $TimeoutSec -AsJson

        # Workaround for https://github.com/dotnet/dnceng/issues/6072:
        # Helix API returns incorrect file URIs for files in subdirectories
        # (e.g., xharness-output/testResults.xml). Rebuild URI from FileName.
        if ($response -and $response.Files) {
            $encodedWorkItem = [uri]::EscapeDataString($WorkItemName)
            foreach ($file in $response.Files) {
                if ($file.FileName -and $file.FileName -match '/') {
                    $encodedFileName = ($file.FileName -split '/' | ForEach-Object { [uri]::EscapeDataString($_) }) -join '/'
                    $file.Uri = "https://helix.dot.net/api/jobs/$JobId/workitems/$encodedWorkItem/files/$encodedFileName?api-version=2019-06-17"
                }
            }
        }

        return $response
    }
    catch {
        Write-Warning "Failed to fetch work item ${WorkItemName}: $_"
        return $null
    }
}

function Get-HelixConsoleLog {
    param([string]$Url)

    try {
        $response = Invoke-CachedRestMethod -Uri $Url -TimeoutSec $TimeoutSec
        return $response
    }
    catch {
        Write-Warning "Failed to fetch Helix log from ${Url}: $_"
        return $null
    }
}

function Find-WorkItemsWithBinlogs {