Modules/businessdev.ALbuild.OnPrem/Private/Resolve-BcAppFileIdentity.ps1
|
function Resolve-BcAppFileIdentity { <# .SYNOPSIS Reads identity and test-app facts out of a built .app file. .DESCRIPTION Used to decide what a per-tenant publish should actually send to a customer environment, and to log WHICH app is being published rather than just a file name. An app counts as a test app when its manifest carries Target="Test" or it depends on a Microsoft test/assert library - the same rule the Marketplace submission uses to keep test apps out of AppSource (Resolve-BcMarketplaceAppSet). Test apps must never reach a customer tenant: they carry no business value, pull in the test framework, and can fail to install where it is absent. A file whose manifest cannot be read is reported with Readable = $false rather than throwing, and falls back to the FILE NAME for the test check. Refusing to publish it would be worse than the bug being fixed: a quirk in one artifact would silently turn a release into a no-op. So an unreadable file is still published (with a warning) unless its name marks it as a test app. .PARAMETER Path The .app file to inspect. .OUTPUTS PSCustomObject: File, Name, Publisher, Version, Id, IsTest, IsRuntime, Readable, Error. #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory)] [string] $Path ) $leaf = Split-Path -Path $Path -Leaf $facts = [PSCustomObject]@{ File = $Path Name = $leaf Publisher = '' Version = '' Id = '' IsTest = $false IsRuntime = ($leaf -like '*.runtime.app') Readable = $false Error = '' } try { $info = Expand-BcAppFile -Path $Path } catch { $facts.Error = $_.Exception.Message # Name-based fallback only. A built app is named '<publisher>_<name>_<version>.app', so the base # name ENDS in the version - matching '*.Tests' would miss the real thing (a live release shipped # 'KTC - ... GmbH_Bollfilter-Core Tests_1.0.22.696.app'). Match a 'Test'/'Tests' token anywhere, # on a separator boundary so 'Latest' and 'Contest' do not qualify. $bare = [System.IO.Path]::GetFileNameWithoutExtension($leaf) $facts.IsTest = ($bare -match '(?i)(^|[\s._-])tests?([\s._-]|$)') return $facts } $facts.Readable = $true $facts.Name = "$($info.Name)" $facts.Publisher = "$($info.Publisher)" $facts.Version = "$($info.Version)" $facts.Id = "$($info.Id)" # Manifest Target="Test" is the authoritative signal. $target = '' try { $appNode = $info.Manifest.SelectSingleNode("//*[local-name()='App']") if ($appNode) { $target = "$($appNode.GetAttribute('Target'))" } } catch { Write-Verbose "Could not read the App Target attribute from '$leaf': $($_.Exception.Message)" } if ($target -ieq 'Test') { $facts.IsTest = $true } # Fallback: a dependency on a Microsoft test/assert library (apps that omit Target). if (-not $facts.IsTest) { foreach ($dependency in @($info.Dependencies)) { if ("$($dependency.Publisher)" -eq 'Microsoft' -and ("$($dependency.Name)" -like '*Test*' -or "$($dependency.Name)" -like '*Assert*')) { $facts.IsTest = $true break } } } return $facts } |