diff --git a/.github/skills/ci-analysis/references/helix-artifacts.md b/.github/skills/ci-analysis/references/helix-artifacts.md index 42d17b2eabcf6a..16bd426aad04ad 100644 --- a/.github/skills/ci-analysis/references/helix-artifacts.md +++ b/.github/skills/ci-analysis/references/helix-artifacts.md @@ -47,9 +47,10 @@ Always query the specific work item to see what's available rather than assuming Artifacts may be at the root level or nested in subdirectories like `xharness-output/logs/`. -> **Note:** The Helix API has a known bug ([dotnet/dnceng#6072](https://github.com/dotnet/dnceng/issues/6072)) where -> file URIs for subdirectory files are incorrect. The script works around this by rebuilding URIs from the `FileName` -> field, but raw API responses may return broken links for files like `xharness-output/wasm-console.log`. +> **Note:** The Helix work item Details API has a known bug ([dotnet/dnceng#6072](https://github.com/dotnet/dnceng/issues/6072)) where +> file URIs for subdirectory files are incorrect, and unicode characters in filenames are rejected. +> The script works around this by using the separate `ListFiles` endpoint (`GET .../workitems/{workItemName}/files`) +> which returns direct blob storage URIs that work for all filenames regardless of subdirectories or unicode. ## Binlog Files diff --git a/.github/skills/ci-analysis/scripts/Get-CIStatus.ps1 b/.github/skills/ci-analysis/scripts/Get-CIStatus.ps1 index eb23c4ad50181e..e386604be3fa5e 100644 --- a/.github/skills/ci-analysis/scripts/Get-CIStatus.ps1 +++ b/.github/skills/ci-analysis/scripts/Get-CIStatus.ps1 @@ -1351,25 +1351,52 @@ function Get-HelixWorkItems { } } +function Get-HelixWorkItemFiles { + <# + .SYNOPSIS + Fetches work item files via the ListFiles endpoint which returns direct blob storage URIs. + .DESCRIPTION + Workaround for https://github.com/dotnet/dnceng/issues/6072: + The Details endpoint returns incorrect permalink URIs for files in subdirectories + and rejects unicode characters in filenames. The ListFiles endpoint returns direct + blob storage URIs that always work, regardless of subdirectory depth or unicode. + #> + param([string]$JobId, [string]$WorkItemName) + + $encodedWorkItem = [uri]::EscapeDataString($WorkItemName) + $url = "https://helix.dot.net/api/2019-06-17/jobs/$JobId/workitems/$encodedWorkItem/files" + + try { + $files = Invoke-CachedRestMethod -Uri $url -TimeoutSec $TimeoutSec -AsJson + return $files + } + catch { + Write-Warning "Failed to fetch files for work item ${WorkItemName}: $_" + return $null + } +} + function Get-HelixWorkItemDetails { param([string]$JobId, [string]$WorkItemName) - $url = "https://helix.dot.net/api/2019-06-17/jobs/$JobId/workitems/$WorkItemName" + $encodedWorkItem = [uri]::EscapeDataString($WorkItemName) + $url = "https://helix.dot.net/api/2019-06-17/jobs/$JobId/workitems/$encodedWorkItem" 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" + # Replace Files from the Details endpoint with results from ListFiles. + # The Details endpoint has broken URIs for subdirectory and unicode filenames + # (https://github.com/dotnet/dnceng/issues/6072). ListFiles returns direct + # blob storage URIs that always work. + $listFiles = Get-HelixWorkItemFiles -JobId $JobId -WorkItemName $WorkItemName + if ($listFiles) { + $response.Files = @($listFiles | ForEach-Object { + [PSCustomObject]@{ + FileName = $_.Name + Uri = $_.Link } - } + }) } return $response