diff --git a/images/windows/scripts/build/Install-ActionsCache.ps1 b/images/windows/scripts/build/Install-ActionsCache.ps1 index 3680f58e9..95d5665ff 100644 --- a/images/windows/scripts/build/Install-ActionsCache.ps1 +++ b/images/windows/scripts/build/Install-ActionsCache.ps1 @@ -9,7 +9,11 @@ if (-not (Test-Path $env:ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE)) { New-Item -ItemType Directory -Path $env:ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE | Out-Null } -$downloadUrl = Get-GitHubPackageDownloadUrl -RepoOwner "actions" -RepoName "action-versions" -Version "latest" -UrlFilter "*/v{Version}/action-versions.zip" +$downloadUrl = Resolve-GithubReleaseAssetUrl ` + -Repo "actions/action-versions" ` + -Version "latest" ` + -Asset "action-versions.zip" + Write-Host "Download Latest action-versions archive from $downloadUrl" $actionVersionsArchivePath = Start-DownloadWithRetry -Url $downloadUrl -Name "action-versions.zip" diff --git a/images/windows/scripts/build/Install-IEWebDriver.ps1 b/images/windows/scripts/build/Install-IEWebDriver.ps1 index e40f1e8ee..79c0c6cdd 100644 --- a/images/windows/scripts/build/Install-IEWebDriver.ps1 +++ b/images/windows/scripts/build/Install-IEWebDriver.ps1 @@ -4,13 +4,10 @@ ################################################################################ $seleniumMajorVersion = (Get-ToolsetContent).selenium.version -$ieDriverUrl = Get-GitHubPackageDownloadUrl ` - -RepoOwner "SeleniumHQ" ` - -RepoName "selenium" ` - -BinaryName "IEDriverServer_x64" ` - -Version $seleniumMajorVersion ` - -UrlFilter "*{BinaryName}_{Version}.zip" ` - -LatestReleaseOnly $false +$ieDriverUrl = Resolve-GithubReleaseAssetUrl ` + -Repo "SeleniumHQ/selenium" ` + -Version "$seleniumMajorVersion.*" ` + -Asset "IEDriverServer_x64_*.zip" # Download IE selenium driver try { diff --git a/images/windows/scripts/build/Install-Kotlin.ps1 b/images/windows/scripts/build/Install-Kotlin.ps1 index 548ce941a..daeba3246 100644 --- a/images/windows/scripts/build/Install-Kotlin.ps1 +++ b/images/windows/scripts/build/Install-Kotlin.ps1 @@ -6,10 +6,12 @@ # Install Kotlin $kotlinVersion = (Get-ToolsetContent).kotlin.version -$kotlinBinaryName = (Get-ToolsetContent).kotlin.binary_name -$kotlinDownloadUrl = Get-GitHubPackageDownloadUrl -RepoOwner "JetBrains" -RepoName "kotlin" -BinaryName $kotlinBinaryName -Version $kotlinVersion -UrlFilter "*{BinaryName}-{Version}.zip" -$kotlinInstallerPath = Start-DownloadWithRetry -Url $kotlinDownloadUrl -Name "$kotlinBinaryName.zip" +$kotlinDownloadUrl = Resolve-GithubReleaseAssetUrl ` + -Repo "JetBrains/kotlin" ` + -Version $kotlinVersion ` + -Asset "kotlin-compiler-*.zip" +$kotlinInstallerPath = Start-DownloadWithRetry -Url $kotlinDownloadUrl -Name "kotlin-compiler.zip" #region Supply chain security $fileHash = (Get-FileHash -Path $kotlinInstallerPath -Algorithm SHA256).Hash diff --git a/images/windows/scripts/build/Install-Mingw64.ps1 b/images/windows/scripts/build/Install-Mingw64.ps1 index 4c55d1a74..27ec4f91b 100644 --- a/images/windows/scripts/build/Install-Mingw64.ps1 +++ b/images/windows/scripts/build/Install-Mingw64.ps1 @@ -50,12 +50,10 @@ if (Test-IsWin19) { throw "Unknown architecture $_" } - $url = Get-GitHubPackageDownloadUrl ` - -RepoOwner "niXman" ` - -RepoName "mingw-builds-binaries" ` - -BinaryName "" ` - -Version $version ` - -UrlFilter "*$arch-{Version}-release-$threads-$exceptions-$runtime-*.7z" + $url = Resolve-GithubReleaseAssetUrl ` + -Repo "niXman/mingw-builds-binaries" ` + -Version "$version" ` + -Asset "$arch-*-release-$threads-$exceptions-$runtime-*.7z" $packagePath = Start-DownloadWithRetry -Url $url -Name "$_.7z" Expand-7ZipArchive -Path $packagePath -DestinationPath "C:\" diff --git a/images/windows/scripts/build/Install-Selenium.ps1 b/images/windows/scripts/build/Install-Selenium.ps1 index 2c321c8a2..dad6a4ac2 100644 --- a/images/windows/scripts/build/Install-Selenium.ps1 +++ b/images/windows/scripts/build/Install-Selenium.ps1 @@ -9,21 +9,18 @@ New-Item -ItemType directory -Path $seleniumDirectory # Download Selenium $seleniumMajorVersion = (Get-ToolsetContent).selenium.version -$seleniumBinaryName = (Get-ToolsetContent).selenium.binary_name -$seleniumFileName = "$seleniumBinaryName.jar" +$seleniumFileName = "selenium-server.jar" -$seleniumDownloadUrl = Get-GitHubPackageDownloadUrl ` - -RepoOwner "SeleniumHQ" ` - -RepoName "selenium" ` - -BinaryName "$seleniumBinaryName" ` - -Version $seleniumMajorVersion ` - -UrlFilter "*{BinaryName}-{Version}.jar" +$seleniumDownloadUrl = Resolve-GithubReleaseAssetUrl ` + -Repo "SeleniumHQ/selenium" ` + -Version "$seleniumMajorVersion.*" ` + -Asset "selenium-server-*.jar" Start-DownloadWithRetry -Url $seleniumDownloadUrl -Name $seleniumFileName -DownloadPath $seleniumDirectory # Create an empty file to retrive Selenium version $seleniumFullVersion = $seleniumDownloadUrl.Split("-")[1].Split("/")[0] -New-Item -Path $seleniumDirectory -Name "$seleniumBinaryName-$seleniumFullVersion" +New-Item -Path $seleniumDirectory -Name "selenium-server-$seleniumFullVersion" # Add SELENIUM_JAR_PATH environment variable $seleniumBinPath = Join-Path $seleniumDirectory $seleniumFileName diff --git a/images/windows/scripts/docs-gen/SoftwareReport.Browsers.psm1 b/images/windows/scripts/docs-gen/SoftwareReport.Browsers.psm1 index 19dd7cee3..43b0ec847 100644 --- a/images/windows/scripts/docs-gen/SoftwareReport.Browsers.psm1 +++ b/images/windows/scripts/docs-gen/SoftwareReport.Browsers.psm1 @@ -63,12 +63,12 @@ function Get-SeleniumWebDriverVersion { $driverName = $webDrivers.$Driver.Name $driverPath = $webDrivers.$Driver.Path $versionFileName = "versioninfo.txt"; - $webDriverVersion = Get-Content -Path "$driverPath\$versionFileName" + $webDriverVersion = Get-Content -Path "$driverPath\$versionFileName" return [ToolVersionNode]::new($driverName, $webDriverVersion) } function Get-SeleniumVersion { - $seleniumBinaryName = (Get-ToolsetContent).selenium.binary_name + $seleniumBinaryName = "selenium-server" $fullSeleniumVersion = (Get-ChildItem "C:\selenium\${seleniumBinaryName}-*").Name -replace "${seleniumBinaryName}-" return [ToolVersionNode]::new("Selenium server", $fullSeleniumVersion) } diff --git a/images/windows/scripts/helpers/ImageHelpers.psm1 b/images/windows/scripts/helpers/ImageHelpers.psm1 index dfbcd8eb2..38c2ac596 100644 --- a/images/windows/scripts/helpers/ImageHelpers.psm1 +++ b/images/windows/scripts/helpers/ImageHelpers.psm1 @@ -36,7 +36,7 @@ Export-ModuleMember -Function @( 'Install-ChocoPackage' 'Send-RequestToCocolateyPackages' 'Resolve-ChocoPackageVersion' - 'Get-GitHubPackageDownloadUrl' + 'Resolve-GithubReleaseAssetUrl' 'Expand-7ZipArchive' 'Invoke-SBWithRetry' 'Get-VsCatalogJsonPath' diff --git a/images/windows/scripts/helpers/InstallHelpers.ps1 b/images/windows/scripts/helpers/InstallHelpers.ps1 index b1daaee01..df88bdd07 100644 --- a/images/windows/scripts/helpers/InstallHelpers.ps1 +++ b/images/windows/scripts/helpers/InstallHelpers.ps1 @@ -685,55 +685,88 @@ function Invoke-SBWithRetry { } } -function Get-GitHubPackageDownloadUrl { +function Resolve-GithubReleaseAssetUrl { param ( - [string]$RepoOwner, - [string]$RepoName, - [string]$BinaryName, - [string]$Version, - [string]$UrlFilter, - [boolean]$IsPrerelease = $false, - [boolean]$LatestReleaseOnly = $true, - [int]$SearchInCount = 100 + [Parameter(Mandatory = $true)] + [Alias("Repo")] + [string] $Repository, + [Parameter(Mandatory = $true)] + [Alias("Pattern", "File", "Asset")] + [string] $UrlMatchPattern, + [switch] $AllowPrerelease, + [string] $Version = "*" ) + # Add wildcard to the beginning of the pattern if it's not there + if ($UrlMatchPattern.Substring(0, 2) -ne "*/") { + $UrlMatchPattern = "*/$UrlMatchPattern" + } + + $releases = @() + $page = 1 + $pageSize = 100 + do { + $releasesPage = Invoke-RestMethod -Uri "https://api.github.com/repos/${Repository}/releases?per_page=${pageSize}&page=${page}" + $releases += $releasesPage + $page++ + } while ($releasesPage.Count -eq $pageSize) + Write-Debug "Found $($releases.Count) releases for ${Repository}" + + if (-not $releases) { + throw "Failed to get releases from ${Repository}" + } + + $releases = $releases.Where{ $_.assets } + if (-not $AllowPrerelease) { + $releases = $releases.Where{ $_.prerelease -eq $false } + } + Write-Debug "Found $($releases.Count) releases with assets for ${Repository}" + + # Parse version from tag name and put it to parameter Version + foreach ($release in $releases) { + $release | Add-Member -MemberType NoteProperty -Name version -Value ( + $release.tag_name | Select-String -Pattern "\d+.\d+.\d+" | ForEach-Object { $_.Matches.Value } + ) + } + + # Sort releases by version + $releases = $releases | Sort-Object -Descending { [version]$_.version } + + # Select releases matching version if ($Version -eq "latest") { - $Version = "*" - } - - $json = Invoke-RestMethod -Uri "https://api.github.com/repos/${RepoOwner}/${RepoName}/releases?per_page=${SearchInCount}" - $tags = $json.Where{ $_.prerelease -eq $IsPrerelease -and $_.assets }.tag_name - $availableVersions = $tags | - Select-String -Pattern "\d+.\d+.\d+" | - ForEach-Object { $_.Matches.Value } | - Where-Object { $_ -like "$Version.*" -or $_ -eq $Version } | - Sort-Object -Descending { [version]$_ } - - if (-not $availableVersions) { - throw "Failed to get available versions from ${RepoOwner}/${RepoName} releases" - } - - if ($LatestReleaseOnly) { - $latestVersion = $availableVersions | Select-Object -First 1 - $urlFilterReplaced = $UrlFilter -replace "{BinaryName}", $BinaryName -replace "{Version}", $latestVersion - $downloadUrl = $json.assets.browser_download_url -like $urlFilterReplaced + $matchingReleases = $releases | Select-Object -First 1 + } elseif ($Version.Contains("*")) { + $matchingReleases = $releases | Where-Object { $_.version -like "$Version" } } else { - foreach ($version in $availableVersions) { - $urlFilterReplaced = $UrlFilter -replace "{BinaryName}", $BinaryName -replace "{Version}", $version - $downloadUrl = $json.assets.browser_download_url -like $urlFilterReplaced + $matchingReleases = $releases | Where-Object { $_.version -eq "$Version" } + } - if ($downloadUrl) { - Write-Host "Found download url for ${RepoOwner}/${RepoName} ${BinaryName} ${version}" - break - } + if (-not $matchingReleases) { + throw "Failed to get releases from ${Repository} matching version `"${Version}`".`nAvailable versions: $($availableVersions -join ", ")" + } + Write-Debug "Found $($matchingReleases.Count) releases matching version ${Version} for ${Repository}" + + # Loop over releases until we find a download url matching the pattern + foreach ($release in $matchingReleases) { + $matchedVersion = $release.version + $matchedUrl = $release.assets.browser_download_url -like $UrlMatchPattern + if ($matchedUrl) { + break } } - if (-not $downloadUrl) { - throw "Failed to get download url for ${RepoOwner}/${RepoName} ${BinaryName}" + if (-not $matchedUrl) { + Write-Debug "Found no download urls matching pattern ${UrlMatchPattern}" + Write-Debug "Available download urls:`n$($matchingReleases.assets.browser_download_url -join "`n")" + throw "No assets found in ${Repository} matching version `"${Version}`" and pattern `"${UrlMatchPattern}`"" + } elseif ($matchedUrl.Count -gt 1) { + Write-Debug "Found multiple download urls matching pattern ${UrlMatchPattern}:`n$($matchedUrl -join "`n")" + throw "Multiple download urls found in ${Repository} version `"${matchedVersion}`" matching pattern `"${UrlMatchPattern}`":`n$($matchedUrl -join "`n")" } - return $downloadUrl + Write-Host "Found download url for ${Repository} version ${matchedVersion}: ${matchedUrl}" + + return ($matchedUrl -as [string]) } function Use-ChecksumComparison { diff --git a/images/windows/scripts/tests/Browsers.Tests.ps1 b/images/windows/scripts/tests/Browsers.Tests.ps1 index 24b65803b..b92d20083 100644 --- a/images/windows/scripts/tests/Browsers.Tests.ps1 +++ b/images/windows/scripts/tests/Browsers.Tests.ps1 @@ -146,8 +146,7 @@ Describe "Internet Explorer" { Describe "Selenium" { BeforeAll { - $seleniumBinaryName = (Get-ToolsetContent).selenium.binary_name - $seleniumBinPath = Join-Path "C:\selenium\" "$seleniumBinaryName.jar" + $seleniumBinPath = "C:\selenium\selenium-server.jar" } It "Selenium server is installed" { @@ -157,4 +156,4 @@ Describe "Selenium" { It "SELENIUM_JAR_PATH environment variable exists" { Get-EnvironmentVariable "SELENIUM_JAR_PATH" | Should -BeExactly "$seleniumBinPath" } -} \ No newline at end of file +} diff --git a/images/windows/toolsets/toolset-2019.json b/images/windows/toolsets/toolset-2019.json index 143fcab69..ad0b81a89 100644 --- a/images/windows/toolsets/toolset-2019.json +++ b/images/windows/toolsets/toolset-2019.json @@ -392,8 +392,7 @@ } ], "selenium": { - "version": "4", - "binary_name": "selenium-server" + "version": "4" }, "npm": { "global_packages": [ @@ -488,8 +487,7 @@ "signature": "698BA51AA27CC31282AACA5055E4B9190BC6C0E9" }, "kotlin": { - "version": "latest", - "binary_name": "kotlin-compiler" + "version": "latest" }, "openssl": { "version": "1.1.1" diff --git a/images/windows/toolsets/toolset-2022.json b/images/windows/toolsets/toolset-2022.json index 694e72d33..5c0f6abdb 100644 --- a/images/windows/toolsets/toolset-2022.json +++ b/images/windows/toolsets/toolset-2022.json @@ -339,8 +339,7 @@ } ], "selenium": { - "version": "4", - "binary_name": "selenium-server" + "version": "4" }, "npm": { "global_packages": [ @@ -428,8 +427,7 @@ "signature": "698BA51AA27CC31282AACA5055E4B9190BC6C0E9" }, "kotlin": { - "version": "latest", - "binary_name": "kotlin-compiler" + "version": "latest" }, "openssl": { "version": "1.1.1"