Merge pull request #17 from actions/v-malob/python-parser
Rework version grabber and add Python supportpull/19/head
						commit
						ab240b2f15
					
				| @ -1,93 +0,0 @@ | |||||||
| #Requires -Modules Pester |  | ||||||
| 
 |  | ||||||
| Import-Module (Join-Path $PSScriptRoot "helpers.psm1") -Force |  | ||||||
|    |  | ||||||
| Describe "Validate-FiltersFormat" { |  | ||||||
|     It "Filter with word" { |  | ||||||
|         { Validate-FiltersFormat -Filters @("1two.2") } | Should -Throw "Invalid filter format" |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     It "Filter with non-word character" { |  | ||||||
|         { Validate-FiltersFormat -Filters @("1,.2") } | Should -Throw "Invalid filter format" |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     It "Valid filters" { |  | ||||||
|         { Validate-FiltersFormat -Filters @("*", "1", "1.*", "1.2", "1.2.*") } | Should -Not -Throw "Invalid filter format" |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Describe "Format-Versions" { |  | ||||||
|     It "Clean versions" { |  | ||||||
|         $actualOutput = Format-Versions -Versions @("14.2.0", "1.14.0") |  | ||||||
|         $expectedOutput = @("14.2.0", "1.14.0") |  | ||||||
|         $actualOutput | Should -Be $expectedOutput |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     It "Versions with prefixes" { |  | ||||||
|         $actualOutput = Format-Versions -Versions @("v14.2.0", "go1.14.0") |  | ||||||
|         $expectedOutput = @("14.2.0", "1.14.0") |  | ||||||
|         $actualOutput | Should -Be $expectedOutput |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     It "Skip beta and rc versions" { |  | ||||||
|         $actualOutput = Format-Versions -Versions @("14.2.0-beta", "v1.14.0-rc-1") |  | ||||||
|         $expectedOutput = @() |  | ||||||
|         $actualOutput | Should -Be $expectedOutput |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     It "Short version" { |  | ||||||
|         $actualOutput = Format-Versions -Versions @("14.2", "v2.0") |  | ||||||
|         $expectedOutput = @("14.2.0", "2.0.0") |  | ||||||
|         $actualOutput | Should -Be $expectedOutput |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     It "Skip versions with 1 digit" { |  | ||||||
|         $actualOutput = Format-Versions -Versions @("14", "v2") |  | ||||||
|         $expectedOutput = @() |  | ||||||
|         $actualOutput | Should -Be $expectedOutput |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Describe "Select-VersionsByFilter" { |  | ||||||
|     $inputVersions = @("8.2.1", "9.3.3", "10.0.2", "10.0.3", "10.5.6", "12.4.3", "12.5.1", "14.2.0") |  | ||||||
| 
 |  | ||||||
|     It "Include filter only" { |  | ||||||
|         $includeFilters = @("8.*", "14.*") |  | ||||||
|         $excludeFilters = @() |  | ||||||
|         $actualOutput = Select-VersionsByFilter -Versions $inputVersions -IncludeFilters $includeFilters -ExcludeFilters $excludeFilters |  | ||||||
|         $expectedOutput = @("8.2.1", "14.2.0") |  | ||||||
|         $actualOutput | Should -Be $expectedOutput |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     It "Include and exclude filters" { |  | ||||||
|         $includeFilters = @("10.*", "12.*") |  | ||||||
|         $excludeFilters = @("10.0.*", "12.4.3") |  | ||||||
|         $actualOutput = Select-VersionsByFilter -Versions $inputVersions -IncludeFilters $includeFilters -ExcludeFilters $excludeFilters |  | ||||||
|         $expectedOutput = @("10.5.6", "12.5.1") |  | ||||||
|         $actualOutput | Should -Be $expectedOutput |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     It "Exclude filter only" { |  | ||||||
|         $includeFilters = @() |  | ||||||
|         $excludeFilters = @("10.*", "12.*") |  | ||||||
|         $actualOutput = Select-VersionsByFilter -Versions $inputVersions -IncludeFilters $includeFilters -ExcludeFilters $excludeFilters |  | ||||||
|         $expectedOutput = @("8.2.1", "9.3.3", "14.2.0") |  | ||||||
|         $actualOutput | Should -Be $expectedOutput |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     It "Include and exclude filters are empty" { |  | ||||||
|         $actualOutput = Select-VersionsByFilter -Versions $inputVersions |  | ||||||
|         $expectedOutput = @("8.2.1", "9.3.3", "10.0.2", "10.0.3", "10.5.6", "12.4.3", "12.5.1", "14.2.0") |  | ||||||
|         $actualOutput | Should -Be $expectedOutput |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Describe "Skip-ExistingVersions" { |  | ||||||
|     It "Substract versions correctly" { |  | ||||||
|         $distInput = @("14.2.0", "14.3.0", "14.4.0", "14.4.1") |  | ||||||
|         $manifestInput = @("12.0.0", "14.2.0", "14.4.0") |  | ||||||
|         $actualOutput =  Skip-ExistingVersions -VersionsFromDist $distInput -VersionsFromManifest $manifestInput |  | ||||||
|         $expectedOutput = @("14.3.0", "14.4.1") |  | ||||||
|         $actualOutput | Should -Be $expectedOutput |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -0,0 +1,31 @@ | |||||||
|  | class BaseVersionsParser { | ||||||
|  |     [Int32]$ApiRetryCount = 3 | ||||||
|  |     [Int32]$ApiRetryIntervalSeconds = 60 | ||||||
|  | 
 | ||||||
|  |     [SemVer[]] GetAvailableVersions() { | ||||||
|  |         $allVersionsRaw = $this.ParseAllAvailableVersions() | ||||||
|  |         $allVersions = $allVersionsRaw | ForEach-Object { $this.FormatVersion($_) } | ||||||
|  |         $filteredVersions = $allVersions | Where-Object { $this.ShouldIncludeVersion($_) } | ||||||
|  |         return $filteredVersions | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     [SemVer[]] GetUploadedVersions() { | ||||||
|  |         throw "Method is not implemented in base class" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [SemVer[]] ParseAllAvailableVersions() { | ||||||
|  |         throw "Method is not implemented in base class" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [SemVer] FormatVersion([string]$VersionSpec) { | ||||||
|  |         throw "Method is not implemented in base class" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [bool] ShouldIncludeVersion([SemVer]$Version) { | ||||||
|  |         throw "Method is not implemented in base class" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [string] BuildGitHubFileUrl($OrganizationName, $RepositoryName, $BranchName, $FilePath) { | ||||||
|  |         return "https://raw.githubusercontent.com/${OrganizationName}/${RepositoryName}/${BranchName}/${FilePath}" | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,25 @@ | |||||||
|  | using module "./base-parser.psm1" | ||||||
|  | 
 | ||||||
|  | class GoVersionsParser: BaseVersionsParser { | ||||||
|  |     [SemVer[]] GetUploadedVersions() { | ||||||
|  |         $url = $this.BuildGitHubFileUrl("actions", "go-versions", "main", "versions-manifest.json") | ||||||
|  |         $releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds | ||||||
|  |         return $releases.version | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [string[]] ParseAllAvailableVersions() { | ||||||
|  |         $url = "https://golang.org/dl/?mode=json&include=all" | ||||||
|  |         $releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds | ||||||
|  |         return $releases.version | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [SemVer] FormatVersion([string]$VersionSpec) { | ||||||
|  |         $cleanVersion = $VersionSpec -replace "^go", "" | ||||||
|  |         return [SemVer]$cleanVersion | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [bool] ShouldIncludeVersion([SemVer]$Version) { | ||||||
|  |         # For Go, we include all versions greater than 1.12 | ||||||
|  |         return $Version -gt [SemVer]"1.12.0" | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,30 @@ | |||||||
|  | using module "./base-parser.psm1" | ||||||
|  | 
 | ||||||
|  | class NodeVersionsParser: BaseVersionsParser { | ||||||
|  |     [SemVer[]] GetUploadedVersions() { | ||||||
|  |         $url = $this.BuildGitHubFileUrl("actions", "node-versions", "main", "versions-manifest.json") | ||||||
|  |         $releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds | ||||||
|  |         return $releases.version | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [string[]] ParseAllAvailableVersions() { | ||||||
|  |         $url = "https://nodejs.org/dist/index.json" | ||||||
|  |         $releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds | ||||||
|  |         return $releases.version | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [SemVer] FormatVersion([string]$VersionSpec) { | ||||||
|  |         $cleanVersion = $VersionSpec -replace "^v", "" | ||||||
|  |         return [SemVer]$cleanVersion | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [bool] ShouldIncludeVersion([SemVer]$Version) { | ||||||
|  |         if ($Version.Major -lt 8) { | ||||||
|  |             return $false | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         # For Node.JS, we should include all LTS versions (all even-numbered releases) | ||||||
|  |         # https://nodejs.org/en/about/releases/ | ||||||
|  |         return $Version.Major % 2 -eq 0 | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,19 @@ | |||||||
|  | using module "./node-parser.psm1" | ||||||
|  | using module "./go-parser.psm1" | ||||||
|  | using module "./python-parser.psm1" | ||||||
|  | 
 | ||||||
|  | function Get-ToolVersionsParser { | ||||||
|  |     param( | ||||||
|  |         [Parameter(Mandatory)] | ||||||
|  |         [string]$ToolName | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     switch ($ToolName) { | ||||||
|  |         "Node" { return [NodeVersionsParser]::New() } | ||||||
|  |         "Go" { return [GoVersionsParser]::New() } | ||||||
|  |         "Python" { return [PythonVersionsParser]::New() } | ||||||
|  |         Default { | ||||||
|  |             throw "Unknown tool name" | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,53 @@ | |||||||
|  | using module "./base-parser.psm1" | ||||||
|  | 
 | ||||||
|  | class PythonVersionsParser: BaseVersionsParser { | ||||||
|  |     [SemVer[]] GetUploadedVersions() { | ||||||
|  |         $url = $this.BuildGitHubFileUrl("actions", "python-versions", "main", "versions-manifest.json") | ||||||
|  |         $releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds | ||||||
|  |         return $releases.version | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [string[]] ParseAllAvailableVersions() { | ||||||
|  |         $stableVersionsUrl = "https://www.python.org/ftp/python" | ||||||
|  |         $stableVersionsHtmlRaw = Invoke-WebRequest $stableVersionsUrl -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds | ||||||
|  |         $stableVersionsList = $stableVersionsHtmlRaw.Links.href | Where-Object { | ||||||
|  |             $parsed = $null | ||||||
|  |             return $_.EndsWith("/") -and [SemVer]::TryParse($_.Replace("/", ""), [ref]$parsed) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return $stableVersionsList | ForEach-Object { | ||||||
|  |             $subVersionsUrl = "${stableVersionsUrl}/${_}" | ||||||
|  |             $subVersionsHtmlRaw = Invoke-WebRequest $subVersionsUrl -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds | ||||||
|  |             return $subVersionsHtmlRaw.Links.href | ForEach-Object { | ||||||
|  |                 if ($_ -match "^Python-(\d+\.\d+\.\d+[a-z]{0,2}\d*)\.tgz$") { | ||||||
|  |                     return $Matches[1] | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [SemVer] FormatVersion([string]$VersionSpec) { | ||||||
|  |         $VersionSpec -match "^(\d+)\.(\d+)\.(\d+)([a-z]{1,2})?(\d+)?$" | ||||||
|  |          | ||||||
|  |         if ($Matches.Count -gt 4) { | ||||||
|  |             $VersionLabel = "{0}.{1}" -f $this.ConvertPythonLabel($Matches[4]), $Matches[5] | ||||||
|  |             return [SemVer]::new($Matches[1], $Matches[2], $Matches[3], $VersionLabel) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return [SemVer]::new($Matches[1], $Matches[2], $Matches[3]) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hidden [string] ConvertPythonLabel([string]$Label) { | ||||||
|  |         switch ($Label) { | ||||||
|  |             "a" { return "alpha" } | ||||||
|  |             "b" { return "beta" } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return $Label | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     [bool] ShouldIncludeVersion([SemVer]$Version) { | ||||||
|  |         # For Python, we include all versions greater than 3.9.0 | ||||||
|  |         return $Version -gt [SemVer]"3.9.0" | ||||||
|  |     } | ||||||
|  | } | ||||||
					Loading…
					
					
				
		Reference in New Issue