1- $DefaultPSRepositoryUrl = " https://www.powershellgallery.com/api/v2"
21$global :CurrentUserModulePath = " "
32
43function 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
52114function 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
123161if ($null -ne $env: SYSTEM_TEAMPROJECTID ) {
0 commit comments