From 421a6f73ab800b7b0f8922e47b2b6c196f8240ff Mon Sep 17 00:00:00 2001 From: James Suplizio Date: Tue, 22 Oct 2024 13:24:49 -0700 Subject: [PATCH 1/2] Refactor PackageProps to make the Yaml loading and processing methods common --- .../scripts/Helpers/Package-Helpers.ps1 | 86 +++++++++++++++++++ eng/common/scripts/Package-Properties.ps1 | 44 +++------- 2 files changed, 98 insertions(+), 32 deletions(-) diff --git a/eng/common/scripts/Helpers/Package-Helpers.ps1 b/eng/common/scripts/Helpers/Package-Helpers.ps1 index 985ebcc4ee3bc..591e55d43988c 100644 --- a/eng/common/scripts/Helpers/Package-Helpers.ps1 +++ b/eng/common/scripts/Helpers/Package-Helpers.ps1 @@ -90,4 +90,90 @@ function CompatibleConvertFrom-Yaml { else { return ConvertFrom-Yaml $content } +} + +<# +.SYNOPSIS +Common function that will verify that the YmlFile being loaded exists, load the raw file and +return the results of CompatibleConvertFrom-Yaml or report an exception and return null if +there's a problem loading the yml file. The return is the PowerShell HashTable object. + +.DESCRIPTION +Common function that will verify that the YmlFile being loaded exists, load the raw file and +return the results of CompatibleConvertFrom-Yaml or report an exception and return null if +there's a problem loading the yml file. This is just to save anyone needing to load yml from +having to deal with checking the file's existence and ensure that the CompatibleConvertFrom-Yaml +is made within a try/catch. The return is the PowerShell HashTable object from the +CompatibleConvertFrom-Yaml call or $null if there was an issue with the convert. + +.PARAMETER YmlFile +The full path of the yml file to load. + +.EXAMPLE +CompatibleLoadAndConvertFrom-Yaml -YmlFile path/to/file.yml +#> +function LoadAndCompatibleConvertFrom-Yaml { + param( + [Parameter(Mandatory=$true)] + [string]$YmlFile + ) + if (Test-Path -Path $YmlFile) { + try { + return Get-Content -Raw -Path $YmlFile | CompatibleConvertFrom-Yaml + } + catch { + Write-Host "CompatibleLoadAndConvertFrom-Yaml::Exception while parsing yml file $($YmlFile): $_" + } + } + else { + Write-Host "CompatibleLoadAndConvertFrom-Yaml::YmlFile '$YmlFile' does not exist." + } + return $null +} + +<# +.SYNOPSIS +Given the Hashtable contents of a Yml file and an array of strings representing the keys +return the value if it exist or null if it doesn't. + +.DESCRIPTION +The Yaml file needs to be loaded via CompatibleConvertFrom-Yaml which returns the file as +as hashtable. The Keys are basically the path in the yaml file whose value to return, or +null if it doesn't exist. This function does is safely traverses the path, outputting an +error if there's an issue or returning the object representing the result if successful. +This function loops through the Keys safely trying to get values, checking each piece of +the path to ensure it exists. Normally one would just do +$Yml["extends"]["parameters"]["artifacts"] +but if something was off it would throw. Doing it this way allows more succinct error +reporting if a piece of the path didn't exist + +.PARAMETER YamlContentAsHashtable +The hashtable representing the yaml file contents loaded through LoadAndCompatibleConvertFrom-Yaml +or CompatibleConvertFrom-Yaml, which is what LoadAndCompatibleConvertFrom-Yaml calls. + +.PARAMETER Keys +String array representation of the path in the yaml file whose value we're trying to retrieve. + +.EXAMPLE +GetValueSafelyFrom-Yaml -YamlContentAsHashtable $YmlFileContent -Keys @("extends", "parameters", "Artifacts") +#> +function GetValueSafelyFrom-Yaml { + param( + [Parameter(Mandatory=$true)] + $YamlContentAsHashtable, + [Parameter(Mandatory=$true)] + [string[]]$Keys + ) + $current = $YamlContentAsHashtable + foreach ($key in $Keys) { + if ($current.ContainsKey($key) -or $current[$key]) { + $current = $current[$key] + } + else { + Write-Host "The '$key' part of the path $($Keys -join "/") doesn't exist or is null." + return $null + } + } + + return [object]$current } \ No newline at end of file diff --git a/eng/common/scripts/Package-Properties.ps1 b/eng/common/scripts/Package-Properties.ps1 index 62626f786f0b6..be5b6cfeb76cb 100644 --- a/eng/common/scripts/Package-Properties.ps1 +++ b/eng/common/scripts/Package-Properties.ps1 @@ -17,7 +17,8 @@ class PackageProps [string]$ReleaseStatus # was this package purely included because other packages included it as an AdditionalValidationPackage? [boolean]$IncludedForValidation - # does this package include other packages that we should trigger validation for? + # does this package include other packages that we should trigger validation for or + # additional packages required for validation of this one [string[]]$AdditionalValidationPackages [HashTable]$ArtifactDetails @@ -83,42 +84,21 @@ class PackageProps $this.Group = $group } - hidden [object]GetValueSafely($hashtable, [string[]]$keys) { - $current = $hashtable - foreach ($key in $keys) { - if ($current.ContainsKey($key) -or $current[$key]) { - $current = $current[$key] - } - else { - return $null - } - } + hidden [HashTable]ParseYmlForArtifact([string]$ymlPath) { - return $current - } + $content = LoadAndCompatibleConvertFrom-Yaml $ymlPath + if ($content) { + $artifacts = GetValueSafelyFrom-Yaml $content @("extends", "parameters", "Artifacts") + $artifactForCurrentPackage = $null - hidden [HashTable]ParseYmlForArtifact([string]$ymlPath) { - if (Test-Path -Path $ymlPath) { - try { - $content = Get-Content -Raw -Path $ymlPath | CompatibleConvertFrom-Yaml - if ($content) { - $artifacts = $this.GetValueSafely($content, @("extends", "parameters", "Artifacts")) - $artifactForCurrentPackage = $null - - if ($artifacts) { - $artifactForCurrentPackage = $artifacts | Where-Object { $_["name"] -eq $this.ArtifactName -or $_["name"] -eq $this.Name } - } - - if ($artifactForCurrentPackage) { - return [HashTable]$artifactForCurrentPackage - } - } + if ($artifacts) { + $artifactForCurrentPackage = $artifacts | Where-Object { $_["name"] -eq $this.ArtifactName -or $_["name"] -eq $this.Name } } - catch { - Write-Host "Exception while parsing yml file $($ymlPath): $_" + + if ($artifactForCurrentPackage) { + return [HashTable]$artifactForCurrentPackage } } - return $null } From b8a762295023e7f68526d2ea03122596c4e862d0 Mon Sep 17 00:00:00 2001 From: James Suplizio Date: Tue, 22 Oct 2024 15:59:58 -0700 Subject: [PATCH 2/2] Updates for feedback --- .../scripts/Helpers/Package-Helpers.ps1 | 20 +++++++++---------- eng/common/scripts/Package-Properties.ps1 | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/eng/common/scripts/Helpers/Package-Helpers.ps1 b/eng/common/scripts/Helpers/Package-Helpers.ps1 index 591e55d43988c..3c882b31111b6 100644 --- a/eng/common/scripts/Helpers/Package-Helpers.ps1 +++ b/eng/common/scripts/Helpers/Package-Helpers.ps1 @@ -110,9 +110,9 @@ CompatibleConvertFrom-Yaml call or $null if there was an issue with the convert. The full path of the yml file to load. .EXAMPLE -CompatibleLoadAndConvertFrom-Yaml -YmlFile path/to/file.yml +LoadFrom-Yaml -YmlFile path/to/file.yml #> -function LoadAndCompatibleConvertFrom-Yaml { +function LoadFrom-Yaml { param( [Parameter(Mandatory=$true)] [string]$YmlFile @@ -122,11 +122,11 @@ function LoadAndCompatibleConvertFrom-Yaml { return Get-Content -Raw -Path $YmlFile | CompatibleConvertFrom-Yaml } catch { - Write-Host "CompatibleLoadAndConvertFrom-Yaml::Exception while parsing yml file $($YmlFile): $_" + Write-Host "LoadFrom-Yaml::Exception while parsing yml file $($YmlFile): $_" } } else { - Write-Host "CompatibleLoadAndConvertFrom-Yaml::YmlFile '$YmlFile' does not exist." + Write-Host "LoadFrom-Yaml::YmlFile '$YmlFile' does not exist." } return $null } @@ -139,17 +139,17 @@ return the value if it exist or null if it doesn't. .DESCRIPTION The Yaml file needs to be loaded via CompatibleConvertFrom-Yaml which returns the file as as hashtable. The Keys are basically the path in the yaml file whose value to return, or -null if it doesn't exist. This function does is safely traverses the path, outputting an -error if there's an issue or returning the object representing the result if successful. -This function loops through the Keys safely trying to get values, checking each piece of -the path to ensure it exists. Normally one would just do +null if it doesn't exist. This function safely traverses the path, outputting an error +if there's an issue or returning the object representing the result if successful. This +function loops through the Keys safely trying to get values, checking each piece of the +path to ensure it exists. Normally one would just do $Yml["extends"]["parameters"]["artifacts"] but if something was off it would throw. Doing it this way allows more succinct error reporting if a piece of the path didn't exist .PARAMETER YamlContentAsHashtable -The hashtable representing the yaml file contents loaded through LoadAndCompatibleConvertFrom-Yaml -or CompatibleConvertFrom-Yaml, which is what LoadAndCompatibleConvertFrom-Yaml calls. +The hashtable representing the yaml file contents loaded through LoadFrom-Yaml +or CompatibleConvertFrom-Yaml, which is what LoadFrom-Yaml calls. .PARAMETER Keys String array representation of the path in the yaml file whose value we're trying to retrieve. diff --git a/eng/common/scripts/Package-Properties.ps1 b/eng/common/scripts/Package-Properties.ps1 index be5b6cfeb76cb..61054f10f22ad 100644 --- a/eng/common/scripts/Package-Properties.ps1 +++ b/eng/common/scripts/Package-Properties.ps1 @@ -86,7 +86,7 @@ class PackageProps hidden [HashTable]ParseYmlForArtifact([string]$ymlPath) { - $content = LoadAndCompatibleConvertFrom-Yaml $ymlPath + $content = LoadFrom-Yaml $ymlPath if ($content) { $artifacts = GetValueSafelyFrom-Yaml $content @("extends", "parameters", "Artifacts") $artifactForCurrentPackage = $null