[Windows] Cleanup various scripts (#8942)

* Use Resolve-GithubReleaseAssetUrl more widely

* Add the Get-ChecksumFromUrl function

* Sort exported functions and add docs

* Remove alias and fix typo

* Fix kind checksum url and syntax

* Fix checksums url for gh cli and msys2

* [Windows] Cleanup various scripts

* Add spaces after type specifications

* Rename the Take-Part function
This commit is contained in:
Vasilii Polikarpov
2023-12-04 10:50:53 +01:00
committed by GitHub
parent ed911223ab
commit 5ed2615017
56 changed files with 770 additions and 568 deletions

View File

@@ -41,7 +41,7 @@ Here are a few things you can do that will increase the likelihood of your pull
### Windows ### Windows
- Add a script that will install the tool and put the script in the `scripts/build` folder. - Add a script that will install the tool and put the script in the `scripts/build` folder.
There are a bunch of helper functions that could simplify your code: `Choco-Install`, `Install-Binary`, `Install-VsixExtension`, `Start-DownloadWithRetry`, `Test-IsWin19`, `Test-IsWin22` (find the full list of helpers in [ImageHelpers.psm1](images/windows/scripts/helpers/ImageHelpers.psm1)). There are a bunch of helper functions that could simplify your code: `Install-ChocoPackage`, `Install-Binary`, `Install-VSIXFromFile`, `Install-VSIXFromUrl`, `Invoke-DownloadWithRetry`, `Test-IsWin19`, `Test-IsWin22` (find the full list of helpers in [ImageHelpers.psm1](images/windows/scripts/helpers/ImageHelpers.psm1)).
- Add a script that will validate the tool installation and put the script in the `scripts/tests` folder. - Add a script that will validate the tool installation and put the script in the `scripts/tests` folder.
We use [Pester v5](https://github.com/pester/pester) for validation scripts. If the tests for the tool are complex enough, create a separate `*.Tests.ps1`. Otherwise, use `Tools.Tests.ps1` for simple tests. We use [Pester v5](https://github.com/pester/pester) for validation scripts. If the tests for the tool are complex enough, create a separate `*.Tests.ps1`. Otherwise, use `Tools.Tests.ps1` for simple tests.
Add `Invoke-PesterTests -TestFile <testFileName> [-TestName <describeName>]` at the end of the installation script to make sure that your tests will be run. Add `Invoke-PesterTests -TestFile <testFileName> [-TestName <describeName>]` at the end of the installation script to make sure that your tests will be run.

View File

@@ -13,7 +13,7 @@ Set-PSRepository -InstallationPolicy Trusted -Name PSGallery
Write-Host 'Warmup PSModuleAnalysisCachePath (speedup first powershell invocation by 20s)' Write-Host 'Warmup PSModuleAnalysisCachePath (speedup first powershell invocation by 20s)'
$PSModuleAnalysisCachePath = 'C:\PSModuleAnalysisCachePath\ModuleAnalysisCache' $PSModuleAnalysisCachePath = 'C:\PSModuleAnalysisCachePath\ModuleAnalysisCache'
[Environment]::SetEnvironmentVariable('PSModuleAnalysisCachePath', $PSModuleAnalysisCachePath, [System.EnvironmentVariableTarget]::Machine) [Environment]::SetEnvironmentVariable('PSModuleAnalysisCachePath', $PSModuleAnalysisCachePath, "Machine")
# make variable to be available in the current session # make variable to be available in the current session
${env:PSModuleAnalysisCachePath} = $PSModuleAnalysisCachePath ${env:PSModuleAnalysisCachePath} = $PSModuleAnalysisCachePath

View File

@@ -19,7 +19,7 @@ $downloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "awslabs/aws-sam-cli" ` -Repo "awslabs/aws-sam-cli" `
-Version "latest" ` -Version "latest" `
-UrlMatchPattern "AWS_SAM_CLI_64_PY3.msi" -UrlMatchPattern "AWS_SAM_CLI_64_PY3.msi"
$externalHash = Get-GithubReleaseAssetHash ` $externalHash = Get-ChecksumFromGithubRelease `
-Repo "awslabs/aws-sam-cli" ` -Repo "awslabs/aws-sam-cli" `
-Version "latest" ` -Version "latest" `
-FileName (Split-Path $downloadUrl -Leaf) ` -FileName (Split-Path $downloadUrl -Leaf) `

View File

@@ -5,15 +5,17 @@
################################################################################ ################################################################################
Write-Host "Download Latest aliyun-cli archive" Write-Host "Download Latest aliyun-cli archive"
$repoUrl = "https://api.github.com/repos/aliyun/aliyun-cli/releases/latest" $downloadUrl = Resolve-GithubReleaseAssetUrl `
$installerFileName = "aliyun-cli-windows" -Repo "aliyun/aliyun-cli" `
$assets = (Invoke-RestMethod -Uri $repoUrl).assets -Version "latest" `
$downloadUrl = ($assets.browser_download_url -ilike "*aliyun-cli-windows-*-amd64.zip*") | Select-Object -First 1 -UrlMatchPattern "aliyun-cli-windows-*-amd64.zip"
$packagePath = Invoke-DownloadWithRetry $downloadUrl $packagePath = Invoke-DownloadWithRetry $downloadUrl
#region Supply chain security - Alibaba Cloud CLI #region Supply chain security - Alibaba Cloud CLI
$hashUrl = ($assets.browser_download_url -ilike "*SHASUMS256.txt*") | Select-Object -First 1 $packageName = Split-Path $downloadUrl -Leaf
$externalHash = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*$installerFileName*" }).Split(' ')[0] $externalHash = Get-ChecksumFromUrl -Type "SHA256" `
-Url ($downloadUrl -replace $packageName, "SHASUMS256.txt") `
-FileName $packageName
Test-FileChecksum $packagePath -ExpectedSHA256Sum $externalHash Test-FileChecksum $packagePath -ExpectedSHA256Sum $externalHash
#endregion #endregion

View File

@@ -7,26 +7,20 @@ Write-Host 'Install the latest Azure CLI release'
$azureCliConfigPath = 'C:\azureCli' $azureCliConfigPath = 'C:\azureCli'
# Store azure-cli cache outside of the provisioning user's profile # Store azure-cli cache outside of the provisioning user's profile
[Environment]::SetEnvironmentVariable('AZURE_CONFIG_DIR', $azureCliConfigPath, [System.EnvironmentVariableTarget]::Machine) [Environment]::SetEnvironmentVariable('AZURE_CONFIG_DIR', $azureCliConfigPath, "Machine")
# make variable to be available in the current session
${env:AZURE_CONFIG_DIR} = $azureCliConfigPath $azureCliExtensionPath = Join-Path $Env:CommonProgramFiles 'AzureCliExtensionDirectory'
New-Item -ItemType 'Directory' -Path $azureCliExtensionPath | Out-Null
[Environment]::SetEnvironmentVariable('AZURE_EXTENSION_DIR', $azureCliExtensionPath, "Machine")
Install-Binary -Type MSI ` Install-Binary -Type MSI `
-Url 'https://aka.ms/installazurecliwindowsx64' ` -Url 'https://aka.ms/installazurecliwindowsx64' `
-ExpectedSignature '72105B6D5F370B62FD5C82F1512F7AD7DEE5F2C0' -ExpectedSignature '72105B6D5F370B62FD5C82F1512F7AD7DEE5F2C0'
$azureCliExtensionPath = Join-Path $Env:CommonProgramFiles 'AzureCliExtensionDirectory' Update-Environment
$null = New-Item -ItemType 'Directory' -Path $azureCliExtensionPath
[Environment]::SetEnvironmentVariable('AZURE_EXTENSION_DIR', $azureCliExtensionPath, [System.EnvironmentVariableTarget]::Machine)
# make variable to be available in the current session
${env:AZURE_EXTENSION_DIR} = $azureCliExtensionPath
# Warm-up Azure CLI # Warm-up Azure CLI
Write-Host "Warmup 'az'" Write-Host "Warmup 'az'"
$env:PATH = [Environment]::GetEnvironmentVariable('PATH', 'Machine')
az --help | Out-Null az --help | Out-Null
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
throw "Command 'az --help' failed" throw "Command 'az --help' failed"

View File

@@ -5,34 +5,26 @@
$azureDevOpsCliConfigPath = 'C:\azureDevOpsCli' $azureDevOpsCliConfigPath = 'C:\azureDevOpsCli'
# Store azure-devops-cli cache outside of the provisioning user's profile # Store azure-devops-cli cache outside of the provisioning user's profile
[Environment]::SetEnvironmentVariable('AZ_DEVOPS_GLOBAL_CONFIG_DIR', $azureDevOpsCliConfigPath, [System.EnvironmentVariableTarget]::Machine) [Environment]::SetEnvironmentVariable('AZ_DEVOPS_GLOBAL_CONFIG_DIR', $azureDevOpsCliConfigPath, "Machine")
# make variable to be available in the current session
${env:AZ_DEVOPS_GLOBAL_CONFIG_DIR} = $azureDevOpsCliConfigPath
$azureDevOpsCliCachePath = Join-Path $azureDevOpsCliConfigPath 'cache' $azureDevOpsCliCachePath = Join-Path $azureDevOpsCliConfigPath 'cache'
$null = New-Item -ItemType 'Directory' -Path $azureDevOpsCliCachePath New-Item -ItemType 'Directory' -Path $azureDevOpsCliCachePath | Out-Null
[Environment]::SetEnvironmentVariable('AZURE_DEVOPS_CACHE_DIR', $azureDevOpsCliCachePath, "Machine")
[Environment]::SetEnvironmentVariable('AZURE_DEVOPS_CACHE_DIR', $azureDevOpsCliCachePath, [System.EnvironmentVariableTarget]::Machine) Update-Environment
# make variable to be available in the current session
${env:AZURE_DEVOPS_CACHE_DIR} = $azureDevOpsCliCachePath
az extension add -n azure-devops az extension add -n azure-devops
if ($LASTEXITCODE -ne 0) if ($LASTEXITCODE -ne 0) {
{
throw "Command 'az extension add -n azure-devops' failed" throw "Command 'az extension add -n azure-devops' failed"
} }
# Warm-up Azure DevOps CLI # Warm-up Azure DevOps CLI
Write-Host "Warmup 'az-devops'" Write-Host "Warmup 'az-devops'"
@('devops', 'pipelines', 'boards', 'repos', 'artifacts') | ForEach-Object { @('devops', 'pipelines', 'boards', 'repos', 'artifacts') | ForEach-Object {
az $_ --help
az $_ --help if ($LASTEXITCODE -ne 0) {
if ($LASTEXITCODE -ne 0) throw "Command 'az $_ --help' failed"
{ }
throw "Command 'az $_ --help' failed"
}
} }
# calling az devops login to force it to install `keyring`. Login will actually fail, redirecting error to null # calling az devops login to force it to install `keyring`. Login will actually fail, redirecting error to null

View File

@@ -6,5 +6,8 @@
Install-ChocoPackage bazel Install-ChocoPackage bazel
npm install -g @bazel/bazelisk npm install -g @bazel/bazelisk
if ($LASTEXITCODE -ne 0) {
throw "Command 'npm install -g @bazel/bazelisk' failed"
}
Invoke-PesterTests -TestFile "Tools" -TestName "Bazel" Invoke-PesterTests -TestFile "Tools" -TestName "Bazel"

View File

@@ -7,20 +7,10 @@ Write-Host "Set TLS1.2"
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor "Tls12" [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor "Tls12"
Write-Host "Install chocolatey" Write-Host "Install chocolatey"
$chocoExePath = 'C:\ProgramData\Chocolatey\bin'
# Add to system PATH # Add to system PATH
$systemPath = [Environment]::GetEnvironmentVariable('Path', [System.EnvironmentVariableTarget]::Machine) Add-MachinePathItem 'C:\ProgramData\Chocolatey\bin'
$systemPath += ';' + $chocoExePath Update-Environment
[Environment]::SetEnvironmentVariable("PATH", $systemPath, [System.EnvironmentVariableTarget]::Machine)
# Update local process' path
$userPath = [Environment]::GetEnvironmentVariable('Path', [System.EnvironmentVariableTarget]::User)
if ($userPath) {
$env:Path = $systemPath + ";" + $userPath
} else {
$env:Path = $systemPath
}
# Verify and run choco installer # Verify and run choco installer
$signatureThumbprint = "83AC7D88C66CB8680BCE802E0F0F5C179722764B" $signatureThumbprint = "83AC7D88C66CB8680BCE802E0F0F5C179722764B"

View File

@@ -33,8 +33,7 @@ $regGoogleParameters = @(
$regGoogleParameters | ForEach-Object { $regGoogleParameters | ForEach-Object {
$Arguments = $_ $Arguments = $_
if (-not ($Arguments.Path)) if (-not ($Arguments.Path)) {
{
$Arguments.Add("Path", $regGoogleUpdatePath) $Arguments.Add("Path", $regGoogleUpdatePath)
} }
$Arguments.Add("Force", $true) $Arguments.Add("Force", $true)
@@ -44,15 +43,14 @@ $regGoogleParameters | ForEach-Object {
# Install Chrome WebDriver # Install Chrome WebDriver
Write-Host "Install Chrome WebDriver..." Write-Host "Install Chrome WebDriver..."
$ChromeDriverPath = "$($env:SystemDrive)\SeleniumWebDrivers\ChromeDriver" $ChromeDriverPath = "$($env:SystemDrive)\SeleniumWebDrivers\ChromeDriver"
if (-not (Test-Path -Path $ChromeDriverPath)) if (-not (Test-Path -Path $ChromeDriverPath)) {
{
New-Item -Path $ChromeDriverPath -ItemType Directory -Force New-Item -Path $ChromeDriverPath -ItemType Directory -Force
} }
Write-Host "Get the Chrome WebDriver download URL..." Write-Host "Get the Chrome WebDriver download URL..."
$RegistryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths" $RegistryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths"
$ChromePath = (Get-ItemProperty "$RegistryPath\chrome.exe").'(default)' $ChromePath = (Get-ItemProperty "$RegistryPath\chrome.exe").'(default)'
[version]$ChromeVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($ChromePath).ProductVersion [version] $ChromeVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($ChromePath).ProductVersion
$ChromeBuild = "$($ChromeVersion.Major).$($ChromeVersion.Minor).$($ChromeVersion.Build)" $ChromeBuild = "$($ChromeVersion.Major).$($ChromeVersion.Minor).$($ChromeVersion.Build)"
$ChromeDriverVersionsUrl = "https://googlechromelabs.github.io/chrome-for-testing/latest-patch-versions-per-build-with-downloads.json" $ChromeDriverVersionsUrl = "https://googlechromelabs.github.io/chrome-for-testing/latest-patch-versions-per-build-with-downloads.json"
@@ -63,7 +61,7 @@ $ChromeDriverVersion = $ChromeDriverVersions.builds.$ChromeBuild
if (-not ($ChromeDriverVersion)) { if (-not ($ChromeDriverVersion)) {
$availableVersions = $ChromeDriverVersions.builds | Get-Member | Select-Object -ExpandProperty Name $availableVersions = $ChromeDriverVersions.builds | Get-Member | Select-Object -ExpandProperty Name
Write-Host "Available chromedriver builds are $availableVersions" Write-Host "Available chromedriver builds are $availableVersions"
Throw "Can't determine chromedriver version that matches chrome build $ChromeBuild" throw "Can't determine chromedriver version that matches chrome build $ChromeBuild"
} }
$ChromeDriverVersion.version | Out-File -FilePath "$ChromeDriverPath\versioninfo.txt" -Force; $ChromeDriverVersion.version | Out-File -FilePath "$ChromeDriverPath\versioninfo.txt" -Force;
@@ -79,10 +77,7 @@ Expand-7ZipArchive -Path $ChromeDriverArchPath -DestinationPath $ChromeDriverPat
Write-Host "Setting the environment variables..." Write-Host "Setting the environment variables..."
[Environment]::SetEnvironmentVariable("ChromeWebDriver", $ChromeDriverPath, "Machine") [Environment]::SetEnvironmentVariable("ChromeWebDriver", $ChromeDriverPath, "Machine")
Add-MachinePathItem $ChromeDriverPath
$regEnvKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\' Update-Environment
$PathValue = Get-ItemPropertyValue -Path $regEnvKey -Name 'Path'
$PathValue += ";$ChromeDriverPath\"
Set-ItemProperty -Path $regEnvKey -Name 'Path' -Value $PathValue
Invoke-PesterTests -TestFile "Browsers" -TestName "Chrome" Invoke-PesterTests -TestFile "Browsers" -TestName "Chrome"

View File

@@ -6,15 +6,16 @@
################################################################################ ################################################################################
Write-Host "Get latest Moby release" Write-Host "Get latest Moby release"
$mobyLatestReleaseVersion = (Invoke-RestMethod -Uri "https://api.github.com/repos/moby/moby/releases/latest").tag_name.Trim("v") $mobyLatestVersion = (Get-GithubReleasesByVersion -Repo "moby/moby" -Version "latest").version
$dockerceUrl = "https://download.docker.com/win/static/stable/x86_64/" $dockerceUrl = "https://download.docker.com/win/static/stable/x86_64/"
$dockerceBinaries = Invoke-WebRequest -Uri $dockerceUrl -UseBasicParsing $dockerceBinaries = Invoke-WebRequest -Uri $dockerceUrl -UseBasicParsing
Write-Host "Check Moby version $mobyLatestReleaseVersion" Write-Host "Check Moby version $mobyLatestVersion"
$mobyRelease = $dockerceBinaries.Links.href -match "${mobyLatestReleaseVersion}\.zip" | Select-Object -Last 1 $mobyRelease = $dockerceBinaries.Links.href -match "${mobyLatestVersion}\.zip" | Select-Object -Last 1
if (-not $mobyRelease) { if (-not $mobyRelease) {
Write-Host "Release not found for $mobyLatestRelease version" Write-Host "Release not found for $mobyLatestRelease version"
$versions = [regex]::Matches($dockerceBinaries.Links.href, "docker-(\d+\.\d+\.\d+)\.zip") | Sort-Object { [version]$_.Groups[1].Value } $versions = [regex]::Matches($dockerceBinaries.Links.href, "docker-(\d+\.\d+\.\d+)\.zip") | Sort-Object { [version] $_.Groups[1].Value }
$mobyRelease = $versions | Select-Object -ExpandProperty Value -Last 1 $mobyRelease = $versions | Select-Object -ExpandProperty Value -Last 1
Write-Host "Found $mobyRelease" Write-Host "Found $mobyRelease"
} }
@@ -47,8 +48,7 @@ foreach ($dockerImage in $dockerImages) {
docker pull $dockerImage docker pull $dockerImage
if (!$?) { if (!$?) {
Write-Host "Docker pull failed with a non-zero exit code" throw "Docker pull failed with a non-zero exit code ($LastExitCode)"
exit 1
} }
} }

View File

@@ -4,32 +4,19 @@
## Supply chain security: checksum validation ## Supply chain security: checksum validation
################################################################################ ################################################################################
#region functions
function Get-DockerWincredHash {
Param (
[Parameter(Mandatory = $True)]
[string] $Release
)
$hashURL = "https://github.com/docker/docker-credential-helpers/releases/download/${Release}/checksums.txt"
(Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*docker-credential-wincred-${Release}.windows-amd64.exe*" }).Split(' ')[0]
}
#endregion
Write-Host "Install docker-wincred" Write-Host "Install docker-wincred"
$dockerCredLatestRelease = Invoke-RestMethod -Uri "https://api.github.com/repos/docker/docker-credential-helpers/releases/latest" $downloadUrl = Resolve-GithubReleaseAssetUrl `
$dockerCredDownloadUrl = $dockerCredLatestRelease.assets.browser_download_url -match "docker-credential-wincred-.+\.exe" | Select-Object -First 1 -Repo "docker/docker-credential-helpers" `
Invoke-DownloadWithRetry -Url $dockerCredDownloadUrl -Path "C:\Windows\System32\docker-credential-wincred.exe" -Version "latest" `
-UrlMatchPattern "docker-credential-wincred-*amd64.exe"
$binaryPath = Invoke-DownloadWithRetry -Url $downloadUrl -Path "C:\Windows\System32\docker-credential-wincred.exe"
#region Supply chain security #region Supply chain security
$distributor_file_hash = Get-DockerWincredHash -Release $dockerCredLatestRelease.name $binaryName = Split-Path $downloadUrl -Leaf
$local_file_hash = (Get-FileHash -Path 'C:\Windows\System32\docker-credential-wincred.exe' -Algorithm SHA256).Hash $externalHash = Get-ChecksumFromUrl -Type "SHA256" `
-Url ($downloadUrl -replace $binaryName, "checksums.txt") `
if ($local_file_hash -ne $distributor_file_hash) { -FileName $binaryName
Write-Host "hash must be equal to: ${distributor_file_hash}" Test-FileChecksum -Path $binaryPath -ExpectedSHA256Sum $externalHash
Write-Host "actual hash is: ${local_file_hash}"
throw 'Checksum verification failed, please rerun install'
}
#endregion #endregion
Invoke-PesterTests -TestFile "Docker" -TestName "DockerWinCred" Invoke-PesterTests -TestFile "Docker" -TestName "DockerWinCred"

View File

@@ -6,36 +6,40 @@
################################################################################ ################################################################################
# Set environment variables # Set environment variables
[System.Environment]::SetEnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0", "Machine") [Environment]::SetEnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0", "Machine")
[System.Environment]::SetEnvironmentVariable("DOTNET_NOLOGO", "1", "Machine") [Environment]::SetEnvironmentVariable("DOTNET_NOLOGO", "1", "Machine")
[System.Environment]::SetEnvironmentVariable("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "1", "Machine") [Environment]::SetEnvironmentVariable("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "1", "Machine")
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor "Tls12" [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor "Tls12"
#region "Functions" #region "Functions"
function Get-SDKVersionsToInstall ( function Get-SDKVersionsToInstall {
$DotnetVersion param (
) { [Parameter(Mandatory)]
$metadataJsonUri = "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/${DotnetVersion}/releases.json" [string] $DotnetVersion
$currentReleases = Invoke-DownloadWithRetry $metadataJsonUri | Get-Item | Get-Content | ConvertFrom-Json )
$releasesJsonUri = "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/${DotnetVersion}/releases.json"
$releasesData = (Invoke-DownloadWithRetry $releasesJsonUri) | Get-Item | Get-Content | ConvertFrom-Json
# filtering out the preview/rc releases # filtering out the preview/rc releases
$currentReleases = $currentReleases.'releases' | Where-Object { !$_.'release-version'.Contains('-') } $releases = $releasesData.'releases' | Where-Object { !$_.'release-version'.Contains('-') }
$sdks = @() $sdks = @()
foreach ($release in $currentReleases) { foreach ($release in $releases) {
$sdks += $release.'sdk' $sdks += $release.'sdk'
$sdks += $release.'sdks' $sdks += $release.'sdks'
} }
return $sdks.version ` return $sdks.version `
| Sort-Object { [Version] $_ } -Unique ` | Sort-Object { [Version] $_ } -Unique `
| Group-Object { $_.Substring(0, $_.LastIndexOf('.') + 2) } ` | Group-Object { $_.Substring(0, $_.LastIndexOf('.') + 2) } `
| ForEach-Object { $_.Group[-1] } | ForEach-Object { $_.Group[-1] }
} }
function Invoke-Warmup ( function Invoke-DotnetWarmup {
$SdkVersion param (
) { [Parameter(Mandatory)]
[string] $SDKVersion
)
# warm up dotnet for first time experience # warm up dotnet for first time experience
$projectTypes = @('console', 'mstest', 'web', 'mvc', 'webapi') $projectTypes = @('console', 'mstest', 'web', 'mvc', 'webapi')
$projectTypes | ForEach-Object { $projectTypes | ForEach-Object {
@@ -43,85 +47,76 @@ function Invoke-Warmup (
$projectPath = Join-Path -Path C:\temp -ChildPath $template $projectPath = Join-Path -Path C:\temp -ChildPath $template
New-Item -Path $projectPath -Force -ItemType Directory New-Item -Path $projectPath -Force -ItemType Directory
Push-Location -Path $projectPath Push-Location -Path $projectPath
& $env:ProgramFiles\dotnet\dotnet.exe new globaljson --sdk-version "$sdkVersion" & $env:ProgramFiles\dotnet\dotnet.exe new globaljson --sdk-version "$SDKVersion"
& $env:ProgramFiles\dotnet\dotnet.exe new $template & $env:ProgramFiles\dotnet\dotnet.exe new $template
Pop-Location Pop-Location
Remove-Item $projectPath -Force -Recurse Remove-Item $projectPath -Force -Recurse
} }
} }
function InstallSDKVersion ( function Install-DotnetSDK {
$SdkVersion, param (
$dotnetVersion, [Parameter(Mandatory)]
$Warmup [string] $InstallScriptPath,
) { [Parameter(Mandatory)]
if (!(Test-Path -Path "C:\Program Files\dotnet\sdk\$sdkVersion")) { [Alias('Version')]
Write-Host "Installing dotnet $sdkVersion" [string] $SDKVersion,
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName()) [Parameter(Mandatory)]
.\dotnet-install.ps1 -Version $sdkVersion -InstallDir $(Join-Path -Path $env:ProgramFiles -ChildPath 'dotnet') -ZipPath $ZipPath -KeepZip [string] $DotnetVersion
)
#region Supply chain security if (Test-Path -Path "C:\Program Files\dotnet\sdk\$SDKVersion") {
$distributorFileHash = (Invoke-RestMethod -Uri "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/$dotnetVersion/releases.json").releases.sdks.Where({ $_.version -eq $SdkVersion }).files.Where({ $_.name -eq 'dotnet-sdk-win-x64.zip' }).hash Write-Host "Sdk version $SDKVersion already installed"
Test-FileChecksum $ZipPath -ExpectedSHA512Sum $distributorFileHash return
#endregion
} else {
Write-Host "Sdk version $sdkVersion already installed"
} }
if ($Warmup) { Write-Host "Installing dotnet $SDKVersion"
Invoke-Warmup -SdkVersion $SdkVersion $zipPath = Join-Path ([IO.Path]::GetTempPath()) ([IO.Path]::GetRandomFileName())
} & $InstallScriptPath -Version $SDKVersion -InstallDir $(Join-Path -Path $env:ProgramFiles -ChildPath 'dotnet') -ZipPath $zipPath -KeepZip
#region Supply chain security
$releasesJsonUri = "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/${DotnetVersion}/releases.json"
$releasesData = (Invoke-DownloadWithRetry $releasesJsonUri) | Get-Item | Get-Content | ConvertFrom-Json
$distributorFileHash = $releasesData.releases.sdks.Where({ $_.version -eq $SDKVersion }).files.Where({ $_.name -eq 'dotnet-sdk-win-x64.zip' }).hash
Test-FileChecksum $zipPath -ExpectedSHA512Sum $distributorFileHash
#endregion
} }
#endregion
function InstallAllValidSdks() { $dotnetToolset = (Get-ToolsetContent).dotnet
# Consider all channels except preview/eol channels.
# Sort the channels in ascending order
$dotnetToolset = (Get-ToolsetContent).dotnet
$dotnetVersions = $dotnetToolset.versions
$warmup = $dotnetToolset.warmup
# Download installation script. # Download installation script.
$installationName = "dotnet-install.ps1" $installScriptPath = Invoke-DownloadWithRetry -Url "https://dot.net/v1/dotnet-install.ps1"
$installationUrl = "https://dot.net/v1/${installationName}"
Invoke-DownloadWithRetry -Url $installationUrl -Path ".\$installationName"
foreach ($dotnetVersion in $dotnetVersions) { # Install and warm up dotnet
$sdkVersionsToInstall = Get-SDKVersionsToInstall -DotnetVersion $dotnetVersion foreach ($dotnetVersion in $dotnetToolset.versions) {
foreach ($sdkVersion in $sdkVersionsToInstall) { $sdkVersionsToInstall = Get-SDKVersionsToInstall -DotnetVersion $dotnetVersion
InstallSDKVersion -SdkVersion $sdkVersion -DotnetVersion $dotnetVersion -Warmup $warmup foreach ($sdkVersion in $sdkVersionsToInstall) {
Install-DotnetSDK -InstallScriptPath $installScriptPath -SDKVersion $sdkVersion -DotnetVersion $dotnetVersion
if ($dotnetToolset.warmup) {
Invoke-DotnetWarmup -SDKVersion $sdkVersion
} }
} }
} }
function InstallTools() { # Add dotnet to PATH
$dotnetTools = (Get-ToolsetContent).dotnet.tools Add-MachinePathItem "C:\Program Files\dotnet"
foreach ($dotnetTool in $dotnetTools) { # Remove NuGet Folder
dotnet tool install $($dotnetTool.name) --tool-path "C:\Users\Default\.dotnet\tools" --add-source https://api.nuget.org/v3/index.json | Out-Null $nugetPath = "$env:APPDATA\NuGet"
} if (Test-Path $nugetPath) {
Remove-Item -Path $nugetPath -Force -Recurse
} }
function RunPostInstallationSteps() { # Generate and copy new NuGet.Config config
# Add dotnet to PATH dotnet nuget list source | Out-Null
Add-MachinePathItem "C:\Program Files\dotnet" Copy-Item -Path $nugetPath -Destination C:\Users\Default\AppData\Roaming -Force -Recurse
# Remove NuGet Folder # Install dotnet tools
$nugetPath = "$env:APPDATA\NuGet" Write-Host "Installing dotnet tools"
if (Test-Path $nugetPath) { Add-DefaultPathItem "%USERPROFILE%\.dotnet\tools"
Remove-Item -Path $nugetPath -Force -Recurse foreach ($dotnetTool in $dotnetToolset.tools) {
} dotnet tool install $($dotnetTool.name) --tool-path "C:\Users\Default\.dotnet\tools" --add-source https://api.nuget.org/v3/index.json | Out-Null
# Generate and copy new NuGet.Config config
dotnet nuget list source | Out-Null
Copy-Item -Path $nugetPath -Destination C:\Users\Default\AppData\Roaming -Force -Recurse
# Add %USERPROFILE%\.dotnet\tools to USER PATH
Add-DefaultPathItem "%USERPROFILE%\.dotnet\tools"
} }
#endregion
InstallAllValidSdks
RunPostInstallationSteps
InstallTools
Invoke-PesterTests -TestFile "DotnetSDK" Invoke-PesterTests -TestFile "DotnetSDK"

View File

@@ -11,7 +11,10 @@ $VersionsManifest = Invoke-RestMethod "https://product-details.mozilla.org/1.0/f
Write-Host "Install Firefox browser..." Write-Host "Install Firefox browser..."
$installerUrl = "https://download.mozilla.org/?product=firefox-$($VersionsManifest.LATEST_FIREFOX_VERSION)&os=win64&lang=en-US" $installerUrl = "https://download.mozilla.org/?product=firefox-$($VersionsManifest.LATEST_FIREFOX_VERSION)&os=win64&lang=en-US"
$hashUrl = "https://archive.mozilla.org/pub/firefox/releases/$($VersionsManifest.LATEST_FIREFOX_VERSION)/SHA256SUMS" $hashUrl = "https://archive.mozilla.org/pub/firefox/releases/$($VersionsManifest.LATEST_FIREFOX_VERSION)/SHA256SUMS"
$externalHash = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*win64/en-US/Firefox Setup*exe*" }).Split(' ')[0]
$externalHash = Get-ChecksumFromUrl -Type "SHA256" `
-Url $hashUrl `
-FileName "win64/en-US/Firefox Setup*exe"
Install-Binary -Type EXE ` Install-Binary -Type EXE `
-Url $installerUrl ` -Url $installerUrl `
@@ -36,13 +39,14 @@ if (-not (Test-Path -Path $GeckoDriverPath)) {
} }
Write-Host "Get the Gecko WebDriver version..." Write-Host "Get the Gecko WebDriver version..."
$GeckoDriverJson = Invoke-RestMethod "https://api.github.com/repos/mozilla/geckodriver/releases/latest" $GeckoDriverVersion = (Get-GithubReleasesByVersion -Repo "mozilla/geckodriver" -Version "latest").version
$GeckoDriverWindowsAsset = $GeckoDriverJson.assets | Where-Object { $_.name -Match "win64" } | Select-Object -First 1 $GeckoDriverVersion | Out-File -FilePath "$GeckoDriverPath\versioninfo.txt" -Force
$GeckoDriverVersion = $GeckoDriverJson.tag_name
$GeckoDriverVersion.Substring(1) | Out-File -FilePath "$GeckoDriverPath\versioninfo.txt" -Force;
Write-Host "Download Gecko WebDriver WebDriver..." Write-Host "Download Gecko WebDriver WebDriver..."
$GeckoDriverDownloadUrl = $GeckoDriverWindowsAsset.browser_download_url $GeckoDriverDownloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "mozilla/geckodriver" `
-Version $GeckoDriverVersion `
-UrlMatchPattern "geckodriver-*-win64.zip"
$GeckoDriverArchPath = Invoke-DownloadWithRetry $GeckoDriverDownloadUrl $GeckoDriverArchPath = Invoke-DownloadWithRetry $GeckoDriverDownloadUrl
Write-Host "Expand Gecko WebDriver archive..." Write-Host "Expand Gecko WebDriver archive..."

View File

@@ -11,7 +11,7 @@ $downloadUrl = Resolve-GithubReleaseAssetUrl `
-Version "latest" ` -Version "latest" `
-UrlMatchPattern "Git-*-64-bit.exe" -UrlMatchPattern "Git-*-64-bit.exe"
$externalHash = Get-GithubReleaseAssetHash ` $externalHash = Get-ChecksumFromGithubRelease `
-Repo "git-for-windows/git" ` -Repo "git-for-windows/git" `
-Version "latest" ` -Version "latest" `
-FileName (Split-Path $downloadUrl -Leaf) ` -FileName (Split-Path $downloadUrl -Leaf) `
@@ -37,7 +37,7 @@ Update-Environment
git config --system --add safe.directory "*" git config --system --add safe.directory "*"
# Disable GCM machine-wide # Disable GCM machine-wide
[Environment]::SetEnvironmentVariable("GCM_INTERACTIVE", "Never", [System.EnvironmentVariableTarget]::Machine) [Environment]::SetEnvironmentVariable("GCM_INTERACTIVE", "Never", "Machine")
# Add to PATH # Add to PATH
Add-MachinePathItem "C:\Program Files\Git\bin" Add-MachinePathItem "C:\Program Files\Git\bin"

View File

@@ -6,16 +6,22 @@
Write-Host "Get the latest gh version..." Write-Host "Get the latest gh version..."
$repoUrl = "https://api.github.com/repos/cli/cli/releases/latest" $downloadUrl = Resolve-GithubReleaseAssetUrl `
$assets = (Invoke-RestMethod -Uri $repoUrl).assets -Repo "cli/cli" `
$downloadUrl = ($assets.browser_download_url -match "windows_amd64.msi") | Select-Object -First 1 -Version "latest" `
-UrlMatchPattern "gh_*_windows_amd64.msi"
$hashUrl = ($assets.browser_download_url -match "checksums.txt") | Select-Object -First 1 $checksumsUrl = Resolve-GithubReleaseAssetUrl `
$externalHash = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*windows_amd64.msi*" }).Split(' ')[0] -Repo "cli/cli" `
-Version "latest" `
-UrlMatchPattern "gh_*_checksums.txt"
$externalHash = Get-ChecksumFromUrl -Type "SHA256" `
-Url $checksumsUrl `
-FileName (Split-Path $downloadUrl -Leaf)
Install-Binary ` Install-Binary `
-Url $downloadUrl ` -Url $downloadUrl `
-ExpectedSHA256Sum $externalHash -ExpectedSHA256Sum $externalHash
Add-MachinePathItem "C:\Program Files (x86)\GitHub CLI" Add-MachinePathItem "C:\Program Files (x86)\GitHub CLI"

View File

@@ -22,9 +22,9 @@ New-Item -Path "$ghcupPrefix\ghcup" -ItemType 'directory' -ErrorAction SilentlyC
New-Item -Path "$ghcupPrefix\ghcup\bin" -ItemType 'directory' -ErrorAction SilentlyContinue | Out-Null New-Item -Path "$ghcupPrefix\ghcup\bin" -ItemType 'directory' -ErrorAction SilentlyContinue | Out-Null
Invoke-DownloadWithRetry -Url $ghcupDownloadURL -Path "$ghcupPrefix\ghcup\bin\ghcup.exe" Invoke-DownloadWithRetry -Url $ghcupDownloadURL -Path "$ghcupPrefix\ghcup\bin\ghcup.exe"
[System.Environment]::SetEnvironmentVariable("GHCUP_INSTALL_BASE_PREFIX", $ghcupPrefix, "Machine") [Environment]::SetEnvironmentVariable("GHCUP_INSTALL_BASE_PREFIX", $ghcupPrefix, "Machine")
[System.Environment]::SetEnvironmentVariable("GHCUP_MSYS2", $msysPath, "Machine") [Environment]::SetEnvironmentVariable("GHCUP_MSYS2", $msysPath, "Machine")
[System.Environment]::SetEnvironmentVariable("CABAL_DIR", $cabalDir, "Machine") [Environment]::SetEnvironmentVariable("CABAL_DIR", $cabalDir, "Machine")
Add-MachinePathItem "$ghcupPrefix\ghcup\bin" Add-MachinePathItem "$ghcupPrefix\ghcup\bin"
Add-MachinePathItem "$cabalDir\bin" Add-MachinePathItem "$cabalDir\bin"
Update-Environment Update-Environment
@@ -32,12 +32,11 @@ Update-Environment
# Get 3 latest versions of GHC # Get 3 latest versions of GHC
$Versions = ghcup list -t ghc -r | Where-Object {$_ -notlike "prerelease"} $Versions = ghcup list -t ghc -r | Where-Object {$_ -notlike "prerelease"}
$VersionsOutput = [Version[]]($Versions | ForEach-Object{ $_.Split(' ')[1]; }) $VersionsOutput = [Version[]]($Versions | ForEach-Object{ $_.Split(' ')[1]; })
$LatestMajorMinor = $VersionsOutput | Group-Object { $_.ToString(2) } | Sort-Object { [Version]$_.Name } | Select-Object -last 3 $LatestMajorMinor = $VersionsOutput | Group-Object { $_.ToString(2) } | Sort-Object { [Version] $_.Name } | Select-Object -last 3
$VersionsList = $LatestMajorMinor | ForEach-Object { $_.Group | Select-Object -Last 1 } | Sort-Object $VersionsList = $LatestMajorMinor | ForEach-Object { $_.Group | Select-Object -Last 1 } | Sort-Object
# The latest version will be installed as a default # The latest version will be installed as a default
ForEach ($version in $VersionsList) foreach ($version in $VersionsList) {
{
Write-Host "Installing ghc $version..." Write-Host "Installing ghc $version..."
ghcup install ghc $version ghcup install ghc $version
ghcup set ghc $version ghcup set ghc $version

View File

@@ -15,7 +15,7 @@ $driverZipFile = Invoke-DownloadWithRetry $ieDriverUrl
$ieDriverPath = "C:\SeleniumWebDrivers\IEDriver" $ieDriverPath = "C:\SeleniumWebDrivers\IEDriver"
if (-not (Test-Path -Path $ieDriverPath)) { if (-not (Test-Path -Path $ieDriverPath)) {
$null = New-Item -Path $ieDriverPath -ItemType Directory -Force New-Item -Path $ieDriverPath -ItemType Directory -Force | Out-Null
} }
Expand-7ZipArchive -Path $driverZipFile -DestinationPath $ieDriverPath Expand-7ZipArchive -Path $driverZipFile -DestinationPath $ieDriverPath

View File

@@ -39,7 +39,7 @@ function Set-JavaPath {
$newPath = $javaPath + '\bin;' + $newPath $newPath = $javaPath + '\bin;' + $newPath
Write-Host "Add $javaPath\bin to PATH" Write-Host "Add $javaPath\bin to PATH"
[System.Environment]::SetEnvironmentVariable("PATH", $newPath, "Machine") [Environment]::SetEnvironmentVariable("PATH", $newPath, "Machine")
Write-Host "Set JAVA_HOME environmental variable as $javaPath" Write-Host "Set JAVA_HOME environmental variable as $javaPath"
[Environment]::SetEnvironmentVariable("JAVA_HOME", $javaPath, "Machine") [Environment]::SetEnvironmentVariable("JAVA_HOME", $javaPath, "Machine")
@@ -118,13 +118,13 @@ Install-ChocoPackage maven -ArgumentList "--version=$versionToInstall"
Install-ChocoPackage gradle Install-ChocoPackage gradle
# Add maven env variables to Machine # Add maven env variables to Machine
[string] $m2 = ([Environment]::GetEnvironmentVariable("PATH", "Machine")).Split(";") -match "maven" [string] $m2Path = ([Environment]::GetEnvironmentVariable("PATH", "Machine")).Split(";") -match "maven"
$m2_repo = 'C:\ProgramData\m2' $m2RepoPath = 'C:\ProgramData\m2'
New-Item -Path $m2_repo -ItemType Directory -Force | Out-Null New-Item -Path $m2RepoPath -ItemType Directory -Force | Out-Null
[Environment]::SetEnvironmentVariable("M2", $m2, "Machine") [Environment]::SetEnvironmentVariable("M2", $m2Path, "Machine")
[Environment]::SetEnvironmentVariable("M2_REPO", $m2_repo, "Machine") [Environment]::SetEnvironmentVariable("M2_REPO", $m2RepoPath, "Machine")
[Environment]::SetEnvironmentVariable("MAVEN_OPTS", "-Xms256m", "Machine") [Environment]::SetEnvironmentVariable("MAVEN_OPTS", "-Xms256m", "Machine")
# Download cobertura jars # Download cobertura jars

View File

@@ -14,7 +14,7 @@ $kotlinDownloadUrl = Resolve-GithubReleaseAssetUrl `
$kotlinArchivePath = Invoke-DownloadWithRetry $kotlinDownloadUrl $kotlinArchivePath = Invoke-DownloadWithRetry $kotlinDownloadUrl
#region Supply chain security #region Supply chain security
$externalHash = Get-GithubReleaseAssetHash ` $externalHash = Get-ChecksumFromGithubRelease `
-Repo "JetBrains/kotlin" ` -Repo "JetBrains/kotlin" `
-Version "$kotlinVersion" ` -Version "$kotlinVersion" `
-FileName (Split-Path $kotlinDownloadUrl -Leaf) ` -FileName (Split-Path $kotlinDownloadUrl -Leaf) `

View File

@@ -6,20 +6,24 @@
Write-Host "Install Kind" Write-Host "Install Kind"
# Choco installation can't be used because it depends on docker-desktop # Choco installation can't be used because it depends on docker-desktop
$repoUrl = 'https://api.github.com/repos/kubernetes-sigs/kind/releases/latest'
$assets = (Invoke-RestMethod -Uri $repoUrl).assets $targetDir = "C:\ProgramData\kind"
[System.String] $kindDownloadLink = $assets.browser_download_url -match "kind-windows-amd64$" New-Item -Path $targetDir -ItemType Directory -Force | Out-Null
$destFilePath = "C:\ProgramData\kind"
$null = New-Item -Path $destFilePath -ItemType Directory -Force $downloadUrl = Resolve-GithubReleaseAssetUrl `
$packagePath = Invoke-DownloadWithRetry -Url $kindDownloadLink -Path "$destFilePath\kind.exe" -Repo "kubernetes-sigs/kind" `
-Version "latest" `
-UrlMatchPattern "kind-windows-amd64"
$packagePath = Invoke-DownloadWithRetry -Url $downloadUrl -Path "$targetDir\kind.exe"
#region Supply chain security - Kind #region Supply chain security - Kind
$hashUrl = ($assets.browser_download_url -match "kind-windows-amd64.sha256sum") | Select-Object -First 1 $externalHash = Get-ChecksumFromUrl -Type "SHA256" `
$externalHash = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*kind-windows-amd64*" }).Split(' ')[0] -Url "$downloadUrl.sha256sum" `
-FileName (Split-Path $downloadUrl -Leaf)
Test-FileChecksum $packagePath -ExpectedSHA256Sum $externalHash Test-FileChecksum $packagePath -ExpectedSHA256Sum $externalHash
#endregion #endregion
Add-MachinePathItem $destFilePath Add-MachinePathItem $targetDir
Write-Host "Install Kubectl" Write-Host "Install Kubectl"
Install-ChocoPackage kubernetes-cli Install-ChocoPackage kubernetes-cli

View File

@@ -4,67 +4,67 @@
################################################################################ ################################################################################
if (Test-IsWin19) { if (Test-IsWin19) {
# If Windows 2019, install version 8.1.0 form sourceforge # If Windows 2019, install version 8.1.0 form sourceforge
$baseUrl = "https://sourceforge.net/projects/mingw-w64/files" $baseUrl = "https://sourceforge.net/projects/mingw-w64/files"
$("mingw32", "mingw64") | ForEach-Object { $("mingw32", "mingw64") | ForEach-Object {
if ($_ -eq "mingw32") { if ($_ -eq "mingw32") {
$url = "$baseUrl/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/8.1.0/threads-posix/dwarf/i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z/download" $url = "$baseUrl/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/8.1.0/threads-posix/dwarf/i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z/download"
$sha256sum = 'adb84b70094c0225dd30187ff995e311d19424b1eb8f60934c60e4903297f946' $sha256sum = 'adb84b70094c0225dd30187ff995e311d19424b1eb8f60934c60e4903297f946'
} elseif ($_ -eq "mingw64") { } elseif ($_ -eq "mingw64") {
$url = "$baseUrl/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/8.1.0/threads-posix/seh/x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z/download" $url = "$baseUrl/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/8.1.0/threads-posix/seh/x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z/download"
$sha256sum = '853970527b5de4a55ec8ca4d3fd732c00ae1c69974cc930c82604396d43e79f8' $sha256sum = '853970527b5de4a55ec8ca4d3fd732c00ae1c69974cc930c82604396d43e79f8'
} else { } else {
throw "Unknown architecture $_" throw "Unknown architecture $_"
}
$packagePath = Invoke-DownloadWithRetry $url
Test-FileChecksum -Path $packagePath -ExpectedSHA256Sum $sha256sum
Expand-7ZipArchive -Path $packagePath -DestinationPath "C:\"
# Make a copy of mingw-make.exe to make.exe, which is a more discoverable name
# and so the same command line can be used on Windows as on macOS and Linux
$path = "C:\$_\bin\mingw32-make.exe" | Get-Item
Copy-Item -Path $path -Destination (Join-Path $path.Directory 'make.exe')
}
Add-MachinePathItem "C:\mingw64\bin"
}
if (Test-IsWin22) {
# If Windows 2022, install version specified in the toolset
$version = (Get-ToolsetContent).mingw.version
$runtime = (Get-ToolsetContent).mingw.runtime
$("mingw32", "mingw64") | ForEach-Object {
if ($_ -eq "mingw32") {
$arch = "i686"
$threads = "posix"
$exceptions = "dwarf"
} elseif ($_ -eq "mingw64") {
$arch = "x86_64"
$threads = "posix"
$exceptions = "seh"
} else {
throw "Unknown architecture $_"
}
$url = Resolve-GithubReleaseAssetUrl `
-Repo "niXman/mingw-builds-binaries" `
-Version "$version" `
-Asset "$arch-*-release-$threads-$exceptions-$runtime-*.7z"
$packagePath = Invoke-DownloadWithRetry $url
Expand-7ZipArchive -Path $packagePath -DestinationPath "C:\"
# Make a copy of mingw-make.exe to make.exe, which is a more discoverable name
# and so the same command line can be used on Windows as on macOS and Linux
$path = "C:\$_\bin\mingw32-make.exe" | Get-Item
Copy-Item -Path $path -Destination (Join-Path $path.Directory 'make.exe')
} }
$packagePath = Invoke-DownloadWithRetry $url Add-MachinePathItem "C:\mingw64\bin"
$hash = Get-FileHash -Path $packagePath -Algorithm SHA256
if ($hash.Hash -ne $sha256sum) {
throw "Checksum verification failed for $packagePath"
}
Expand-7ZipArchive -Path $packagePath -DestinationPath "C:\"
# Make a copy of mingw-make.exe to make.exe, which is a more discoverable name
# and so the same command line can be used on Windows as on macOS and Linux
$path = "C:\$_\bin\mingw32-make.exe" | Get-Item
Copy-Item -Path $path -Destination (Join-Path $path.Directory 'make.exe')
}
Add-MachinePathItem "C:\mingw64\bin"
} else {
$version = (Get-ToolsetContent).mingw.version
$runtime = (Get-ToolsetContent).mingw.runtime
$("mingw32", "mingw64") | ForEach-Object {
if ($_ -eq "mingw32") {
$arch = "i686"
$threads = "posix"
$exceptions = "dwarf"
} elseif ($_ -eq "mingw64") {
$arch = "x86_64"
$threads = "posix"
$exceptions = "seh"
} else {
throw "Unknown architecture $_"
}
$url = Resolve-GithubReleaseAssetUrl `
-Repo "niXman/mingw-builds-binaries" `
-Version "$version" `
-Asset "$arch-*-release-$threads-$exceptions-$runtime-*.7z"
$packagePath = Invoke-DownloadWithRetry $url
Expand-7ZipArchive -Path $packagePath -DestinationPath "C:\"
# Make a copy of mingw-make.exe to make.exe, which is a more discoverable name
# and so the same command line can be used on Windows as on macOS and Linux
$path = "C:\$_\bin\mingw32-make.exe" | Get-Item
Copy-Item -Path $path -Destination (Join-Path $path.Directory 'make.exe')
}
Add-MachinePathItem "C:\mingw64\bin"
} }
Invoke-PesterTests -TestFile "Tools" -TestName "Mingw64" Invoke-PesterTests -TestFile "Tools" -TestName "Mingw64"

View File

@@ -27,6 +27,6 @@ Install-Binary `
-InstallArgs @("/S", "/AddToPath=0", "/RegisterPython=0", "/D=$CondaDestination") ` -InstallArgs @("/S", "/AddToPath=0", "/RegisterPython=0", "/D=$CondaDestination") `
-ExpectedSHA256Sum $distributorFileHash -ExpectedSHA256Sum $distributorFileHash
[System.Environment]::SetEnvironmentVariable("CONDA", $CondaDestination, "Machine") [Environment]::SetEnvironmentVariable("CONDA", $CondaDestination, "Machine")
Invoke-PesterTests -TestFile "Miniconda" Invoke-PesterTests -TestFile "Miniconda"

View File

@@ -6,24 +6,24 @@
# Install mongodb package # Install mongodb package
$toolsetVersion = (Get-ToolsetContent).mongodb.version $toolsetVersion = (Get-ToolsetContent).mongodb.version
$getMongoReleases = Invoke-WebRequest -Uri "mongodb.com/docs/manual/release-notes/$toolsetVersion/" -UseBasicParsing $getMongoReleases = Invoke-WebRequest -Uri "mongodb.com/docs/manual/release-notes/$toolsetVersion/" -UseBasicParsing
$TargetReleases = $getMongoReleases.Links.href | Where-Object {$_ -like "#$toolsetVersion*---*"} $TargetReleases = $getMongoReleases.Links.href | Where-Object {$_ -like "#$toolsetVersion*---*"}
$MinorVersions = @() $MinorVersions = @()
foreach ($release in $TargetReleases) { foreach ($release in $TargetReleases) {
if ($release -notlike "*upcoming*") { if ($release -notlike "*upcoming*") {
$pattern = '\d+\.\d+\.\d+' $pattern = '\d+\.\d+\.\d+'
$version = $release | Select-String -Pattern $pattern -AllMatches | ForEach-Object { $_.Matches } | ForEach-Object { $_.Value } $version = $release | Select-String -Pattern $pattern -AllMatches | ForEach-Object { $_.Matches } | ForEach-Object { $_.Value }
$MinorVersions += $version $MinorVersions += $version
} }
} }
$LatestVersion = $MinorVersions[0] $LatestVersion = $MinorVersions[0]
Install-Binary ` Install-Binary `
-Url "https://fastdl.mongodb.org/windows/mongodb-windows-x86_64-$LatestVersion-signed.msi" ` -Url "https://fastdl.mongodb.org/windows/mongodb-windows-x86_64-$LatestVersion-signed.msi" `
-ExtraInstallArgs @('TARGETDIR=C:\PROGRA~1\MongoDB ADDLOCAL=ALL') ` -ExtraInstallArgs @('TARGETDIR=C:\PROGRA~1\MongoDB ADDLOCAL=ALL') `
-ExpectedSignature (Get-ToolsetContent).mongodb.signature -ExpectedSignature (Get-ToolsetContent).mongodb.signature
# Add mongodb to the PATH # Add mongodb to the PATH
$mongoPath = (Get-CimInstance Win32_Service -Filter "Name LIKE 'mongodb'").PathName $mongoPath = (Get-CimInstance Win32_Service -Filter "Name LIKE 'mongodb'").PathName

View File

@@ -11,25 +11,27 @@ $dash = "-" * 40
$origPath = $env:PATH $origPath = $env:PATH
function Install-Msys2 { function Install-Msys2 {
$msys2_release = "https://api.github.com/repos/msys2/msys2-installer/releases/latest" # We can't use Resolve-GithubReleaseAssetUrl function here
$assets = (Invoke-RestMethod -Uri $msys2_release).assets # because msys2-installer releases don't have a consistent versioning scheme
$msys2Uri = ($assets | Where-Object { $_.name -match "^msys2-x86_64" -and $_.name.EndsWith(".exe") }).browser_download_url
$assets = (Invoke-RestMethod -Uri "https://api.github.com/repos/msys2/msys2-installer/releases/latest").assets
$downloadUri = ($assets | Where-Object { $_.name -match "^msys2-x86_64" -and $_.name.EndsWith(".exe") }).browser_download_url
$installerName = Split-Path $downloadUri -Leaf
# Download the latest msys2 x86_64, filename includes release date # Download the latest msys2 x86_64, filename includes release date
Write-Host "Starting msys2 download using $($msys2Uri.split('/')[-1])" Write-Host "Download msys2 installer $installerName"
$msys2File = Invoke-DownloadWithRetry $msys2Uri $installerPath = Invoke-DownloadWithRetry $downloadUri
Write-Host "Finished download"
#region Supply chain security - Kind #region Supply chain security - MSYS2
$hashUrl = ($assets.browser_download_url -match "msys2-checksums.txt") | Select-Object -First 1 $externalHash = Get-ChecksumFromUrl -Type "SHA256" `
$externalHash = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*msys2-x86_64*" }).Split(' ')[0] -Url ($downloadUri -replace $installerName, "msys2-checksums.txt") `
Test-FileChecksum $msys2File -ExpectedSHA256Sum $externalHash -FileName $installerName
Test-FileChecksum $installerPath -ExpectedSHA256Sum $externalHash
#endregion #endregion
# extract tar.xz to C:\
Write-Host "Starting msys2 installation" Write-Host "Starting msys2 installation"
& $msys2File in --confirm-command --accept-messages --root C:/msys64 & $installerPath in --confirm-command --accept-messages --root C:/msys64
Remove-Item $msys2File Remove-Item $installerPath
} }
function Install-Msys2Packages($Packages) { function Install-Msys2Packages($Packages) {

View File

@@ -10,12 +10,14 @@ Install-Binary `
-ExpectedSignature '3BDA323E552DB1FDE5F4FBEE75D6D5B2B187EEDC' -ExpectedSignature '3BDA323E552DB1FDE5F4FBEE75D6D5B2B187EEDC'
# Downloading mysql # Downloading mysql
[version]$MysqlVersion = (Get-ToolsetContent).mysql.version [version] $MysqlVersion = (Get-ToolsetContent).mysql.version
$MysqlVersionMajorMinor = $MysqlVersion.ToString(2) $MysqlVersionMajorMinor = $MysqlVersion.ToString(2)
if ($MysqlVersion.Build -lt 0) { if ($MysqlVersion.Build -lt 0) {
$MysqlVersion = (Invoke-RestMethod -Uri "https://dev.mysql.com/downloads/mysql/${MysqlVersionMajorMinor}.html" -Headers @{ 'User-Agent' = 'curl/8.4.0' } | $downloadsPageUrl = "https://dev.mysql.com/downloads/mysql/${MysqlVersionMajorMinor}.html"
Select-String -Pattern "${MysqlVersionMajorMinor}\.\d+").Matches.Value $MysqlVersion = Invoke-RestMethod -Uri $downloadsPageUrl -Headers @{ 'User-Agent' = 'curl/8.4.0' } `
| Select-String -Pattern "${MysqlVersionMajorMinor}\.\d+" `
| ForEach-Object { $_.Matches.Value }
} }
$MysqlVersionFull = $MysqlVersion.ToString() $MysqlVersionFull = $MysqlVersion.ToString()

View File

@@ -10,8 +10,8 @@ $env:PIPX_HOME = "${env:ProgramFiles(x86)}\pipx"
pip install pipx pip install pipx
Add-MachinePathItem "${env:PIPX_BIN_DIR}" Add-MachinePathItem "${env:PIPX_BIN_DIR}"
[System.Environment]::SetEnvironmentVariable("PIPX_BIN_DIR", $env:PIPX_BIN_DIR, "Machine") [Environment]::SetEnvironmentVariable("PIPX_BIN_DIR", $env:PIPX_BIN_DIR, "Machine")
[System.Environment]::SetEnvironmentVariable("PIPX_HOME", $env:PIPX_HOME, "Machine") [Environment]::SetEnvironmentVariable("PIPX_HOME", $env:PIPX_HOME, "Machine")
Invoke-PesterTests -TestFile "Tools" -TestName "Pipx" Invoke-PesterTests -TestFile "Tools" -TestName "Pipx"

View File

@@ -3,20 +3,20 @@ $pgUser = "postgres"
$pgPwd = "root" $pgPwd = "root"
# Prepare environment variable for validation # Prepare environment variable for validation
[System.Environment]::SetEnvironmentVariable("PGUSER", $pgUser, "Machine") [Environment]::SetEnvironmentVariable("PGUSER", $pgUser, "Machine")
[System.Environment]::SetEnvironmentVariable("PGPASSWORD", $pgPwd, "Machine") [Environment]::SetEnvironmentVariable("PGPASSWORD", $pgPwd, "Machine")
# Define latest available version to install based on version specified in the toolset # Define latest available version to install based on version specified in the toolset
$toolsetVersion = (Get-ToolsetContent).postgresql.version $toolsetVersion = (Get-ToolsetContent).postgresql.version
$getPostgreReleases = Invoke-WebRequest -Uri "https://git.postgresql.org/gitweb/?p=postgresql.git;a=tags" -UseBasicParsing $getPostgreReleases = Invoke-WebRequest -Uri "https://git.postgresql.org/gitweb/?p=postgresql.git;a=tags" -UseBasicParsing
# Getting all links matched to the pattern (e.g.a=log;h=refs/tags/REL_14) # Getting all links matched to the pattern (e.g.a=log;h=refs/tags/REL_14)
$TargetReleases = $getPostgreReleases.Links.href | Where-Object { $_ -match "a=log;h=refs/tags/REL_$toolsetVersion" } $TargetReleases = $getPostgreReleases.Links.href | Where-Object { $_ -match "a=log;h=refs/tags/REL_$toolsetVersion" }
[Int32]$OutNumber = $null [Int32] $OutNumber = $null
$MinorVersions = @() $MinorVersions = @()
foreach ($release in $TargetReleases) { foreach ($release in $TargetReleases) {
$version = $release.split('/')[-1] $version = $release.split('/')[-1]
# Checking if the latest symbol of the release version is actually a number. If yes, add to $MinorVersions array # Checking if the latest symbol of the release version is actually a number. If yes, add to $MinorVersions array
if ([Int32]::TryParse($($version.Split('_')[-1]), [ref]$OutNumber)) { if ([Int32]::TryParse($($version.Split('_')[-1]), [ref] $OutNumber)) {
$MinorVersions += $OutNumber $MinorVersions += $OutNumber
} }
} }
@@ -72,9 +72,9 @@ if ($exitCode -ne 0) {
} }
# Added PostgreSQL environment variable # Added PostgreSQL environment variable
[System.Environment]::SetEnvironmentVariable("PGBIN", $pgBin, "Machine") [Environment]::SetEnvironmentVariable("PGBIN", $pgBin, "Machine")
[System.Environment]::SetEnvironmentVariable("PGROOT", $pgRoot, "Machine") [Environment]::SetEnvironmentVariable("PGROOT", $pgRoot, "Machine")
[System.Environment]::SetEnvironmentVariable("PGDATA", $pgData, "Machine") [Environment]::SetEnvironmentVariable("PGDATA", $pgData, "Machine")
# Stop and disable PostgreSQL service # Stop and disable PostgreSQL service
$pgService = Get-Service -Name postgresql* $pgService = Get-Service -Name postgresql*

View File

@@ -9,22 +9,18 @@
# Install PowerShell modules # Install PowerShell modules
$modules = (Get-ToolsetContent).powershellModules $modules = (Get-ToolsetContent).powershellModules
foreach($module in $modules) foreach ($module in $modules) {
{
$moduleName = $module.name $moduleName = $module.name
Write-Host "Installing ${moduleName} module" Write-Host "Installing ${moduleName} module"
if ($module.versions) if ($module.versions) {
{ foreach ($version in $module.versions) {
foreach ($version in $module.versions)
{
Write-Host " - $version" Write-Host " - $version"
Install-Module -Name $moduleName -RequiredVersion $version -Scope AllUsers -SkipPublisherCheck -Force Install-Module -Name $moduleName -RequiredVersion $version -Scope AllUsers -SkipPublisherCheck -Force
} }
continue } else {
Install-Module -Name $moduleName -Scope AllUsers -SkipPublisherCheck -Force
} }
Install-Module -Name $moduleName -Scope AllUsers -SkipPublisherCheck -Force
} }
Import-Module Pester Import-Module Pester

View File

@@ -16,10 +16,11 @@ try {
$release = $metadata.LTSReleaseTag[0] -replace '^v' $release = $metadata.LTSReleaseTag[0] -replace '^v'
$downloadUrl = "https://github.com/PowerShell/PowerShell/releases/download/v${release}/PowerShell-${release}-win-x64.msi" $downloadUrl = "https://github.com/PowerShell/PowerShell/releases/download/v${release}/PowerShell-${release}-win-x64.msi"
$hashUrl = "https://github.com/PowerShell/PowerShell/releases/download/v${release}/hashes.sha256" $installerName = Split-Path $downloadUrl -Leaf
$expectedSHA256Sum = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*PowerShell-${Release}-win-x64.msi*" }).Split(' ')[0] $externalHash = Get-ChecksumFromUrl -Type "SHA256" `
-Url ($downloadUrl -replace $installerName, "hashes.sha256") `
Install-Binary -Url $downloadUrl -ExpectedSHA256Sum $expectedSHA256Sum -FileName $installerName
Install-Binary -Url $downloadUrl -ExpectedSHA256Sum $externalHash
} finally { } finally {
# Restore original value # Restore original value
[Net.ServicePointManager]::SecurityProtocol = $originalValue [Net.ServicePointManager]::SecurityProtocol = $originalValue
@@ -30,6 +31,6 @@ try {
# While the update check happens during the first session in a given 24-hour period, for performance reasons, # While the update check happens during the first session in a given 24-hour period, for performance reasons,
# the notification will only be shown on the start of subsequent sessions. # the notification will only be shown on the start of subsequent sessions.
# Also for performance reasons, the check will not start until at least 3 seconds after the session begins. # Also for performance reasons, the check will not start until at least 3 seconds after the session begins.
[System.Environment]::SetEnvironmentVariable("POWERSHELL_UPDATECHECK", "Off", [System.EnvironmentVariableTarget]::Machine) [Environment]::SetEnvironmentVariable("POWERSHELL_UPDATECHECK", "Off", "Machine")
Invoke-PesterTests -TestFile "Tools" -TestName "PowerShell Core" Invoke-PesterTests -TestFile "Tools" -TestName "PowerShell Core"

View File

@@ -33,7 +33,7 @@ function Get-CertificatesWithoutPropId {
$certs | ForEach-Object -Process { $certs | ForEach-Object -Process {
$certHandle = $_.Handle $certHandle = $_.Handle
$isPropertySet = [PKI.Cert]::CertGetCertificateContextProperty( $isPropertySet = [PKI.Cert]::CertGetCertificateContextProperty(
$certHandle, $CERT_NOT_BEFORE_FILETIME_PROP_ID, $null, [ref]$null $certHandle, $CERT_NOT_BEFORE_FILETIME_PROP_ID, $null, [ref] $null
) )
if (-not $isPropertySet) { if (-not $isPropertySet) {
Write-Host "Subject: $($_.Subject)" Write-Host "Subject: $($_.Subject)"
@@ -43,31 +43,17 @@ function Get-CertificatesWithoutPropId {
$certsWithoutPropId $certsWithoutPropId
} }
function Invoke-WithRetry {
<#
.SYNOPSIS
Runs $command block until $BreakCondition or $RetryCount is reached.
#>
param([ScriptBlock]$Command, [ScriptBlock] $BreakCondition, [int] $RetryCount=5, [int] $Sleep=10)
$c = 0
while($c -lt $RetryCount){
$result = & $Command
if(& $BreakCondition){
break
}
Start-Sleep $Sleep
$c++
}
$result
}
function Import-SSTFromWU { function Import-SSTFromWU {
# Serialized Certificate Store File # Serialized Certificate Store File
$sstFile = "$env:TEMP\roots.sst" $sstFile = "$env:TEMP\roots.sst"
# Generate SST from Windows Update # Generate SST from Windows Update
$result = Invoke-WithRetry { certutil.exe -generateSSTFromWU $sstFile } {$LASTEXITCODE -eq 0} $result = Invoke-ScriptBlockWithRetry -RetryCount 5 -RetryIntervalSeconds 10 -Command {
$r = certutil.exe -generateSSTFromWU $sstFile
if ($LASTEXITCODE -ne 0) {
throw "failed to generate $sstFile sst file`n$o"
}
return $r
}
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
Write-Host "[Error]: failed to generate $sstFile sst file`n$result" Write-Host "[Error]: failed to generate $sstFile sst file`n$result"
exit $LASTEXITCODE exit $LASTEXITCODE
@@ -88,7 +74,9 @@ function Import-SSTFromWU {
} }
function Clear-CertificatesPropId { function Clear-CertificatesPropId {
param([hashtable]$CertsWithoutPropId) param(
[hashtable] $CertsWithoutPropId
)
# List installed certificates # List installed certificates
$certs = Get-ChildItem -Path Cert:\LocalMachine\Root $certs = Get-ChildItem -Path Cert:\LocalMachine\Root

View File

@@ -3,39 +3,12 @@
## Desc: Install Ruby using the RubyInstaller2 package and set the default Ruby version ## Desc: Install Ruby using the RubyInstaller2 package and set the default Ruby version
################################################################################ ################################################################################
function Get-RubyVersions {
param (
[System.String] $Arch = "x64",
[System.String] $Extension = "7z",
[System.String] $ReleasesAmount = "50"
)
$uri = "https://api.github.com/repos/oneclick/rubyinstaller2/releases?per_page=$ReleasesAmount"
try {
$versionLists = @{}
$assets = (Invoke-RestMethod -Uri $uri).Where{ -not $_.prerelease }.assets
$7zArchives = $assets.Where{ $_.name.EndsWith("$Arch.$Extension") }
$majorMinorGroups = $7zArchives | Group-Object { $_.name.Replace("rubyinstaller-", "").Substring(0, 3) }
foreach ($majorMinorGroup in $majorMinorGroups) {
$group = $majorMinorGroup.Group
$sortVersions = $group | Sort-Object { [Version]$_.name.Replace("rubyinstaller-", "").Replace("-$Arch.$Extension", "").Replace("-", ".") }
$latestVersion = $sortVersions | Select-Object -Last 1
$versionLists[$majorMinorGroup.Name] = $latestVersion.browser_download_url
}
return $versionLists
} catch {
Write-Host "Unable to send request to the '$uri'. Error: '$_'"
exit 1
}
}
# Most of this logic is from # Most of this logic is from
# https://github.com/ruby/setup-ruby/blob/master/windows.js # https://github.com/ruby/setup-ruby/blob/master/windows.js
function Install-Ruby { function Install-Ruby {
param( param(
[String]$PackagePath, [String] $PackagePath,
[String]$Architecture = "x64" [String] $Architecture = "x64"
) )
# Create Ruby toolcache folder # Create Ruby toolcache folder
@@ -44,47 +17,46 @@ function Install-Ruby {
Write-Host "Creating Ruby toolcache folder" Write-Host "Creating Ruby toolcache folder"
New-Item -ItemType Directory -Path $rubyToolcachePath | Out-Null New-Item -ItemType Directory -Path $rubyToolcachePath | Out-Null
} }
# Expand archive with binaries
$packageName = [IO.Path]::GetFileNameWithoutExtension((Split-Path -Path $PackagePath -Leaf)) $packageName = [IO.Path]::GetFileNameWithoutExtension((Split-Path -Path $PackagePath -Leaf))
Write-Host "Expanding Ruby archive $packageName"
$tempFolder = Join-Path -Path $rubyToolcachePath -ChildPath $packageName $tempFolder = Join-Path -Path $rubyToolcachePath -ChildPath $packageName
Expand-7ZipArchive -Path $PackagePath -DestinationPath $rubyToolcachePath Expand-7ZipArchive -Path $PackagePath -DestinationPath $rubyToolcachePath
# Get Ruby version from binaries # Get Ruby version from binaries
$rubyVersion = & "$tempFolder\bin\ruby.exe" -e "print RUBY_VERSION" $rubyVersion = & "$tempFolder\bin\ruby.exe" -e "print RUBY_VERSION"
if (($LASTEXITCODE -ne 0) -or (-not $rubyVersion)) {
if ($rubyVersion) { throw "Unable to determine Ruby version. Exit code: $LASTEXITCODE, output: '$rubyVersion'"
Write-Host "Installing Ruby $rubyVersion"
$rubyVersionPath = Join-Path -Path $rubyToolcachePath -ChildPath $rubyVersion
$rubyArchPath = Join-Path -Path $rubyVersionPath -ChildPath $Architecture
Write-Host "Creating Ruby '${rubyVersion}' folder in '${rubyVersionPath}'"
New-Item -ItemType Directory -Path $rubyVersionPath -Force | Out-Null
Write-Host "Moving Ruby '${rubyVersion}' files to '${rubyArchPath}'"
Invoke-ScriptBlockWithRetry -Command {
Move-Item -Path $tempFolder -Destination $rubyArchPath -ErrorAction Stop | Out-Null
}
Write-Host "Removing Ruby '${rubyVersion}' documentation '${rubyArchPath}\share\doc' folder"
Remove-Item -Path "${rubyArchPath}\share\doc" -Force -Recurse -ErrorAction Ignore
Write-Host "Creating complete file"
New-Item -ItemType File -Path $rubyVersionPath -Name "$Architecture.complete" | Out-Null
} else {
Write-Host "Ruby application is not found. Failed to expand '$PackagePath' archive"
exit 1
} }
Write-Host "Ruby version is $rubyVersion"
$rubyVersionPath = Join-Path -Path $rubyToolcachePath -ChildPath $rubyVersion
$rubyArchPath = Join-Path -Path $rubyVersionPath -ChildPath $Architecture
Write-Host "Creating Ruby '${rubyVersion}' folder in '${rubyVersionPath}'"
New-Item -ItemType Directory -Path $rubyVersionPath -Force | Out-Null
Write-Host "Moving Ruby '${rubyVersion}' files to '${rubyArchPath}'"
Invoke-ScriptBlockWithRetry -Command {
Move-Item -Path $tempFolder -Destination $rubyArchPath -ErrorAction Stop | Out-Null
}
Write-Host "Removing Ruby '${rubyVersion}' documentation '${rubyArchPath}\share\doc' folder"
Remove-Item -Path "${rubyArchPath}\share\doc" -Force -Recurse -ErrorAction Ignore
Write-Host "Creating complete file for Ruby $rubyVersion $Architecture"
New-Item -ItemType File -Path $rubyVersionPath -Name "$Architecture.complete" | Out-Null
} }
function Set-DefaultRubyVersion { function Set-DefaultRubyVersion {
param( param(
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[System.Version] $Version, [version] $Version,
[System.String] $Arch = "x64" [Alias("Arch")]
[string] $Architecture = "x64"
) )
$rubyPath = Join-Path $env:AGENT_TOOLSDIRECTORY "/Ruby/${Version}*/${Arch}/bin" $rubyPath = Join-Path $env:AGENT_TOOLSDIRECTORY "/Ruby/${Version}*/${Architecture}/bin"
$rubyDir = (Get-Item -Path $rubyPath).FullName $rubyDir = (Get-Item -Path $rubyPath).FullName
Write-Host "Use Ruby ${Version} as a system Ruby" Write-Host "Use Ruby ${Version} as a system Ruby"
@@ -95,21 +67,15 @@ function Set-DefaultRubyVersion {
$rubyTools = (Get-ToolsetContent).toolcache | Where-Object { $_.name -eq "Ruby" } $rubyTools = (Get-ToolsetContent).toolcache | Where-Object { $_.name -eq "Ruby" }
$rubyToolVersions = $rubyTools.versions $rubyToolVersions = $rubyTools.versions
# Get Ruby versions from the repo
$rubyLatestMajorVersions = Get-RubyVersions
Write-Host "Starting installation Ruby..." Write-Host "Starting installation Ruby..."
foreach ($rubyVersion in $rubyToolVersions) { foreach ($rubyVersion in $rubyToolVersions) {
Write-Host "Starting Ruby $rubyVersion installation" Write-Host "Starting Ruby $rubyVersion installation"
# Get url for the latest major Ruby version $downloadUrl = Resolve-GithubReleaseAssetUrl `
$url = $rubyLatestMajorVersions[$rubyVersion] -Repo "oneclick/rubyinstaller2" `
if ($url) { -Version "$rubyVersion*" `
$tempRubyPackagePath = Invoke-DownloadWithRetry $url -UrlMatchPattern "*-x64.7z"
Install-Ruby -PackagePath $tempRubyPackagePath $packagePath = Invoke-DownloadWithRetry $downloadUrl
} else { Install-Ruby -PackagePath $packagePath
Write-Host "Url not found for the '$rubyVersion' version"
exit 1
}
} }
Set-DefaultRubyVersion -Version $rubyTools.default -Arch $rubyTools.arch Set-DefaultRubyVersion -Version $rubyTools.default -Arch $rubyTools.arch

View File

@@ -5,10 +5,11 @@
################################################################################ ################################################################################
Write-Host "Download latest Runner for GitHub Actions" Write-Host "Download latest Runner for GitHub Actions"
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/actions/runner/releases/latest" $downloadUrl = Resolve-GithubReleaseAssetUrl `
$version = $release.tag_name.Trim("v") -Repo "actions/runner" `
$downloadUrl = ($release.assets.browser_download_url -ilike "*actions-runner-win-x64-${version}.zip*") | Select-Object -First 1 -Version "latest" `
$fileName = [System.IO.Path]::GetFileName($downloadUrl) -UrlMatchPattern "actions-runner-win-x64-*[0-9.].zip"
$fileName = Split-Path $downloadUrl -Leaf
New-Item -Path "C:\ProgramData\runner" -ItemType Directory New-Item -Path "C:\ProgramData\runner" -ItemType Directory
Invoke-DownloadWithRetry -Url $downloadUrl -Path "C:\ProgramData\runner\$fileName" Invoke-DownloadWithRetry -Url $downloadUrl -Path "C:\ProgramData\runner\$fileName"

View File

@@ -14,7 +14,7 @@ $rustupPath = Invoke-DownloadWithRetry "https://static.rust-lang.org/rustup/dist
#region Supply chain security #region Supply chain security
$distributorFileHash = (Invoke-RestMethod -Uri 'https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe.sha256').Trim() $distributorFileHash = (Invoke-RestMethod -Uri 'https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe.sha256').Trim()
Test-FileChecksum (Join-Path ${env:TEMP} 'rustup-init.exe') -ExpectedSHA256Sum $distributorFileHash Test-FileChecksum $rustupPath -ExpectedSHA256Sum $distributorFileHash
#endregion #endregion
# Install Rust by running rustup-init.exe (disabling the confirmation prompt with -y) # Install Rust by running rustup-init.exe (disabling the confirmation prompt with -y)

View File

@@ -8,13 +8,13 @@ $signatureThumbrint = "9ACA9419E53D3C9E56396DD2335FF683A8B0B8F3"
# install required MSIs # install required MSIs
Install-Binary ` Install-Binary `
-Url "${baseUrl}/SQLSysClrTypes.msi" ` -Url "${baseUrl}/SQLSysClrTypes.msi" `
-ExpectedSignature $signatureThumbrint -ExpectedSignature $signatureThumbrint
Install-Binary ` Install-Binary `
-Url "${baseUrl}/SharedManagementObjects.msi" ` -Url "${baseUrl}/SharedManagementObjects.msi" `
-ExpectedSignature $signatureThumbrint -ExpectedSignature $signatureThumbrint
Install-Binary ` Install-Binary `
-Url "${baseUrl}/PowerShellTools.msi" ` -Url "${baseUrl}/PowerShellTools.msi" `
-ExpectedSignature $signatureThumbrint -ExpectedSignature $signatureThumbrint

View File

@@ -14,13 +14,13 @@ $urlBase = "https://download.microsoft.com/download/b/8/a/b8a2fb98-0ec1-41e5-be9
# Install Service Fabric Runtime for Windows # Install Service Fabric Runtime for Windows
Install-Binary ` Install-Binary `
-Url "${urlBase}/MicrosoftServiceFabric.${runtimeVersion}.exe" ` -Url "${urlBase}/MicrosoftServiceFabric.${runtimeVersion}.exe" `
-InstallArgs @("/accepteula ", "/quiet", "/force") ` -InstallArgs @("/accepteula ", "/quiet", "/force") `
-ExpectedSignature (Get-ToolsetContent).serviceFabric.runtime.signature -ExpectedSignature (Get-ToolsetContent).serviceFabric.runtime.signature
# Install Service Fabric SDK # Install Service Fabric SDK
Install-Binary ` Install-Binary `
-Url "${urlBase}/MicrosoftServiceFabricSDK.${sdkVersion}.msi" ` -Url "${urlBase}/MicrosoftServiceFabricSDK.${sdkVersion}.msi" `
-ExpectedSignature (Get-ToolsetContent).serviceFabric.sdk.signature -ExpectedSignature (Get-ToolsetContent).serviceFabric.sdk.signature
Invoke-PesterTests -TestFile "Tools" -TestName "ServiceFabricSDK" Invoke-PesterTests -TestFile "Tools" -TestName "ServiceFabricSDK"

View File

@@ -5,19 +5,23 @@
################################################################################ ################################################################################
Write-Host "Get the latest Stack version..." Write-Host "Get the latest Stack version..."
$StackReleasesJson = Invoke-RestMethod "https://api.github.com/repos/commercialhaskell/stack/releases/latest"
$Version = $StackReleasesJson.name.TrimStart("v") $version = (Get-GithubReleasesByVersion -Repo "commercialhaskell/stack" -Version "latest" -WithAssetsOnly).version
$DownloadFilePattern = "windows-x86_64.zip"
$DownloadUrl = $StackReleasesJson.assets | Where-Object { $_.name.EndsWith($DownloadFilePattern) } | Select-Object -ExpandProperty "browser_download_url" -First 1 $downloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "commercialhaskell/stack" `
-Version $version `
-UrlMatchPattern "stack-*-windows-x86_64.zip"
Write-Host "Download stack archive" Write-Host "Download stack archive"
$StackToolcachePath = Join-Path $Env:AGENT_TOOLSDIRECTORY "stack\$Version" $StackToolcachePath = Join-Path $Env:AGENT_TOOLSDIRECTORY "stack\$version"
$DestinationPath = Join-Path $StackToolcachePath "x64" $DestinationPath = Join-Path $StackToolcachePath "x64"
$StackArchivePath = Invoke-DownloadWithRetry $DownloadUrl $StackArchivePath = Invoke-DownloadWithRetry $downloadUrl
#region Supply chain security - Stack #region Supply chain security - Stack
$hashUrl = $StackReleasesJson.assets | Where-Object { $_.name.EndsWith("$DownloadFilePattern.sha256") } | Select-Object -ExpandProperty "browser_download_url" -First 1 $externalHash = Get-ChecksumFromUrl -Type "SHA256" `
$externalHash = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*$DownloadFilePattern*" }).Split(' ')[0] -Url "$downloadUrl.sha256" `
-FileName (Split-Path $downloadUrl -Leaf)
Test-FileChecksum $StackArchivePath -ExpectedSHA256Sum $externalHash Test-FileChecksum $StackArchivePath -ExpectedSHA256Sum $externalHash
#endregion #endregion

View File

@@ -51,12 +51,11 @@ foreach ($tool in $tools) {
| Where-Object { ($_.platform -eq $tool.platform) -and ($_.arch -eq $tool.arch) -and ($_.toolset -eq $tool.toolset) } ` | Where-Object { ($_.platform -eq $tool.platform) -and ($_.arch -eq $tool.arch) -and ($_.toolset -eq $tool.toolset) } `
| Select-Object -First 1 | Select-Object -First 1
Write-Host "Installing $($tool.name) $toolVersion $($tool.arch)..." if (-not $asset) {
if ($null -ne $asset) { throw "Asset for $($tool.name) $toolVersion $($tool.arch) not found in versions manifest"
Install-Asset -ReleaseAsset $asset
} else {
Write-Host "Asset was not found in versions manifest"
exit 1
} }
Write-Host "Installing $($tool.name) $toolVersion $($tool.arch)..."
Install-Asset -ReleaseAsset $asset
} }
} }

View File

@@ -8,13 +8,13 @@ $argumentList = ("/install", "/quiet", "/norestart")
$signatureThumbrint = "ABDCA79AF9DD48A0EA702AD45260B3C03093FB4B" $signatureThumbrint = "ABDCA79AF9DD48A0EA702AD45260B3C03093FB4B"
Install-Binary ` Install-Binary `
-Url "${baseUrl}/vcredist_x86.exe" ` -Url "${baseUrl}/vcredist_x86.exe" `
-InstallArgs $argumentList ` -InstallArgs $argumentList `
-ExpectedSignature $signatureThumbrint -ExpectedSignature $signatureThumbrint
Install-Binary ` Install-Binary `
-Url "${baseUrl}/vcredist_x64.exe" ` -Url "${baseUrl}/vcredist_x64.exe" `
-InstallArgs $argumentList ` -InstallArgs $argumentList `
-ExpectedSignature $signatureThumbrint -ExpectedSignature $signatureThumbrint
Invoke-PesterTests -TestFile "Tools" -TestName "VCRedist" Invoke-PesterTests -TestFile "Tools" -TestName "VCRedist"

View File

@@ -3,16 +3,16 @@
## Desc: Install Visual Studio ## Desc: Install Visual Studio
################################################################################ ################################################################################
$toolset = Get-ToolsetContent $vsToolset = (Get-ToolsetContent).visualStudio
# Install VS # Install VS
Install-VisualStudio ` Install-VisualStudio `
-Version $toolset.visualStudio.subversion ` -Version $vsToolset.subversion `
-Edition $toolset.visualStudio.edition ` -Edition $vsToolset.edition `
-Channel $toolset.visualStudio.channel ` -Channel $vsToolset.channel `
-RequiredComponents $toolset.visualStudio.workloads ` -RequiredComponents $vsToolset.workloads `
-ExtraArgs "--allWorkloads --includeRecommended --remove Component.CPython3.x64" ` -ExtraArgs "--allWorkloads --includeRecommended --remove Component.CPython3.x64" `
-SignatureThumbprint $toolset.visualStudio.signature -SignatureThumbprint $vsToolset.signature
# Find the version of VS installed for this instance # Find the version of VS installed for this instance
# Only supports a single instance # Only supports a single instance
@@ -20,8 +20,7 @@ $vsProgramData = Get-Item -Path "C:\ProgramData\Microsoft\VisualStudio\Packages\
$instanceFolders = Get-ChildItem -Path $vsProgramData.FullName $instanceFolders = Get-ChildItem -Path $vsProgramData.FullName
if ($instanceFolders -is [array]) { if ($instanceFolders -is [array]) {
Write-Host "More than one instance installed" throw "More than one instance installed"
exit 1
} }
# Updating content of MachineState.json file to disable autoupdate of VSIX extensions # Updating content of MachineState.json file to disable autoupdate of VSIX extensions
@@ -35,7 +34,7 @@ if (Test-IsWin19) {
-Url 'https://go.microsoft.com/fwlink/p/?LinkId=838916' ` -Url 'https://go.microsoft.com/fwlink/p/?LinkId=838916' `
-InstallArgs @("/q", "/norestart", "/ceip off", "/features OptionId.WindowsSoftwareDevelopmentKit") ` -InstallArgs @("/q", "/norestart", "/ceip off", "/features OptionId.WindowsSoftwareDevelopmentKit") `
-ExpectedSignature 'C91545B333C52C4465DE8B90A3FAF4E1D9C58DFA' -ExpectedSignature 'C91545B333C52C4465DE8B90A3FAF4E1D9C58DFA'
# Install Windows 11 SDK version 10.0.22621.0 # Install Windows 11 SDK version 10.0.22621.0
Install-Binary -Type EXE ` Install-Binary -Type EXE `
-Url 'https://go.microsoft.com/fwlink/p/?linkid=2196241' ` -Url 'https://go.microsoft.com/fwlink/p/?linkid=2196241' `

View File

@@ -4,7 +4,7 @@
################################################################################ ################################################################################
Install-Binary -Type MSI ` Install-Binary -Type MSI `
-Url 'http://go.microsoft.com/fwlink/?LinkId=287166' ` -Url 'http://go.microsoft.com/fwlink/?LinkId=287166' `
-ExpectedSignature 'C3A3D43788E7ABCD287CB4F5B6583043774F99D2' -ExpectedSignature 'C3A3D43788E7ABCD287CB4F5B6583043774F99D2'
Invoke-PesterTests -TestFile "Tools" -TestName "WebPlatformInstaller" Invoke-PesterTests -TestFile "Tools" -TestName "WebPlatformInstaller"

View File

@@ -4,12 +4,13 @@
#################################################################################### ####################################################################################
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$downloadUrl = Resolve-GithubReleaseAssetUrl `
$latestReleaseUrl = 'https://api.github.com/repos/microsoft/WinAppDriver/releases/latest' -Repo "microsoft/WinAppDriver" `
$installerUrl = (Invoke-RestMethod -Uri $latestReleaseUrl).assets.browser_download_url -Version "latest" `
-UrlMatchPattern "WindowsApplicationDriver_*.msi"
Install-Binary ` Install-Binary `
-Url $installerUrl ` -Url $downloadUrl `
-ExpectedSignature '2485A7AFA98E178CB8F30C9838346B514AEA4769' -ExpectedSignature '2485A7AFA98E178CB8F30C9838346B514AEA4769'
Invoke-PesterTests -TestFile "WinAppDriver" -TestName "WinAppDriver" Invoke-PesterTests -TestFile "WinAppDriver" -TestName "WinAppDriver"

View File

@@ -1,3 +1,8 @@
####################################################################################
## File: Install-WindowsFeatures.ps1
## Desc: Install Windows Features
####################################################################################
$windowsFeatures = (Get-ToolsetContent).windowsFeatures $windowsFeatures = (Get-ToolsetContent).windowsFeatures
foreach ($feature in $windowsFeatures) { foreach ($feature in $windowsFeatures) {

View File

@@ -28,8 +28,7 @@ function Install-WindowsUpdates {
$failedUpdates = $updates[0] | Where-Object Title -notmatch "Microsoft Defender Antivirus" | Where-Object { -not ($notFailedUpdateNames -match $_.KB) } $failedUpdates = $updates[0] | Where-Object Title -notmatch "Microsoft Defender Antivirus" | Where-Object { -not ($notFailedUpdateNames -match $_.KB) }
if ( $failedUpdates ) { if ( $failedUpdates ) {
Write-Host "Windows updates failed to install: $($failedUpdates.KB)" throw "Windows updates failed to install: $($failedUpdates.KB)"
exit 1
} }
} }

View File

@@ -3,17 +3,18 @@
## Desc: Install zstd ## Desc: Install zstd
################################################################################ ################################################################################
$url = "https://api.github.com/repos/facebook/zstd/releases/latest" $downloadUrl = Resolve-GithubReleaseAssetUrl `
# Explicitly set type to string since match returns array by default -Repo "facebook/zstd" `
[System.String] $zstdLatest = (Invoke-RestMethod -Uri $url).assets.browser_download_url -match "zstd-.+-win64.zip$" -Version "latest" `
$zstdArchivePath = Invoke-DownloadWithRetry $zstdLatest -UrlMatchPattern "zstd-*-win64.zip"
$zstdArchivePath = Invoke-DownloadWithRetry $downloadUrl
$zstdName = [IO.Path]::GetFileNameWithoutExtension($zstdArchivePath)
$toolPath = "C:\tools" $toolPath = "C:\tools"
$zstdPath = Join-Path $toolPath zstd $zstdPath = Join-Path $toolPath zstd
$zstdParentName = [IO.Path]::GetFileNameWithoutExtension($zstdLatest)
$filesInArchive = 7z l $zstdArchivePath | Out-String $filesInArchive = 7z l $zstdArchivePath | Out-String
if ($filesInArchive.Contains($zstdParentName)) { if ($filesInArchive.Contains($zstdName)) {
Expand-7ZipArchive -Path $zstdArchivePath -DestinationPath $toolPath Expand-7ZipArchive -Path $zstdArchivePath -DestinationPath $toolPath
Invoke-ScriptBlockWithRetry -Command { Invoke-ScriptBlockWithRetry -Command {
Move-Item -Path "${zstdPath}*" -Destination $zstdPath -ErrorAction Stop Move-Item -Path "${zstdPath}*" -Destination $zstdPath -ErrorAction Stop

View File

@@ -1,28 +1,28 @@
function Get-ToolcacheGoVersions { function Get-ToolcacheGoVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Go" $toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Go"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version]$_ } return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
} }
function Get-ToolcacheNodeVersions { function Get-ToolcacheNodeVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Node" $toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Node"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version]$_ } return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
} }
function Get-ToolcachePythonVersions { function Get-ToolcachePythonVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Python" $toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Python"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version]$_ } return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
} }
function Get-ToolcacheRubyVersions { function Get-ToolcacheRubyVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Ruby" $toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Ruby"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version]$_ } return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
} }
function Get-ToolcachePyPyVersions { function Get-ToolcachePyPyVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "PyPy" $toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "PyPy"
Get-ChildItem -Path $toolcachePath -Name | Sort-Object { [Version] $_ } | ForEach-Object { Get-ChildItem -Path $toolcachePath -Name | Sort-Object { [Version] $_ } | ForEach-Object {
$pypyRootPath = Join-Path $toolcachePath $_ "x86" $pypyRootPath = Join-Path $toolcachePath $_ "x86"
[string]$pypyVersionOutput = & "$pypyRootPath\python.exe" -c "import sys;print(sys.version)" [string] $pypyVersionOutput = & "$pypyRootPath\python.exe" -c "import sys;print(sys.version)"
$pypyVersionOutput -match "^([\d\.]+) \(.+\) \[PyPy ([\d\.]+\S*) .+]$" | Out-Null $pypyVersionOutput -match "^([\d\.]+) \(.+\) \[PyPy ([\d\.]+\S*) .+]$" | Out-Null
return "{0} [PyPy {1}]" -f $Matches[1], $Matches[2] return "{0} [PyPy {1}]" -f $Matches[1], $Matches[2]
} }

View File

@@ -5,7 +5,7 @@ function Initialize-RustEnvironment {
} }
function Get-OSName { function Get-OSName {
return (Get-CimInstance -ClassName Win32_OperatingSystem).Caption | Take-Part -Part 1,2,3 return (Get-CimInstance -ClassName Win32_OperatingSystem).Caption | Get-StringPart -Part 1,2,3
} }
function Get-OSVersion { function Get-OSVersion {
@@ -26,75 +26,75 @@ function Get-BashVersion {
} }
function Get-RustVersion { function Get-RustVersion {
rustc --version | Take-Part -Part 1 rustc --version | Get-StringPart -Part 1
} }
function Get-RustupVersion { function Get-RustupVersion {
cmd /c "rustup --version 2>NUL" | Take-Part -Part 1 cmd /c "rustup --version 2>NUL" | Get-StringPart -Part 1
} }
function Get-RustCargoVersion { function Get-RustCargoVersion {
cargo --version | Take-Part -Part 1 cargo --version | Get-StringPart -Part 1
} }
function Get-RustdocVersion { function Get-RustdocVersion {
rustdoc --version | Take-Part -Part 1 rustdoc --version | Get-StringPart -Part 1
} }
function Get-RustfmtVersion { function Get-RustfmtVersion {
rustfmt --version | Take-Part -Part 1 | Take-Part -Part 0 -Delimiter ('-') rustfmt --version | Get-StringPart -Part 1 | Get-StringPart -Part 0 -Delimiter ('-')
} }
function Get-RustClippyVersion { function Get-RustClippyVersion {
cargo clippy --version | Take-Part -Part 1 cargo clippy --version | Get-StringPart -Part 1
} }
function Get-BindgenVersion { function Get-BindgenVersion {
bindgen --version | Take-Part -Part 1 bindgen --version | Get-StringPart -Part 1
} }
function Get-CbindgenVersion { function Get-CbindgenVersion {
cbindgen --version | Take-Part -Part 1 cbindgen --version | Get-StringPart -Part 1
} }
function Get-CargoAuditVersion { function Get-CargoAuditVersion {
cargo-audit --version | Take-Part -Part 1 cargo-audit --version | Get-StringPart -Part 1
} }
function Get-CargoOutdatedVersion { function Get-CargoOutdatedVersion {
cargo outdated --version | Take-Part -Part 1 cargo outdated --version | Get-StringPart -Part 1
} }
function Get-PythonVersion { function Get-PythonVersion {
python --version | Take-Part -Part 1 python --version | Get-StringPart -Part 1
} }
function Get-PowershellCoreVersion { function Get-PowershellCoreVersion {
pwsh --version | Take-Part -Part 1 pwsh --version | Get-StringPart -Part 1
} }
function Get-RubyVersion { function Get-RubyVersion {
ruby --version | Take-Part -Part 1 ruby --version | Get-StringPart -Part 1
} }
function Get-GoVersion { function Get-GoVersion {
go version | Take-Part -Part 2 | Take-Part -Part 1 -Delimiter ('o') go version | Get-StringPart -Part 2 | Get-StringPart -Part 1 -Delimiter ('o')
} }
function Get-KotlinVersion { function Get-KotlinVersion {
cmd /c "kotlinc -version 2>&1" | Take-Part -Part 2 cmd /c "kotlinc -version 2>&1" | Get-StringPart -Part 2
} }
function Get-PHPVersion { function Get-PHPVersion {
php --version | Out-String | Take-Part -Part 1 php --version | Out-String | Get-StringPart -Part 1
} }
function Get-JuliaVersion { function Get-JuliaVersion {
julia --version | Take-Part -Part 2 julia --version | Get-StringPart -Part 2
} }
function Get-LLVMVersion { function Get-LLVMVersion {
(clang --version) -match "clang" | Take-Part -Part 2 (clang --version) -match "clang" | Get-StringPart -Part 2
} }
function Get-PerlVersion { function Get-PerlVersion {
@@ -104,7 +104,7 @@ function Get-PerlVersion {
} }
function Get-NodeVersion { function Get-NodeVersion {
node --version | Take-Part -Part 0 -Delimiter ('v') node --version | Get-StringPart -Part 0 -Delimiter ('v')
} }
function Get-ChocoVersion { function Get-ChocoVersion {
@@ -135,7 +135,7 @@ function Get-HelmVersion {
} }
function Get-PipVersion { function Get-PipVersion {
(pip --version) -match "pip" | Take-Part -Part 1,4,5 (pip --version) -match "pip" | Get-StringPart -Part 1, 4, 5
} }
function Get-CondaVersion { function Get-CondaVersion {
@@ -144,19 +144,19 @@ function Get-CondaVersion {
} }
function Get-ComposerVersion { function Get-ComposerVersion {
composer --version | Take-Part -Part 2 composer --version | Get-StringPart -Part 2
} }
function Get-NugetVersion { function Get-NugetVersion {
(nuget help) -match "Nuget Version" | Take-Part -Part 2 (nuget help) -match "Nuget Version" | Get-StringPart -Part 2
} }
function Get-AntVersion { function Get-AntVersion {
ant -version | Take-Part -Part 3 ant -version | Get-StringPart -Part 3
} }
function Get-MavenVersion { function Get-MavenVersion {
(mvn -version) -match "Apache Maven" | Take-Part -Part 2 (mvn -version) -match "Apache Maven" | Get-StringPart -Part 2
} }
function Get-GradleVersion { function Get-GradleVersion {
@@ -166,16 +166,16 @@ function Get-GradleVersion {
} }
function Get-SbtVersion { function Get-SbtVersion {
(sbt -version) -match "sbt script" | Take-Part -Part 3 (sbt -version) -match "sbt script" | Get-StringPart -Part 3
} }
function Get-DotnetSdks { function Get-DotnetSdks {
$sdksRawList = dotnet --list-sdks $sdksRawList = dotnet --list-sdks
$sdkVersions = $sdksRawList | Foreach-Object {$_.Split()[0]} $sdkVersions = $sdksRawList | Foreach-Object { $_.Split()[0] }
$sdkPath = $sdksRawList[0].Split(' ', 2)[1] -replace '\[|]' $sdkPath = $sdksRawList[0].Split(' ', 2)[1] -replace '\[|]'
[PSCustomObject]@{ [PSCustomObject]@{
Versions = $sdkVersions Versions = $sdkVersions
Path = $sdkPath Path = $sdkPath
} }
} }
@@ -185,7 +185,7 @@ function Get-DotnetTools {
$toolsList = @() $toolsList = @()
foreach ($dotnetTool in $dotnetTools) { foreach ($dotnetTool in $dotnetTools) {
$version = Invoke-Expression $dotnetTool.getversion $version = Invoke-Expression $dotnetTool.getversion
$toolsList += [ToolVersionNode]::new($dotnetTool.name, $version) $toolsList += [ToolVersionNode]::new($dotnetTool.name, $version)
} }
@@ -194,21 +194,21 @@ function Get-DotnetTools {
function Get-DotnetRuntimes { function Get-DotnetRuntimes {
$runtimesRawList = dotnet --list-runtimes $runtimesRawList = dotnet --list-runtimes
$runtimesRawList | Group-Object {$_.Split()[0]} | ForEach-Object { $runtimesRawList | Group-Object { $_.Split()[0] } | ForEach-Object {
$runtimeName = $_.Name $runtimeName = $_.Name
$runtimeVersions = $_.Group | Foreach-Object {$_.split()[1]} $runtimeVersions = $_.Group | Foreach-Object { $_.split()[1] }
$runtimePath = $_.Group[0].Split(' ', 3)[2] -replace '\[|]' $runtimePath = $_.Group[0].Split(' ', 3)[2] -replace '\[|]'
[PSCustomObject]@{ [PSCustomObject]@{
"Runtime" = $runtimeName "Runtime" = $runtimeName
"Versions" = $runtimeVersions "Versions" = $runtimeVersions
"Path" = $runtimePath "Path" = $runtimePath
} }
} }
} }
function Get-DotnetFrameworkVersions { function Get-DotnetFrameworkVersions {
$path = "${env:ProgramFiles(x86)}\Microsoft SDKs\Windows\*\*\NETFX * Tools" $path = "${env:ProgramFiles(x86)}\Microsoft SDKs\Windows\*\*\NETFX * Tools"
return Get-ChildItem -Path $path -Directory | ForEach-Object { $_.Name | Take-Part -Part 1 } return Get-ChildItem -Path $path -Directory | ForEach-Object { $_.Name | Get-StringPart -Part 1 }
} }
function Get-PowerShellAzureModules { function Get-PowerShellAzureModules {
@@ -276,20 +276,21 @@ function Get-CachedDockerImagesTableData {
$parts = $_.Split("|") $parts = $_.Split("|")
[PSCustomObject] @{ [PSCustomObject] @{
"Repository:Tag" = $parts[0] "Repository:Tag" = $parts[0]
"Digest" = $parts[1] "Digest" = $parts[1]
"Created" = $parts[2].split(' ')[0] "Created" = $parts[2].split(' ')[0]
} }
} | Sort-Object -Property "Repository:Tag" } | Sort-Object -Property "Repository:Tag"
} }
function Get-ShellTarget { function Get-ShellTarget {
return Get-ChildItem C:\shells -File | Select-Object Name, @{n="Target";e={ return Get-ChildItem C:\shells -File | Select-Object Name, @{n = "Target"; e = {
if ($_.Name -eq "msys2bash.cmd") { if ($_.Name -eq "msys2bash.cmd") {
"C:\msys64\usr\bin\bash.exe" "C:\msys64\usr\bin\bash.exe"
} else { } else {
@($_.Target)[0] @($_.Target)[0]
}
} }
}} | Sort-Object Name } | Sort-Object Name
} }
function Get-PacmanVersion { function Get-PacmanVersion {
@@ -302,7 +303,7 @@ function Get-PacmanVersion {
} }
function Get-YAMLLintVersion { function Get-YAMLLintVersion {
yamllint --version | Take-Part -Part 1 yamllint --version | Get-StringPart -Part 1
} }
function Get-BizTalkVersion { function Get-BizTalkVersion {

View File

@@ -17,7 +17,7 @@ function Get-PathWithLink {
return "${inputPath}${link}" return "${inputPath}${link}"
} }
function Take-Part { function Get-StringPart {
param ( param (
[Parameter(ValueFromPipeline)] [Parameter(ValueFromPipeline)]
[string] $toolOutput, [string] $toolOutput,
@@ -27,4 +27,4 @@ function Take-Part {
$parts = $toolOutput.Split($Delimiter, [System.StringSplitOptions]::RemoveEmptyEntries) $parts = $toolOutput.Split($Delimiter, [System.StringSplitOptions]::RemoveEmptyEntries)
$selectedParts = $parts[$Part] $selectedParts = $parts[$Part]
return [string]::Join($Delimiter, $selectedParts) return [string]::Join($Delimiter, $selectedParts)
} }

View File

@@ -2,7 +2,7 @@ function Get-JavaVersions {
$defaultJavaPath = $env:JAVA_HOME $defaultJavaPath = $env:JAVA_HOME
$javaVersions = Get-Item env:JAVA_HOME_*_X64 $javaVersions = Get-Item env:JAVA_HOME_*_X64
$sortRules = @{ $sortRules = @{
Expression = { [Int32]$_.Name.Split("_")[2] } Expression = { [Int32] $_.Name.Split("_")[2] }
Descending = $false Descending = $false
} }
@@ -19,4 +19,4 @@ function Get-JavaVersions {
"Environment Variable" = $_.Name "Environment Variable" = $_.Name
} }
} }
} }

View File

@@ -66,12 +66,12 @@ function Get-DockerComposeVersionV2 {
} }
function Get-DockerWincredVersion { function Get-DockerWincredVersion {
$dockerCredVersion = docker-credential-wincred version | Take-Part -Part 2 | Take-Part -Part 0 -Delimiter "v" $dockerCredVersion = docker-credential-wincred version | Get-StringPart -Part 2 | Get-StringPart -Part 0 -Delimiter "v"
return $dockerCredVersion return $dockerCredVersion
} }
function Get-GitVersion { function Get-GitVersion {
$gitVersion = git --version | Take-Part -Part -1 $gitVersion = git --version | Get-StringPart -Part -1
return $gitVersion return $gitVersion
} }

View File

@@ -1,4 +1,25 @@
function Install-ChocoPackage { function Install-ChocoPackage {
<#
.SYNOPSIS
A function to install a Chocolatey package with retries.
.DESCRIPTION
This function attempts to install a specified Chocolatey package. If the
installation fails, it retries a specified number of times.
.PARAMETER PackageName
The name of the Chocolatey package to install.
.PARAMETER ArgumentList
An array of arguments to pass to the choco install command.
.PARAMETER RetryCount
The number of times to retry the installation if it fails. Default is 5.
.EXAMPLE
Install-ChocoPackage -PackageName "git" -RetryCount 3
#>
[CmdletBinding()] [CmdletBinding()]
param( param(
[Parameter(Mandatory)] [Parameter(Mandatory)]
@@ -30,6 +51,25 @@ function Install-ChocoPackage {
} }
function Resolve-ChocoPackageVersion { function Resolve-ChocoPackageVersion {
<#
.SYNOPSIS
Resolves the latest version of a Chocolatey package.
.DESCRIPTION
This function takes a package name and a target version as input and returns the latest
version of the package that is greater than or equal to the target version.
.PARAMETER PackageName
The name of the Chocolatey package.
.PARAMETER TargetVersion
The target version of the package.
.EXAMPLE
Resolve-ChocoPackageVersion -PackageName "example-package" -TargetVersion "1.0.0"
Returns the latest version of the "example-package" that is greater than or equal to "1.0.0".
#>
param( param(
[Parameter(Mandatory)] [Parameter(Mandatory)]
[string] $PackageName, [string] $PackageName,
@@ -38,12 +78,12 @@ function Resolve-ChocoPackageVersion {
) )
$versionNumbers = $TargetVersion.Split(".") $versionNumbers = $TargetVersion.Split(".")
[int]$versionNumbers[-1] += 1 [int] $versionNumbers[-1] += 1
$incrementedVersion = $versionNumbers -join "." $incrementedVersion = $versionNumbers -join "."
$filterQuery = "`$filter=(Id eq '$PackageName') and (IsPrerelease eq false) and (Version ge '$TargetVersion') and (Version lt '$incrementedVersion')" $filterQuery = "`$filter=(Id eq '$PackageName') and (IsPrerelease eq false) and (Version ge '$TargetVersion') and (Version lt '$incrementedVersion')"
$latestVersion = (Invoke-RestMethod "https://community.chocolatey.org/api/v2/Packages()?$filterQuery").properties.Version | $latestVersion = (Invoke-RestMethod "https://community.chocolatey.org/api/v2/Packages()?$filterQuery").properties.Version |
Where-Object { $_ -Like "$TargetVersion.*" -or $_ -eq $TargetVersion } | Where-Object { $_ -Like "$TargetVersion.*" -or $_ -eq $TargetVersion } |
Sort-Object { [version]$_ } | Sort-Object { [version] $_ } |
Select-Object -Last 1 Select-Object -Last 1
return $latestVersion return $latestVersion

View File

@@ -2,43 +2,55 @@
param() param()
. $PSScriptRoot\AndroidHelpers.ps1 . $PSScriptRoot\AndroidHelpers.ps1
. $PSScriptRoot\ChocoHelpers.ps1 Export-ModuleMember -Function @(
. $PSScriptRoot\InstallHelpers.ps1 'Get-AndroidPackages'
. $PSScriptRoot\PathHelpers.ps1 'Get-AndroidPlatformPackages'
. $PSScriptRoot\VisualStudioHelpers.ps1 'Get-AndroidBuildToolPackages'
'Get-AndroidInstalledPackages'
)
. $PSScriptRoot\ChocoHelpers.ps1
Export-ModuleMember -Function @(
'Install-ChocoPackage'
'Resolve-ChocoPackageVersion'
)
. $PSScriptRoot\InstallHelpers.ps1
Export-ModuleMember -Function @(
'Install-Binary'
'Invoke-DownloadWithRetry'
'Get-ToolsetContent'
'Get-TCToolPath'
'Get-TCToolVersionPath'
'Test-IsWin22'
'Test-IsWin19'
'Expand-7ZipArchive'
'Get-WindowsUpdateStates'
'Invoke-ScriptBlockWithRetry'
'Get-GithubReleasesByVersion'
'Resolve-GithubReleaseAssetUrl'
'Get-ChecksumFromGithubRelease'
'Get-ChecksumFromUrl'
'Test-FileChecksum'
'Test-FileSignature'
'Update-Environment'
)
. $PSScriptRoot\PathHelpers.ps1
Export-ModuleMember -Function @( Export-ModuleMember -Function @(
'Mount-RegistryHive' 'Mount-RegistryHive'
'Dismount-RegistryHive' 'Dismount-RegistryHive'
'Add-MachinePathItem' 'Add-MachinePathItem'
'Add-DefaultPathItem' 'Add-DefaultPathItem'
'Install-Binary' )
. $PSScriptRoot\VisualStudioHelpers.ps1
Export-ModuleMember -Function @(
'Install-VisualStudio' 'Install-VisualStudio'
'Get-ToolsetContent' 'Get-VisualStudioInstance'
'Get-TCToolVersionPath' 'Get-VisualStudioComponents'
'Get-TCToolPath'
'Invoke-DownloadWithRetry'
'Get-VsixInfoFromMarketplace' 'Get-VsixInfoFromMarketplace'
'Install-VSIXFromFile' 'Install-VSIXFromFile'
'Install-VSIXFromUrl' 'Install-VSIXFromUrl'
'Get-VSExtensionVersion' 'Get-VSExtensionVersion'
'Test-IsWin22'
'Test-IsWin19'
'Install-ChocoPackage'
'Resolve-ChocoPackageVersion'
'Resolve-GithubReleaseAssetUrl'
'Expand-7ZipArchive'
'Invoke-ScriptBlockWithRetry'
'Get-VsCatalogJsonPath'
'Get-AndroidPackages'
'Get-AndroidPlatformPackages'
'Get-AndroidBuildToolPackages'
'Get-AndroidInstalledPackages'
'Get-VisualStudioInstance'
'Get-VisualStudioComponents'
'Get-WindowsUpdateStates'
'Get-GithubReleaseAssetHash'
'Test-FileChecksum'
'Test-FileSignature'
'Update-Environment'
) )

View File

@@ -131,6 +131,33 @@ function Install-Binary {
} }
function Invoke-DownloadWithRetry { function Invoke-DownloadWithRetry {
<#
.SYNOPSIS
Downloads a file from a given URL with retry functionality.
.DESCRIPTION
The Invoke-DownloadWithRetry function downloads a file from the specified URL
to the specified path. It includes retry functionality in case the download fails.
.PARAMETER Url
The URL of the file to download.
.PARAMETER Path
The path where the downloaded file will be saved. If not provided, a temporary path
will be used.
.EXAMPLE
Invoke-DownloadWithRetry -Url "https://example.com/file.zip" -Path "C:\Downloads\file.zip"
Downloads the file from the specified URL and saves it to the specified path.
.EXAMPLE
Invoke-DownloadWithRetry -Url "https://example.com/file.zip"
Downloads the file from the specified URL and saves it to a temporary path.
.OUTPUTS
The path where the downloaded file is saved.
#>
Param Param
( (
[Parameter(Mandatory)] [Parameter(Mandatory)]
@@ -165,6 +192,11 @@ function Invoke-DownloadWithRetry {
$attemptSeconds = [math]::Round(($(Get-Date) - $attemptStartTime).TotalSeconds, 2) $attemptSeconds = [math]::Round(($(Get-Date) - $attemptStartTime).TotalSeconds, 2)
Write-Warning "Package download failed in $attemptSeconds seconds" Write-Warning "Package download failed in $attemptSeconds seconds"
Write-Warning $_.Exception.Message Write-Warning $_.Exception.Message
if ($_.Exception.InnerException.Response.StatusCode -eq [System.Net.HttpStatusCode]::NotFound) {
Write-Warning "Request returned 404 Not Found. Aborting download."
$retries = 0
}
} }
if ($retries -eq 0) { if ($retries -eq 0) {
@@ -180,6 +212,15 @@ function Invoke-DownloadWithRetry {
} }
function Get-ToolsetContent { function Get-ToolsetContent {
<#
.SYNOPSIS
Retrieves the content of the toolset.json file.
.DESCRIPTION
This function reads the toolset.json file located at "C:\image\toolset.json"
and returns the content as a PowerShell object.
#>
$toolsetPath = Join-Path "C:\\image" "toolset.json" $toolsetPath = Join-Path "C:\\image" "toolset.json"
$toolsetJson = Get-Content -Path $toolsetPath -Raw $toolsetJson = Get-Content -Path $toolsetPath -Raw
ConvertFrom-Json -InputObject $toolsetJson ConvertFrom-Json -InputObject $toolsetJson
@@ -478,6 +519,10 @@ function Get-GithubReleasesByVersion {
.PARAMETER AllowPrerelease .PARAMETER AllowPrerelease
Specifies whether to include prerelease versions in the results. By default, Specifies whether to include prerelease versions in the results. By default,
prerelease versions are excluded. prerelease versions are excluded.
.PARAMETER WithAssetsOnly
Specifies whether to exclude releases without assets. By default, releases without
assets are included.
.EXAMPLE .EXAMPLE
Get-GithubReleasesByVersion -Repository "Microsoft/PowerShell" -Version "7.2.0" Get-GithubReleasesByVersion -Repository "Microsoft/PowerShell" -Version "7.2.0"
@@ -500,7 +545,8 @@ function Get-GithubReleasesByVersion {
[Alias("Repo")] [Alias("Repo")]
[string] $Repository, [string] $Repository,
[string] $Version = "*", [string] $Version = "*",
[switch] $AllowPrerelease [switch] $AllowPrerelease,
[switch] $WithAssetsOnly
) )
$localCacheFile = Join-Path ${env:TEMP} "github-releases_$($Repository -replace "/", "_").json" $localCacheFile = Join-Path ${env:TEMP} "github-releases_$($Repository -replace "/", "_").json"
@@ -528,7 +574,9 @@ function Get-GithubReleasesByVersion {
throw "Failed to get releases from ${Repository}" throw "Failed to get releases from ${Repository}"
} }
$releases = $releases.Where{ $_.assets } if ($WithAssetsOnly) {
$releases = $releases.Where{ $_.assets }
}
if (-not $AllowPrerelease) { if (-not $AllowPrerelease) {
$releases = $releases.Where{ $_.prerelease -eq $false } $releases = $releases.Where{ $_.prerelease -eq $false }
} }
@@ -608,7 +656,8 @@ function Resolve-GithubReleaseAssetUrl {
$matchingReleases = Get-GithubReleasesByVersion ` $matchingReleases = Get-GithubReleasesByVersion `
-Repository $Repository ` -Repository $Repository `
-AllowPrerelease:$AllowPrerelease ` -AllowPrerelease:$AllowPrerelease `
-Version $Version -Version $Version `
-WithAssetsOnly
# Add wildcard to the beginning of the pattern if it's not there # Add wildcard to the beginning of the pattern if it's not there
if ($UrlMatchPattern.Substring(0, 2) -ne "*/") { if ($UrlMatchPattern.Substring(0, 2) -ne "*/") {
@@ -618,7 +667,7 @@ function Resolve-GithubReleaseAssetUrl {
# Loop over releases until we find a download url matching the pattern # Loop over releases until we find a download url matching the pattern
foreach ($release in $matchingReleases) { foreach ($release in $matchingReleases) {
$matchedVersion = $release.version $matchedVersion = $release.version
$matchedUrl = $release.assets.browser_download_url -like $UrlMatchPattern $matchedUrl = ([string[]] $release.assets.browser_download_url) -like $UrlMatchPattern
if ($matchedUrl) { if ($matchedUrl) {
break break
} }
@@ -638,13 +687,13 @@ function Resolve-GithubReleaseAssetUrl {
return ($matchedUrl -as [string]) return ($matchedUrl -as [string])
} }
function Get-GithubReleaseAssetHash { function Get-ChecksumFromGithubRelease {
<# <#
.SYNOPSIS .SYNOPSIS
Retrieves the hash value of a specific file from a GitHub release body. Retrieves the hash value of a specific file from a GitHub release body.
.DESCRIPTION .DESCRIPTION
The Get-GithubReleaseAssetHash function retrieves the hash value (SHA256 or SHA512) The Get-ChecksumFromGithubRelease function retrieves the hash value (SHA256 or SHA512)
of a specific file from a GitHub release. It searches for the file in the release body of a specific file from a GitHub release. It searches for the file in the release body
and returns the hash value if found. and returns the hash value if found.
@@ -666,12 +715,12 @@ function Get-GithubReleaseAssetHash {
The type of hash value to retrieve. Valid values are "SHA256" and "SHA512". The type of hash value to retrieve. Valid values are "SHA256" and "SHA512".
.EXAMPLE .EXAMPLE
Get-GithubReleaseAssetHash -Repository "MyRepo" -FileName "myfile.txt" -HashType "SHA256" Get-ChecksumFromGithubRelease -Repository "MyRepo" -FileName "myfile.txt" -HashType "SHA256"
Retrieves the SHA256 hash value of "myfile.txt" from the latest release of the "MyRepo" repository. Retrieves the SHA256 hash value of "myfile.txt" from the latest release of the "MyRepo" repository.
.EXAMPLE .EXAMPLE
Get-GithubReleaseAssetHash -Repository "MyRepo" -Version "1.0" -FileName "myfile.txt" -HashType "SHA512" Get-ChecksumFromGithubRelease -Repository "MyRepo" -Version "1.0" -FileName "myfile.txt" -HashType "SHA512"
Retrieves the SHA512 hash value of "myfile.txt" from the release version "1.0" of the "MyRepo" repository. Retrieves the SHA512 hash value of "myfile.txt" from the release version "1.0" of the "MyRepo" repository.
#> #>
@@ -693,7 +742,8 @@ function Get-GithubReleaseAssetHash {
$matchingReleases = Get-GithubReleasesByVersion ` $matchingReleases = Get-GithubReleasesByVersion `
-Repository $Repository ` -Repository $Repository `
-AllowPrerelease:$AllowPrerelease ` -AllowPrerelease:$AllowPrerelease `
-Version $Version -Version $Version `
-WithAssetsOnly
foreach ($release in $matchingReleases) { foreach ($release in $matchingReleases) {
$matchedVersion = $release.version $matchedVersion = $release.version
@@ -728,6 +778,70 @@ function Get-GithubReleaseAssetHash {
return $hash return $hash
} }
function Get-ChecksumFromUrl {
<#
.SYNOPSIS
Retrieves the checksum hash for a file from a given URL.
.DESCRIPTION
The Get-ChecksumFromUrl function retrieves the checksum hash for a specified file
from a given URL. It supports SHA256 and SHA512 hash types.
.PARAMETER Url
The URL of the checksum file.
.PARAMETER FileName
The name of the file to retrieve the checksum hash for.
.PARAMETER HashType
The type of hash to retrieve. Valid values are "SHA256" and "SHA512".
.EXAMPLE
Get-ChecksumFromUrl -Url "https://example.com/checksums.txt" -FileName "file.txt" -HashType "SHA256"
Retrieves the SHA256 checksum hash for the file "file.txt" from the URL "https://example.com/checksums.txt".
#>
param (
[Parameter(Mandatory = $true)]
[string] $Url,
[Parameter(Mandatory = $true)]
[Alias("File", "Asset")]
[string] $FileName,
[Parameter(Mandatory = $true)]
[ValidateSet("SHA256", "SHA512")]
[Alias("Type")]
[string] $HashType
)
$tempFile = Join-Path -Path $env:TEMP -ChildPath ([System.IO.Path]::GetRandomFileName())
$checksums = (Invoke-DownloadWithRetry -Url $Url -Path $tempFile | Get-Item | Get-Content) -as [string[]]
Remove-Item -Path $tempFile
$matchedLine = $checksums | Where-Object { $_ -like "*$FileName*" }
if ($matchedLine.Count -gt 1) {
throw "Found multiple lines matching file name '${FileName}' in checksum file."
} elseif ($matchedLine.Count -eq 0) {
throw "File name '${FileName}' not found in checksum file."
}
if ($HashType -eq "SHA256") {
$pattern = "[A-Fa-f0-9]{64}"
} elseif ($HashType -eq "SHA512") {
$pattern = "[A-Fa-f0-9]{128}"
} else {
throw "Unknown hash type: ${HashType}"
}
Write-Debug "Found line matching file name '${FileName}' in checksum file:`n${matchedLine}"
$hash = $matchedLine | Select-String -Pattern $pattern | ForEach-Object { $_.Matches.Value }
if ([string]::IsNullOrEmpty($hash)) {
throw "Found '${FileName}' in checksum file, but failed to get hash from it.`nLine: ${matchedLine}"
}
Write-Host "Found hash for ${FileName} in checksum file: $hash"
return $hash
}
function Test-FileChecksum { function Test-FileChecksum {
<# <#
.SYNOPSIS .SYNOPSIS

View File

@@ -18,9 +18,9 @@ function Mount-RegistryHive {
#> #>
param( param(
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[string]$FileName, [string] $FileName,
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[string]$SubKey [string] $SubKey
) )
Write-Host "Loading the file $FileName to the Key $SubKey" Write-Host "Loading the file $FileName to the Key $SubKey"
@@ -31,8 +31,7 @@ function Mount-RegistryHive {
$result = reg load $SubKey $FileName *>&1 $result = reg load $SubKey $FileName *>&1
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to load file $FileName to the key ${SubKey}: $result" throw "Failed to load file $FileName to the key ${SubKey}: $result"
exit 1
} }
} }
@@ -52,7 +51,7 @@ function Dismount-RegistryHive {
#> #>
param( param(
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[string]$SubKey [string] $SubKey
) )
Write-Host "Unloading the hive $SubKey" Write-Host "Unloading the hive $SubKey"
@@ -87,12 +86,12 @@ function Add-MachinePathItem {
param( param(
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[string]$PathItem [string] $PathItem
) )
$currentPath = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") $currentPath = [System.Environment]::GetEnvironmentVariable("PATH", "Machine")
$newPath = $PathItem + ';' + $currentPath $newPath = $PathItem + ';' + $currentPath
[System.Environment]::SetEnvironmentVariable("PATH", $newPath, "Machine") [Environment]::SetEnvironmentVariable("PATH", $newPath, "Machine")
} }
function Add-DefaultPathItem { function Add-DefaultPathItem {
@@ -120,7 +119,7 @@ function Add-DefaultPathItem {
param( param(
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[string]$PathItem [string] $PathItem
) )
Mount-RegistryHive ` Mount-RegistryHive `

View File

@@ -117,18 +117,65 @@ Function Install-VisualStudio {
} }
function Get-VisualStudioInstance { function Get-VisualStudioInstance {
<#
.SYNOPSIS
Retrieves the Visual Studio instance.
.DESCRIPTION
This function retrieves the Visual Studio instance
using the Get-VSSetupInstance cmdlet.
It searches for both regular and preview versions
of Visual Studio and returns the first instance found.
#>
# Use -Prerelease and -All flags to make sure that Preview versions of VS are found correctly # Use -Prerelease and -All flags to make sure that Preview versions of VS are found correctly
$vsInstance = Get-VSSetupInstance -Prerelease -All | Where-Object { $_.DisplayName -match "Visual Studio" } | Select-Object -First 1 $vsInstance = Get-VSSetupInstance -Prerelease -All | Where-Object { $_.DisplayName -match "Visual Studio" } | Select-Object -First 1
$vsInstance | Select-VSSetupInstance -Product * $vsInstance | Select-VSSetupInstance -Product *
} }
function Get-VisualStudioComponents { function Get-VisualStudioComponents {
(Get-VisualStudioInstance).Packages | Where-Object type -in 'Component', 'Workload' | <#
Sort-Object Id, Version | Select-Object @{n = 'Package'; e = { $_.Id } }, Version | .SYNOPSIS
Where-Object { $_.Package -notmatch "[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}" } Retrieves the Visual Studio components.
.DESCRIPTION
This function retrieves the Visual Studio components
by filtering the packages returned by Get-VisualStudioInstance cmdlet.
It filters the packages based on their type, sorts them by Id and Version,
and excludes packages with GUID-like Ids.
#>
(Get-VisualStudioInstance).Packages `
| Where-Object type -in 'Component', 'Workload' `
| Sort-Object Id, Version `
| Select-Object @{n = 'Package'; e = { $_.Id } }, Version `
| Where-Object { $_.Package -notmatch "[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}" }
} }
function Get-VsixInfoFromMarketplace { function Get-VsixInfoFromMarketplace {
<#
.SYNOPSIS
Retrieves information about a Visual Studio extension from the Visual Studio Marketplace.
.DESCRIPTION
The Get-VsixInfoFromMarketplace function retrieves information
about a Visual Studio extension from the Visual Studio Marketplace.
It takes the name of the extension as input and returns
the extension's name, VsixId, filename, and download URI.
.PARAMETER Name
The name of the Visual Studio extension.
.PARAMETER MarketplaceUri
The URI of the Visual Studio Marketplace.
Default value is "https://marketplace.visualstudio.com/items?itemName=".
.EXAMPLE
Get-VsixInfoFromMarketplace -Name "ProBITools.MicrosoftReportProjectsforVisualStudio2022"
Retrieves information about the "ProBITools.MicrosoftReportProjectsforVisualStudio2022" extension
from the Visual Studio Marketplace.
#>
Param Param
( (
[Parameter(Mandatory)] [Parameter(Mandatory)]
@@ -183,6 +230,25 @@ function Get-VsixInfoFromMarketplace {
} }
function Install-VSIXFromFile { function Install-VSIXFromFile {
<#
.SYNOPSIS
Installs a Visual Studio Extension (VSIX) from a file.
.DESCRIPTION
This function installs a Visual Studio Extension (VSIX)
from the specified file path. It uses the VSIXInstaller.exe
tool provided by Microsoft Visual Studio.
.PARAMETER FilePath
The path to the VSIX file that needs to be installed.
.PARAMETER Retries
The number of retries to attempt if the installation fails. Default is 20.
.EXAMPLE
Install-VSIXFromFile -FilePath "C:\Extensions\MyExtension.vsix" -Retries 10
Installs the VSIX file located at "C:\Extensions\MyExtension.vsix" with 10 retries in case of failure.
#>
Param Param
( (
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
@@ -228,6 +294,25 @@ function Install-VSIXFromFile {
} }
function Install-VSIXFromUrl { function Install-VSIXFromUrl {
<#
.SYNOPSIS
Installs a Visual Studio extension (VSIX) from a given URL.
.DESCRIPTION
This function downloads a Visual Studio extension (VSIX)
from the specified URL and installs it.
.PARAMETER Url
The URL of the VSIX file to download and install.
.PARAMETER Retries
The number of retries to attempt if the download fails. Default is 20.
.EXAMPLE
Install-VSIXFromUrl -Url "https://example.com/extension.vsix" -Retries 10
Downloads and installs the VSIX file from the specified URL with 10 retries.
#>
Param Param
( (
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
@@ -241,6 +326,22 @@ function Install-VSIXFromUrl {
} }
function Get-VSExtensionVersion { function Get-VSExtensionVersion {
<#
.SYNOPSIS
Retrieves the version of a Visual Studio extension package.
.DESCRIPTION
This function retrieves the version of a specified Visual Studio extension package.
It searches for the package in the installed instances of Visual Studio and
returns the version number.
.PARAMETER packageName
The name of the extension package.
.EXAMPLE
Get-VSExtensionVersion -packageName "MyExtensionPackage"
Retrieves the version of the extension package named "MyExtensionPackage" for Visual Studio.
#>
Param Param
( (
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]

View File

@@ -1,16 +1,16 @@
Describe "Haskell" { Describe "Haskell" {
$ghcPackagesPath = "c:\ghcup\ghc" $ghcPackagesPath = "c:\ghcup\ghc"
[array]$ghcVersionList = Get-ChildItem -Path $ghcPackagesPath -Filter "*" | ForEach-Object { $_.Name.Trim() } [array] $ghcVersionList = Get-ChildItem -Path $ghcPackagesPath -Filter "*" | ForEach-Object { $_.Name.Trim() }
$ghcCount = $ghcVersionList.Count $ghcCount = $ghcVersionList.Count
$defaultGhcVersion = $ghcVersionList | Sort-Object {[Version]$_} | Select-Object -Last 1 $defaultGhcVersion = $ghcVersionList | Sort-Object {[Version] $_} | Select-Object -Last 1
$ghcDefaultCases = @{ $ghcDefaultCases = @{
defaultGhcVersion = $defaultGhcVersion defaultGhcVersion = $defaultGhcVersion
defaultGhcShortVersion = ([version]$defaultGhcVersion).ToString(3) defaultGhcShortVersion = ([version] $defaultGhcVersion).ToString(3)
} }
$ghcTestCases = $ghcVersionList | ForEach-Object { $ghcTestCases = $ghcVersionList | ForEach-Object {
$ghcVersion = $_ $ghcVersion = $_
$ghcShortVersion = ([version]$ghcVersion).ToString(3) $ghcShortVersion = ([version] $ghcVersion).ToString(3)
$binGhcPath = Join-Path $ghcPackagesPath "$ghcShortVersion\bin\ghc.exe" $binGhcPath = Join-Path $ghcPackagesPath "$ghcShortVersion\bin\ghc.exe"
@{ @{
ghcVersion = $ghcVersion ghcVersion = $ghcVersion

View File

@@ -3,7 +3,7 @@ Describe "Java" {
$defaultVersion = $toolsetJava.default $defaultVersion = $toolsetJava.default
$jdkVersions = $toolsetJava.versions $jdkVersions = $toolsetJava.versions
[array]$testCases = $jdkVersions | ForEach-Object { @{Version = $_ } } [array] $testCases = $jdkVersions | ForEach-Object { @{Version = $_ } }
It "Java <DefaultJavaVersion> is default" -TestCases @(@{ DefaultJavaVersion = $defaultVersion }) { It "Java <DefaultJavaVersion> is default" -TestCases @(@{ DefaultJavaVersion = $defaultVersion }) {
$actualJavaPath = Get-EnvironmentVariable "JAVA_HOME" $actualJavaPath = Get-EnvironmentVariable "JAVA_HOME"