Skip to content

Commit ecc4b3f

Browse files
committed
Add logic for checking the appropriate version of the Cli tools before starting to build
1 parent 7f3ddb3 commit ecc4b3f

File tree

1 file changed

+137
-21
lines changed

1 file changed

+137
-21
lines changed

build.psm1

Lines changed: 137 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function Publish-File
2121
# attempt to get the users module directory
2222
function Get-UserModulePath
2323
{
24-
if ( $IsCoreCLR -and ! $IsWindows )
24+
if ( $IsCoreCLR -and -not $IsWindows )
2525
{
2626
$platformType = "System.Management.Automation.Platform" -as [Type]
2727
if ( $platformType ) {
@@ -104,7 +104,7 @@ function Start-DocumentationBuild
104104
throw "Cannot find markdown documentation folder."
105105
}
106106
Import-Module platyPS
107-
if ( ! (Test-Path $outputDocsPath)) {
107+
if ( -not (Test-Path $outputDocsPath)) {
108108
$null = New-Item -Type Directory -Path $outputDocsPath -Force
109109
}
110110
$null = New-ExternalHelp -Path $markdownDocsPath -OutputPath $outputDocsPath -Force
@@ -126,7 +126,22 @@ function Start-ScriptAnalyzerBuild
126126
[switch]$Documentation
127127
)
128128

129+
BEGIN {
130+
# don't allow the build to be started unless we have the proper Cli version
131+
if ( -not (Test-SuitableDotnet) ) {
132+
$requiredVersion = Get-GlobalJsonSdkVersion
133+
throw "No suitable dotnet CLI found, requires version '$requiredVersion'"
134+
}
135+
}
129136
END {
137+
138+
# Build docs either when -Documentation switch is being specified or the first time in a clean repo
139+
$documentationFileExists = Test-Path (Join-Path $PSScriptRoot 'out\PSScriptAnalyzer\en-us\Microsoft.Windows.PowerShell.ScriptAnalyzer.dll-Help.xml')
140+
if ( $Documentation -or -not $documentationFileExists )
141+
{
142+
Start-DocumentationBuild
143+
}
144+
130145
if ( $All )
131146
{
132147
# Build all the versions of the analyzer
@@ -136,13 +151,6 @@ function Start-ScriptAnalyzerBuild
136151
return
137152
}
138153

139-
$documentationFileExists = Test-Path (Join-Path $PSScriptRoot 'out\PSScriptAnalyzer\en-us\Microsoft.Windows.PowerShell.ScriptAnalyzer.dll-Help.xml')
140-
# Build docs either when -Documentation switch is being specified or the first time in a clean repo
141-
if ( $Documentation -or -not $documentationFileExists )
142-
{
143-
Start-DocumentationBuild
144-
}
145-
146154
if ($PSVersion -ge 6) {
147155
$framework = 'netstandard2.0'
148156
}
@@ -277,17 +285,25 @@ function Get-TestFailures
277285
function Install-Dotnet
278286
{
279287
[CmdletBinding(SupportsShouldProcess=$true)]
280-
param ( [Parameter()][Switch]$Force )
288+
param (
289+
[Parameter()][Switch]$Force,
290+
[Parameter()]$version = $( Get-GlobalJsonSdkVersion )
291+
)
281292

282-
$json = Get-Content -raw (Join-Path $PSScriptRoot global.json) | ConvertFrom-Json
283-
$version = $json.sdk.Version
284-
if ( Test-DotnetInstallation -version $version ) {
293+
if ( Test-DotnetInstallation -requestedversion $version ) {
285294
Write-Verbose -Verbose "dotnet version '$version' already installed"
286-
return
295+
if ( $Force ) {
296+
Write-Verbose -Verbose "Installing again"
297+
}
298+
else {
299+
return
300+
}
287301
}
302+
288303
try {
289304
Push-Location $PSScriptRoot
290305
$installScriptPath = Receive-DotnetInstallScript
306+
$installScriptName = [System.IO.Path]::GetFileName($installScriptPath)
291307
If ( $PSCmdlet.ShouldProcess("$installScriptName for $version")) {
292308
& "${installScriptPath}" -c release -v $version
293309
}
@@ -303,19 +319,119 @@ function Install-Dotnet
303319
}
304320
}
305321

306-
function Test-DotnetInstallation
307-
{
308-
param ( $version )
322+
function Get-GlobalJsonSdkVersion {
323+
$json = Get-Content -raw (Join-Path $PSScriptRoot global.json) | ConvertFrom-Json
324+
$version = $json.sdk.Version
325+
ConvertTo-PortableVersion $version
326+
}
327+
328+
# we don't have semantic version in earlier versions of PowerShell, so we need to
329+
# create something that we can use
330+
function ConvertTo-PortableVersion {
331+
param ( [string[]]$strVersion )
332+
if ( -not $strVersion ) {
333+
return (ConvertTo-PortableVersion "0.0.0-0")
334+
}
335+
foreach ( $v in $strVersion ) {
336+
$ver, $pre = $v.split("-",2)
337+
try {
338+
[int]$major, [int]$minor, [int]$patch = $ver.Split(".")
339+
}
340+
catch {
341+
Write-Warning "Cannot convert '$v' to portable version"
342+
continue
343+
}
344+
$h = @{
345+
Major = $major
346+
Minor = $minor
347+
Patch = $patch
348+
}
349+
if ( $pre ) {
350+
$h['PrereleaseLabel'] = $pre
351+
}
352+
else {
353+
$h['PrereleaseLabel'] = [String]::Empty
354+
}
355+
$customObject = [pscustomobject]$h
356+
Add-Member -inputobject $customObject -Type ScriptMethod -Name ToString -Force -Value {
357+
$str = "{0}.{1}.{2}" -f $this.Major,$this.Minor,$this.Patch
358+
if ( $this.PrereleaseLabel ) {
359+
$str += "-{0}" -f $this.PrereleaseLabel
360+
}
361+
return $str
362+
}
363+
Add-Member -inputobject $customObject -Type ScriptMethod -Name IsContainedIn -Value {
364+
param ( [object[]]$collection )
365+
foreach ( $object in $collection ) {
366+
if (
367+
$this.Major -eq $object.Major -and
368+
$this.Minor -eq $object.Minor -and
369+
$this.Patch -eq $object.Patch -and
370+
$this.PrereleaseLabel -eq $object.PrereleaseLabel
371+
) {
372+
return $true
373+
}
374+
}
375+
return $false
376+
}
377+
$customObject
378+
}
379+
}
380+
381+
# see https://docs.microsoft.com/en-us/dotnet/core/tools/global-json for rules
382+
# on how version checks are done
383+
function Test-SuitableDotnet {
384+
param (
385+
$availableVersions = $( Get-InstalledCliVersion),
386+
$requiredVersion = $( Get-GlobalJsonSdkVersion )
387+
)
388+
if ( $requiredVersion -is [String] -or $requiredVersion -is [Version] ) {
389+
$requiredVersion = ConvertTo-PortableVersion "$requiredVersion"
390+
}
391+
# if we have what was requested, we can use it
392+
if ( $RequiredVersion.IsContainedIn($availableVersions)) {
393+
return $true
394+
}
395+
# if we had found a match, we would have returned $true above
396+
# exact match required for 2.1.100 through 2.1.201
397+
if ( $RequiredVersion.Major -eq 2 -and $RequiredVersion.Minor -eq 1 -and $RequiredVersion.Patch -ge 100 -and $RequiredVersion.Patch -le 201 ) {
398+
return $false
399+
}
400+
# we need to check each available version for something that's useable
401+
foreach ( $version in $availableVersions ) {
402+
# major/minor numbers don't match - keep looking
403+
if ( $version.Major -ne $requiredVersion.Major -or $version.Minor -ne $requiredVersion.Minor ) {
404+
continue
405+
}
406+
$requiredPatch = $requiredVersion.Patch
407+
$possiblePatch = $version.Patch
408+
if ( $requiredPatch -gt $possiblePath ) {
409+
continue
410+
}
411+
if ( ($requiredPatch - $possiblePatch) -ge 100 ) {
412+
continue
413+
}
414+
return $true
415+
}
416+
return $false
417+
}
418+
419+
# these are mockable functions for testing
420+
function Get-InstalledCLIVersion {
309421
try {
310422
$installedVersions = dotnet --list-sdks | Foreach-Object { $_.Split()[0] }
311423
}
312424
catch {
313425
$installedVersions = @()
314426
}
315-
if ( $installedVersions -contains $version ) {
316-
return $true
317-
}
318-
return $false
427+
return (ConvertTo-PortableVersion $installedVersions)
428+
}
429+
430+
function Test-DotnetInstallation
431+
{
432+
param ( $requestedVersion = $( Get-GlobalJsonSdkVersion ) )
433+
$installedVersions = Get-InstalledCLIVersion
434+
return (Test-SuitableDotnet -availableVersions $installedVersions -requiredVersion $requestedVersion )
319435
}
320436

321437
function Receive-DotnetInstallScript

0 commit comments

Comments
 (0)