Skip to content

Commit 7720ae6

Browse files
azure-sdkbenbp
authored andcommitted
Sync eng/common directory with azure-sdk-tools for PR 9392 (Azure#38630)
* Support override of powershell module feeds * snap * Add fallback repository support * Unregister repository after module install --------- Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
1 parent bf38f4e commit 7720ae6

File tree

1 file changed

+91
-53
lines changed

1 file changed

+91
-53
lines changed

eng/common/scripts/Helpers/PSModule-Helpers.ps1

Lines changed: 91 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
$DefaultPSRepositoryUrl = "https://www.powershellgallery.com/api/v2"
21
$global:CurrentUserModulePath = ""
32

43
function Update-PSModulePathForCI()
@@ -47,6 +46,69 @@ function Update-PSModulePathForCI()
4746
}
4847
}
4948

49+
function Get-ModuleRepositories([string]$moduleName) {
50+
$DefaultPSRepositoryUrl = "https://www.powershellgallery.com/api/v2"
51+
# List of modules+versions we want to replace with internal feed sources for reliability, security, etc.
52+
$packageFeedOverrides = @{
53+
'powershell-yaml' = 'https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-tools/nuget/v2'
54+
}
55+
56+
$repoUrls = if ($packageFeedOverrides.Contains("${moduleName}")) {
57+
@($packageFeedOverrides["${moduleName}"], $DefaultPSRepositoryUrl)
58+
} else {
59+
@($DefaultPSRepositoryUrl)
60+
}
61+
62+
return $repoUrls
63+
}
64+
65+
function moduleIsInstalled([string]$moduleName, [string]$version) {
66+
$modules = (Get-Module -ListAvailable $moduleName)
67+
if ($version -as [Version]) {
68+
$modules = $modules.Where({ [Version]$_.Version -ge [Version]$version })
69+
if ($modules.Count -gt 0)
70+
{
71+
Write-Host "Using module $($modules[0].Name) with version $($modules[0].Version)."
72+
return $modules[0]
73+
}
74+
}
75+
return $null
76+
}
77+
78+
function installModule([string]$moduleName, [string]$version, $repoUrl) {
79+
$repo = (Get-PSRepository).Where({ $_.SourceLocation -eq $repoUrl })
80+
if ($repo.Count -eq 0)
81+
{
82+
Register-PSRepository -Name $repoUrl -SourceLocation $repoUrl -InstallationPolicy Trusted
83+
$repo = (Get-PSRepository).Where({ $_.SourceLocation -eq $repoUrl })
84+
if ($repo.Count -eq 0) {
85+
throw "Failed to register package repository $repoUrl."
86+
}
87+
}
88+
89+
if ($repo.InstallationPolicy -ne "Trusted") {
90+
Set-PSRepository -Name $repo.Name -InstallationPolicy "Trusted"
91+
}
92+
93+
Write-Host "Installing module $moduleName with min version $version from $repoUrl"
94+
# Install under CurrentUser scope so that the end up under $CurrentUserModulePath for caching
95+
Install-Module $moduleName -MinimumVersion $version -Repository $repo.Name -Scope CurrentUser -Force
96+
# Ensure module installed
97+
$modules = (Get-Module -ListAvailable $moduleName)
98+
if ($version -as [Version]) {
99+
$modules = $modules.Where({ [Version]$_.Version -ge [Version]$version })
100+
}
101+
if ($modules.Count -eq 0) {
102+
throw "Failed to install module $moduleName with version $version"
103+
}
104+
105+
# Unregister repository as it can cause overlap issues with `dotnet tool install`
106+
# commands using the same devops feed
107+
Unregister-PSRepository -Name $repoUrl
108+
109+
return $modules[0]
110+
}
111+
50112
# Manual test at eng/common-tests/psmodule-helpers/Install-Module-Parallel.ps1
51113
# If we want to use another default repository other then PSGallery we can update the default parameters
52114
function Install-ModuleIfNotInstalled()
@@ -55,69 +117,45 @@ function Install-ModuleIfNotInstalled()
55117
param(
56118
[string]$moduleName,
57119
[string]$version,
58-
[string]$repositoryUrl = $DefaultPSRepositoryUrl
120+
[string]$repositoryUrl
59121
)
60122

61-
# Check installed modules
62-
$modules = (Get-Module -ListAvailable $moduleName)
63-
if ($version -as [Version]) {
64-
$modules = $modules.Where({ [Version]$_.Version -ge [Version]$version })
65-
}
123+
# Check installed modules before after acquiring lock to avoid a big queue
124+
$module = moduleIsInstalled -moduleName $moduleName -version $version
125+
if ($module) { return $module }
66126

67-
if ($modules.Count -eq 0)
68-
{
69-
# Use double-checked locking to avoid locking when module is already installed
127+
try {
70128
$mutex = New-Object System.Threading.Mutex($false, "Install-ModuleIfNotInstalled")
71129
$null = $mutex.WaitOne()
72130

73-
try {
74-
# Check installed modules again after acquiring lock
75-
$modules = (Get-Module -ListAvailable $moduleName)
76-
if ($version -as [Version]) {
77-
$modules = $modules.Where({ [Version]$_.Version -ge [Version]$version })
78-
}
79-
80-
if ($modules.Count -eq 0)
81-
{
82-
$repositories = (Get-PSRepository).Where({ $_.SourceLocation -eq $repositoryUrl })
83-
if ($repositories.Count -eq 0)
84-
{
85-
Register-PSRepository -Name $repositoryUrl -SourceLocation $repositoryUrl -InstallationPolicy Trusted
86-
$repositories = (Get-PSRepository).Where({ $_.SourceLocation -eq $repositoryUrl })
87-
if ($repositories.Count -eq 0) {
88-
Write-Error "Failed to register package repository $repositoryUrl."
89-
return
90-
}
91-
}
92-
$repository = $repositories[0]
93-
94-
if ($repository.InstallationPolicy -ne "Trusted") {
95-
Set-PSRepository -Name $repository.Name -InstallationPolicy "Trusted"
96-
}
97-
98-
Write-Host "Installing module $moduleName with min version $version from $repositoryUrl"
99-
# Install under CurrentUser scope so that the end up under $CurrentUserModulePath for caching
100-
Install-Module $moduleName -MinimumVersion $version -Repository $repository.Name -Scope CurrentUser -Force
101-
102-
# Ensure module installed
103-
$modules = (Get-Module -ListAvailable $moduleName)
104-
if ($version -as [Version]) {
105-
$modules = $modules.Where({ [Version]$_.Version -ge [Version]$version })
106-
}
107-
108-
if ($modules.Count -eq 0) {
109-
Write-Error "Failed to install module $moduleName with version $version"
110-
return
131+
# Check installed modules again after acquiring lock, in case it has been installed
132+
$module = moduleIsInstalled -moduleName $moduleName -version $version
133+
if ($module) { return $module }
134+
135+
$repoUrls = Get-ModuleRepositories $moduleName
136+
137+
foreach ($url in $repoUrls) {
138+
try {
139+
$module = installModule -moduleName $moduleName -version $version -repoUrl $url
140+
} catch {
141+
if ($url -ne $repoUrls[-1]) {
142+
Write-Warning "Failed to install powershell module from '$url'. Retrying with fallback repository"
143+
Write-Warning $_
144+
continue
145+
} else {
146+
Write-Warning "Failed to install powershell module from $url"
147+
throw
111148
}
112149
}
150+
break
113151
}
114-
finally {
115-
$mutex.ReleaseMutex()
116-
}
152+
153+
Write-Host "Using module '$($module.Name)' with version '$($module.Version)'."
154+
} finally {
155+
$mutex.ReleaseMutex()
117156
}
118157

119-
Write-Host "Using module $($modules[0].Name) with version $($modules[0].Version)."
120-
return $modules[0]
158+
return $module
121159
}
122160

123161
if ($null -ne $env:SYSTEM_TEAMPROJECTID) {

0 commit comments

Comments
 (0)