Modules/businessdev.ALbuild.RuntimePackages/Private/Get-BcRuntimeIssueClass.ps1
|
function Get-BcRuntimeIssueClass { <# .SYNOPSIS Reduces one failed (app, platform version) to the CAUSE behind it, so identical causes collapse. .DESCRIPTION A product that cannot compile against older majors fails once per platform version: ERiC produced 162 identical failures in run 27383, all of them the same line in app.json. Reporting those as 162 findings is a wall, not a report - and it is a wall the product team has to read before it can decide anything. The cause is the set of AL error codes the compiler produced, which is stable across versions and is what a developer recognises: 'AL0280+AL0282' is "we subscribe to events this Base Application does not have", 'AL0791' is "we reference namespaces it does not have". The SET, not the first code, because the order compiler diagnostics arrive in is not something to build a grouping on. Failures with no diagnostics at all - a container command that would not run, a signing tool that died - are classed by their message with the moving parts taken out: paths, guids, versions and bare numbers. Two of those collapse when they are the same problem and stay apart when they are not. .PARAMETER Message The failure message recorded for the app. NOT named -Error: '$Error' is a PowerShell automatic variable, and a parameter by that name shadows it for the whole function body. .PARAMETER Diagnostic The compiler diagnostics attributed to that app, if any. .OUTPUTS PSCustomObject: Key (stable, for grouping) and Label (for a human). #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [AllowEmptyString()] [AllowNull()] [string] $Message = '', [AllowEmptyCollection()] [string[]] $Diagnostic = @() ) $codes = [System.Collections.Generic.SortedSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($d in @($Diagnostic)) { foreach ($m in [regex]::Matches("$d", '\berror ([A-Za-z]{2}\d+):')) { [void]$codes.Add($m.Groups[1].Value) } } if ($codes.Count -gt 0) { $key = ($codes -join '+') return [PSCustomObject]@{ Key = $key; Label = "compiler errors $key" } } # No diagnostics: class by the message, with everything that varies per version removed. $norm = "$Message" $norm = $norm -replace '[A-Za-z]:\\[^\s'']+', '<path>' $norm = $norm -replace '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}', '<guid>' $norm = $norm -replace '\b\d+(\.\d+){2,3}\b', '<version>' $norm = $norm -replace '\b[0-9a-f]{8}\b', '<id>' $norm = $norm -replace '-?\d+', '<n>' $norm = ($norm -replace '\s+', ' ').Trim() if (-not $norm) { $norm = 'unknown failure' } return [PSCustomObject]@{ Key = $norm; Label = $norm } } |