diff --git a/eng/common/scripts/Helpers/PSModule-Helpers.ps1 b/eng/common/scripts/Helpers/PSModule-Helpers.ps1 index 34dac96f8b1f..da2e6de4cc69 100644 --- a/eng/common/scripts/Helpers/PSModule-Helpers.ps1 +++ b/eng/common/scripts/Helpers/PSModule-Helpers.ps1 @@ -1,7 +1,6 @@ $global:CurrentUserModulePath = "" -function Update-PSModulePathForCI() -{ +function Update-PSModulePathForCI() { # Information on PSModulePath taken from docs # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_psmodulepath @@ -11,7 +10,8 @@ function Update-PSModulePathForCI() if ($IsWindows) { $hostedAgentModulePath = $env:SystemDrive + "\Modules" $moduleSeperator = ";" - } else { + } + else { $hostedAgentModulePath = "/usr/share" $moduleSeperator = ":" } @@ -55,7 +55,8 @@ function Get-ModuleRepositories([string]$moduleName) { $repoUrls = if ($packageFeedOverrides.Contains("${moduleName}")) { @($packageFeedOverrides["${moduleName}"], $DefaultPSRepositoryUrl) - } else { + } + else { @($DefaultPSRepositoryUrl) } @@ -63,11 +64,21 @@ function Get-ModuleRepositories([string]$moduleName) { } function moduleIsInstalled([string]$moduleName, [string]$version) { - $modules = (Get-Module -ListAvailable $moduleName) + if (-not (Test-Path variable:script:InstalledModules)) { + $script:InstalledModules = @{} + } + + if ($script:InstalledModules.ContainsKey("${moduleName}")) { + $modules = $script:InstalledModules["${moduleName}"] + } + else { + $modules = (Get-Module -ListAvailable $moduleName) + $script:InstalledModules["${moduleName}"] = $modules + } + if ($version -as [Version]) { $modules = $modules.Where({ [Version]$_.Version -ge [Version]$version }) - if ($modules.Count -gt 0) - { + if ($modules.Count -gt 0) { Write-Host "Using module $($modules[0].Name) with version $($modules[0].Version)." return $modules[0] } @@ -77,8 +88,7 @@ function moduleIsInstalled([string]$moduleName, [string]$version) { function installModule([string]$moduleName, [string]$version, $repoUrl) { $repo = (Get-PSRepository).Where({ $_.SourceLocation -eq $repoUrl }) - if ($repo.Count -eq 0) - { + if ($repo.Count -eq 0) { Register-PSRepository -Name $repoUrl -SourceLocation $repoUrl -InstallationPolicy Trusted | Out-Null $repo = (Get-PSRepository).Where({ $_.SourceLocation -eq $repoUrl }) if ($repo.Count -eq 0) { @@ -102,6 +112,8 @@ function installModule([string]$moduleName, [string]$version, $repoUrl) { throw "Failed to install module $moduleName with version $version" } + $script:InstalledModules["${moduleName}"] = $modules + # Unregister repository as it can cause overlap issues with `dotnet tool install` # commands using the same devops feed Unregister-PSRepository -Name $repoUrl | Out-Null @@ -109,10 +121,17 @@ function installModule([string]$moduleName, [string]$version, $repoUrl) { return $modules[0] } +function InstallAndImport-ModuleIfNotInstalled([string]$module, [string]$version) { + if ($null -eq (moduleIsInstalled $module $version)) { + Install-ModuleIfNotInstalled -WhatIf:$false $module $version | Import-Module + } elseif (!(Get-Module -Name $module)) { + Import-Module $module + } +} + # Manual test at eng/common-tests/psmodule-helpers/Install-Module-Parallel.ps1 # If we want to use another default repository other then PSGallery we can update the default parameters -function Install-ModuleIfNotInstalled() -{ +function Install-ModuleIfNotInstalled() { [CmdletBinding(SupportsShouldProcess = $true)] param( [string]$moduleName, @@ -137,12 +156,14 @@ function Install-ModuleIfNotInstalled() foreach ($url in $repoUrls) { try { $module = installModule -moduleName $moduleName -version $version -repoUrl $url - } catch { + } + catch { if ($url -ne $repoUrls[-1]) { Write-Warning "Failed to install powershell module from '$url'. Retrying with fallback repository" Write-Warning $_ continue - } else { + } + else { Write-Warning "Failed to install powershell module from $url" throw } @@ -151,7 +172,8 @@ function Install-ModuleIfNotInstalled() } Write-Host "Using module '$($module.Name)' with version '$($module.Version)'." - } finally { + } + finally { $mutex.ReleaseMutex() } @@ -159,5 +181,5 @@ function Install-ModuleIfNotInstalled() } if ($null -ne $env:SYSTEM_TEAMPROJECTID) { - Update-PSModulePathForCI + Update-PSModulePathForCI } diff --git a/eng/common/scripts/Helpers/Package-Helpers.ps1 b/eng/common/scripts/Helpers/Package-Helpers.ps1 index f1ea6ef91f27..b545872dbbbd 100644 --- a/eng/common/scripts/Helpers/Package-Helpers.ps1 +++ b/eng/common/scripts/Helpers/Package-Helpers.ps1 @@ -46,7 +46,6 @@ function GetDocsTocDisplayName($pkg) { return $displayName } - <# .SYNOPSIS This function is a safe wrapper around `yq` and `ConvertFrom-Yaml` to convert YAML content to a PowerShell HashTable object @@ -68,7 +67,7 @@ Get-Content -Raw path/to/file.yml | CompatibleConvertFrom-Yaml #> function CompatibleConvertFrom-Yaml { param( - [Parameter(Mandatory=$true, ValueFromPipeline=$true)] + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$Content ) @@ -76,20 +75,10 @@ function CompatibleConvertFrom-Yaml { throw "Content to parse is a required input." } - # Initialize any variables or checks that need to be done once - $yqPresent = Get-Command 'yq' -ErrorAction SilentlyContinue - if (-not $yqPresent) { - . (Join-Path $PSScriptRoot PSModule-Helpers.ps1) - Install-ModuleIfNotInstalled -WhatIf:$false "powershell-yaml" "0.4.7" | Import-Module - } + . (Join-Path $PSScriptRoot PSModule-Helpers.ps1) + InstallAndImport-ModuleIfNotInstalled "powershell-yaml" "0.4.7" - # Process the content (for example, you could convert from YAML here) - if ($yqPresent) { - return ($content | yq -o=json | ConvertFrom-Json -AsHashTable) - } - else { - return ConvertFrom-Yaml $content - } + return ConvertFrom-Yaml $content } <# @@ -114,7 +103,7 @@ LoadFrom-Yaml -YmlFile path/to/file.yml #> function LoadFrom-Yaml { param( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [string]$YmlFile ) if (Test-Path -Path $YmlFile) { @@ -159,19 +148,19 @@ GetValueSafelyFrom-Yaml -YamlContentAsHashtable $YmlFileContent -Keys @("extends #> function GetValueSafelyFrom-Yaml { param( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] $YamlContentAsHashtable, - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [string[]]$Keys ) $current = $YamlContentAsHashtable foreach ($key in $Keys) { - if ($current.ContainsKey($key) -or $current[$key]) { - $current = $current[$key] - } - else { - return $null - } + if ($current.ContainsKey($key) -or $current[$key]) { + $current = $current[$key] + } + else { + return $null + } } return [object]$current