Modules/businessdev.ALbuild.RuntimePackages/Private/ConvertTo-BcRuntimeJUnit.ps1
|
function ConvertTo-BcRuntimeJUnit { <# .SYNOPSIS Renders per-app runtime-package results as JUnit XML. .DESCRIPTION Azure DevOps shows a stage as one icon, so a run that builds a dozen products across dozens of platform versions collapses into a single green or red dot - and finding which app failed on which version means reading a multi-thousand-line log. Giving every app its own stage would restore the icons but destroy the point of the factory: a stage is a job, a job is a container, and one container per (app, platform version) is the ~2300-container arrangement the factory exists to replace. JUnit results are the way out. Published with PublishTestResults@2, each app becomes an entry in the Tests tab: green when its runtime package was produced, red with the actual error when it failed, skipped when the package already existed. It is per-app, filterable, and kept across runs so a version that starts failing is visible as a change rather than as a wall of text. Suite = platform version, case = app. That grouping matches how the work is actually shaped and how someone reads it: "what broke on BC 27.3?". .PARAMETER Result Per-version results with PlatformVersion, Seconds and Products[] (Name, Status, Error, Seconds). Status is Succeeded, Failed or Skipped. .OUTPUTS System.String - JUnit XML. #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory)] [AllowEmptyCollection()] [object[]] $Result ) $esc = { param([string] $Value) [System.Security.SecurityElement]::Escape("$Value") } $sb = [System.Text.StringBuilder]::new() [void]$sb.AppendLine('<?xml version="1.0" encoding="utf-8"?>') [void]$sb.AppendLine('<testsuites>') foreach ($version in @($Result)) { $products = @(Get-BcRuntimeProperty -InputObject $version -Name 'Products' -Default @()) $failures = @($products | Where-Object { $_.Status -eq 'Failed' }).Count $skipped = @($products | Where-Object { $_.Status -eq 'Skipped' }).Count $seconds = [double](Get-BcRuntimeProperty -InputObject $version -Name 'Seconds' -Default 0) [void]$sb.AppendLine((' <testsuite name="{0}" tests="{1}" failures="{2}" skipped="{3}" time="{4}">' -f (& $esc "BC $($version.PlatformVersion)"), $products.Count, $failures, $skipped, ([string]::Format([cultureinfo]::InvariantCulture, '{0:0.###}', $seconds)))) foreach ($p in $products) { $pSeconds = [double](Get-BcRuntimeProperty -InputObject $p -Name 'Seconds' -Default 0) # classname = platform version so the Tests tab groups by version even when a consumer # flattens the suites. [void]$sb.AppendLine((' <testcase classname="{0}" name="{1}" time="{2}">' -f (& $esc "BC $($version.PlatformVersion)"), (& $esc $p.Name), ([string]::Format([cultureinfo]::InvariantCulture, '{0:0.###}', $pSeconds)))) switch ($p.Status) { 'Failed' { $message = "$(Get-BcRuntimeProperty -InputObject $p -Name 'Error' -Default 'Runtime package creation failed.')" [void]$sb.AppendLine((' <failure message="{0}">{1}</failure>' -f (& $esc $message), (& $esc $message))) } 'Skipped' { $message = "$(Get-BcRuntimeProperty -InputObject $p -Name 'Error' -Default 'Already published.')" [void]$sb.AppendLine((' <skipped message="{0}" />' -f (& $esc $message))) } } [void]$sb.AppendLine(' </testcase>') } [void]$sb.AppendLine(' </testsuite>') } [void]$sb.AppendLine('</testsuites>') return $sb.ToString() } |