[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
- 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.
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.

View File

@@ -13,7 +13,7 @@ Set-PSRepository -InstallationPolicy Trusted -Name PSGallery
Write-Host 'Warmup PSModuleAnalysisCachePath (speedup first powershell invocation by 20s)'
$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
${env:PSModuleAnalysisCachePath} = $PSModuleAnalysisCachePath

View File

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

View File

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

View File

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

View File

@@ -5,34 +5,26 @@
$azureDevOpsCliConfigPath = 'C:\azureDevOpsCli'
# Store azure-devops-cli cache outside of the provisioning user's profile
[Environment]::SetEnvironmentVariable('AZ_DEVOPS_GLOBAL_CONFIG_DIR', $azureDevOpsCliConfigPath, [System.EnvironmentVariableTarget]::Machine)
# make variable to be available in the current session
${env:AZ_DEVOPS_GLOBAL_CONFIG_DIR} = $azureDevOpsCliConfigPath
[Environment]::SetEnvironmentVariable('AZ_DEVOPS_GLOBAL_CONFIG_DIR', $azureDevOpsCliConfigPath, "Machine")
$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)
# make variable to be available in the current session
${env:AZURE_DEVOPS_CACHE_DIR} = $azureDevOpsCliCachePath
Update-Environment
az extension add -n azure-devops
if ($LASTEXITCODE -ne 0)
{
if ($LASTEXITCODE -ne 0) {
throw "Command 'az extension add -n azure-devops' failed"
}
# Warm-up Azure DevOps CLI
Write-Host "Warmup 'az-devops'"
@('devops', 'pipelines', 'boards', 'repos', 'artifacts') | ForEach-Object {
az $_ --help
if ($LASTEXITCODE -ne 0)
{
if ($LASTEXITCODE -ne 0) {
throw "Command 'az $_ --help' failed"
}
}
# 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
npm install -g @bazel/bazelisk
if ($LASTEXITCODE -ne 0) {
throw "Command 'npm install -g @bazel/bazelisk' failed"
}
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"
Write-Host "Install chocolatey"
$chocoExePath = 'C:\ProgramData\Chocolatey\bin'
# Add to system PATH
$systemPath = [Environment]::GetEnvironmentVariable('Path', [System.EnvironmentVariableTarget]::Machine)
$systemPath += ';' + $chocoExePath
[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
}
Add-MachinePathItem 'C:\ProgramData\Chocolatey\bin'
Update-Environment
# Verify and run choco installer
$signatureThumbprint = "83AC7D88C66CB8680BCE802E0F0F5C179722764B"

View File

@@ -33,8 +33,7 @@ $regGoogleParameters = @(
$regGoogleParameters | ForEach-Object {
$Arguments = $_
if (-not ($Arguments.Path))
{
if (-not ($Arguments.Path)) {
$Arguments.Add("Path", $regGoogleUpdatePath)
}
$Arguments.Add("Force", $true)
@@ -44,8 +43,7 @@ $regGoogleParameters | ForEach-Object {
# Install Chrome WebDriver
Write-Host "Install Chrome WebDriver..."
$ChromeDriverPath = "$($env:SystemDrive)\SeleniumWebDrivers\ChromeDriver"
if (-not (Test-Path -Path $ChromeDriverPath))
{
if (-not (Test-Path -Path $ChromeDriverPath)) {
New-Item -Path $ChromeDriverPath -ItemType Directory -Force
}
@@ -63,7 +61,7 @@ $ChromeDriverVersion = $ChromeDriverVersions.builds.$ChromeBuild
if (-not ($ChromeDriverVersion)) {
$availableVersions = $ChromeDriverVersions.builds | Get-Member | Select-Object -ExpandProperty Name
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;
@@ -79,10 +77,7 @@ Expand-7ZipArchive -Path $ChromeDriverArchPath -DestinationPath $ChromeDriverPat
Write-Host "Setting the environment variables..."
[Environment]::SetEnvironmentVariable("ChromeWebDriver", $ChromeDriverPath, "Machine")
$regEnvKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\'
$PathValue = Get-ItemPropertyValue -Path $regEnvKey -Name 'Path'
$PathValue += ";$ChromeDriverPath\"
Set-ItemProperty -Path $regEnvKey -Name 'Path' -Value $PathValue
Add-MachinePathItem $ChromeDriverPath
Update-Environment
Invoke-PesterTests -TestFile "Browsers" -TestName "Chrome"

View File

@@ -6,12 +6,13 @@
################################################################################
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/"
$dockerceBinaries = Invoke-WebRequest -Uri $dockerceUrl -UseBasicParsing
Write-Host "Check Moby version $mobyLatestReleaseVersion"
$mobyRelease = $dockerceBinaries.Links.href -match "${mobyLatestReleaseVersion}\.zip" | Select-Object -Last 1
Write-Host "Check Moby version $mobyLatestVersion"
$mobyRelease = $dockerceBinaries.Links.href -match "${mobyLatestVersion}\.zip" | Select-Object -Last 1
if (-not $mobyRelease) {
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 }
@@ -47,8 +48,7 @@ foreach ($dockerImage in $dockerImages) {
docker pull $dockerImage
if (!$?) {
Write-Host "Docker pull failed with a non-zero exit code"
exit 1
throw "Docker pull failed with a non-zero exit code ($LastExitCode)"
}
}

View File

@@ -4,32 +4,19 @@
## 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"
$dockerCredLatestRelease = Invoke-RestMethod -Uri "https://api.github.com/repos/docker/docker-credential-helpers/releases/latest"
$dockerCredDownloadUrl = $dockerCredLatestRelease.assets.browser_download_url -match "docker-credential-wincred-.+\.exe" | Select-Object -First 1
Invoke-DownloadWithRetry -Url $dockerCredDownloadUrl -Path "C:\Windows\System32\docker-credential-wincred.exe"
$downloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "docker/docker-credential-helpers" `
-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
$distributor_file_hash = Get-DockerWincredHash -Release $dockerCredLatestRelease.name
$local_file_hash = (Get-FileHash -Path 'C:\Windows\System32\docker-credential-wincred.exe' -Algorithm SHA256).Hash
if ($local_file_hash -ne $distributor_file_hash) {
Write-Host "hash must be equal to: ${distributor_file_hash}"
Write-Host "actual hash is: ${local_file_hash}"
throw 'Checksum verification failed, please rerun install'
}
$binaryName = Split-Path $downloadUrl -Leaf
$externalHash = Get-ChecksumFromUrl -Type "SHA256" `
-Url ($downloadUrl -replace $binaryName, "checksums.txt") `
-FileName $binaryName
Test-FileChecksum -Path $binaryPath -ExpectedSHA256Sum $externalHash
#endregion
Invoke-PesterTests -TestFile "Docker" -TestName "DockerWinCred"

View File

@@ -6,23 +6,25 @@
################################################################################
# Set environment variables
[System.Environment]::SetEnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0", "Machine")
[System.Environment]::SetEnvironmentVariable("DOTNET_NOLOGO", "1", "Machine")
[System.Environment]::SetEnvironmentVariable("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "1", "Machine")
[Environment]::SetEnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0", "Machine")
[Environment]::SetEnvironmentVariable("DOTNET_NOLOGO", "1", "Machine")
[Environment]::SetEnvironmentVariable("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "1", "Machine")
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor "Tls12"
#region "Functions"
function Get-SDKVersionsToInstall (
$DotnetVersion
) {
$metadataJsonUri = "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/${DotnetVersion}/releases.json"
$currentReleases = Invoke-DownloadWithRetry $metadataJsonUri | Get-Item | Get-Content | ConvertFrom-Json
function Get-SDKVersionsToInstall {
param (
[Parameter(Mandatory)]
[string] $DotnetVersion
)
$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
$currentReleases = $currentReleases.'releases' | Where-Object { !$_.'release-version'.Contains('-') }
$releases = $releasesData.'releases' | Where-Object { !$_.'release-version'.Contains('-') }
$sdks = @()
foreach ($release in $currentReleases) {
foreach ($release in $releases) {
$sdks += $release.'sdk'
$sdks += $release.'sdks'
}
@@ -33,9 +35,11 @@ function Get-SDKVersionsToInstall (
| ForEach-Object { $_.Group[-1] }
}
function Invoke-Warmup (
$SdkVersion
) {
function Invoke-DotnetWarmup {
param (
[Parameter(Mandatory)]
[string] $SDKVersion
)
# warm up dotnet for first time experience
$projectTypes = @('console', 'mstest', 'web', 'mvc', 'webapi')
$projectTypes | ForEach-Object {
@@ -43,65 +47,58 @@ function Invoke-Warmup (
$projectPath = Join-Path -Path C:\temp -ChildPath $template
New-Item -Path $projectPath -Force -ItemType Directory
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
Pop-Location
Remove-Item $projectPath -Force -Recurse
}
}
function InstallSDKVersion (
$SdkVersion,
$dotnetVersion,
$Warmup
) {
if (!(Test-Path -Path "C:\Program Files\dotnet\sdk\$sdkVersion")) {
Write-Host "Installing dotnet $sdkVersion"
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
.\dotnet-install.ps1 -Version $sdkVersion -InstallDir $(Join-Path -Path $env:ProgramFiles -ChildPath 'dotnet') -ZipPath $ZipPath -KeepZip
function Install-DotnetSDK {
param (
[Parameter(Mandatory)]
[string] $InstallScriptPath,
[Parameter(Mandatory)]
[Alias('Version')]
[string] $SDKVersion,
[Parameter(Mandatory)]
[string] $DotnetVersion
)
if (Test-Path -Path "C:\Program Files\dotnet\sdk\$SDKVersion") {
Write-Host "Sdk version $SDKVersion already installed"
return
}
Write-Host "Installing dotnet $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
$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
Test-FileChecksum $ZipPath -ExpectedSHA512Sum $distributorFileHash
$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
} else {
Write-Host "Sdk version $sdkVersion already installed"
}
#endregion
if ($Warmup) {
Invoke-Warmup -SdkVersion $SdkVersion
}
}
function InstallAllValidSdks() {
# 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.
$installationName = "dotnet-install.ps1"
$installationUrl = "https://dot.net/v1/${installationName}"
Invoke-DownloadWithRetry -Url $installationUrl -Path ".\$installationName"
$installScriptPath = Invoke-DownloadWithRetry -Url "https://dot.net/v1/dotnet-install.ps1"
foreach ($dotnetVersion in $dotnetVersions) {
# Install and warm up dotnet
foreach ($dotnetVersion in $dotnetToolset.versions) {
$sdkVersionsToInstall = Get-SDKVersionsToInstall -DotnetVersion $dotnetVersion
foreach ($sdkVersion in $sdkVersionsToInstall) {
InstallSDKVersion -SdkVersion $sdkVersion -DotnetVersion $dotnetVersion -Warmup $warmup
Install-DotnetSDK -InstallScriptPath $installScriptPath -SDKVersion $sdkVersion -DotnetVersion $dotnetVersion
if ($dotnetToolset.warmup) {
Invoke-DotnetWarmup -SDKVersion $sdkVersion
}
}
}
function InstallTools() {
$dotnetTools = (Get-ToolsetContent).dotnet.tools
foreach ($dotnetTool in $dotnetTools) {
dotnet tool install $($dotnetTool.name) --tool-path "C:\Users\Default\.dotnet\tools" --add-source https://api.nuget.org/v3/index.json | Out-Null
}
}
function RunPostInstallationSteps() {
# Add dotnet to PATH
Add-MachinePathItem "C:\Program Files\dotnet"
@@ -115,13 +112,11 @@ function RunPostInstallationSteps() {
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
# Install dotnet tools
Write-Host "Installing dotnet tools"
Add-DefaultPathItem "%USERPROFILE%\.dotnet\tools"
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
}
#endregion
InstallAllValidSdks
RunPostInstallationSteps
InstallTools
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..."
$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"
$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 `
-Url $installerUrl `
@@ -36,13 +39,14 @@ if (-not (Test-Path -Path $GeckoDriverPath)) {
}
Write-Host "Get the Gecko WebDriver version..."
$GeckoDriverJson = Invoke-RestMethod "https://api.github.com/repos/mozilla/geckodriver/releases/latest"
$GeckoDriverWindowsAsset = $GeckoDriverJson.assets | Where-Object { $_.name -Match "win64" } | Select-Object -First 1
$GeckoDriverVersion = $GeckoDriverJson.tag_name
$GeckoDriverVersion.Substring(1) | Out-File -FilePath "$GeckoDriverPath\versioninfo.txt" -Force;
$GeckoDriverVersion = (Get-GithubReleasesByVersion -Repo "mozilla/geckodriver" -Version "latest").version
$GeckoDriverVersion | Out-File -FilePath "$GeckoDriverPath\versioninfo.txt" -Force
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
Write-Host "Expand Gecko WebDriver archive..."

View File

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

View File

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

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
Invoke-DownloadWithRetry -Url $ghcupDownloadURL -Path "$ghcupPrefix\ghcup\bin\ghcup.exe"
[System.Environment]::SetEnvironmentVariable("GHCUP_INSTALL_BASE_PREFIX", $ghcupPrefix, "Machine")
[System.Environment]::SetEnvironmentVariable("GHCUP_MSYS2", $msysPath, "Machine")
[System.Environment]::SetEnvironmentVariable("CABAL_DIR", $cabalDir, "Machine")
[Environment]::SetEnvironmentVariable("GHCUP_INSTALL_BASE_PREFIX", $ghcupPrefix, "Machine")
[Environment]::SetEnvironmentVariable("GHCUP_MSYS2", $msysPath, "Machine")
[Environment]::SetEnvironmentVariable("CABAL_DIR", $cabalDir, "Machine")
Add-MachinePathItem "$ghcupPrefix\ghcup\bin"
Add-MachinePathItem "$cabalDir\bin"
Update-Environment
@@ -36,8 +36,7 @@ $LatestMajorMinor = $VersionsOutput | Group-Object { $_.ToString(2) } | Sort-Obj
$VersionsList = $LatestMajorMinor | ForEach-Object { $_.Group | Select-Object -Last 1 } | Sort-Object
# The latest version will be installed as a default
ForEach ($version in $VersionsList)
{
foreach ($version in $VersionsList) {
Write-Host "Installing ghc $version..."
ghcup install ghc $version
ghcup set ghc $version

View File

@@ -15,7 +15,7 @@ $driverZipFile = Invoke-DownloadWithRetry $ieDriverUrl
$ieDriverPath = "C:\SeleniumWebDrivers\IEDriver"
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

View File

@@ -39,7 +39,7 @@ function Set-JavaPath {
$newPath = $javaPath + '\bin;' + $newPath
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"
[Environment]::SetEnvironmentVariable("JAVA_HOME", $javaPath, "Machine")
@@ -118,13 +118,13 @@ Install-ChocoPackage maven -ArgumentList "--version=$versionToInstall"
Install-ChocoPackage gradle
# 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'
New-Item -Path $m2_repo -ItemType Directory -Force | Out-Null
$m2RepoPath = 'C:\ProgramData\m2'
New-Item -Path $m2RepoPath -ItemType Directory -Force | Out-Null
[Environment]::SetEnvironmentVariable("M2", $m2, "Machine")
[Environment]::SetEnvironmentVariable("M2_REPO", $m2_repo, "Machine")
[Environment]::SetEnvironmentVariable("M2", $m2Path, "Machine")
[Environment]::SetEnvironmentVariable("M2_REPO", $m2RepoPath, "Machine")
[Environment]::SetEnvironmentVariable("MAVEN_OPTS", "-Xms256m", "Machine")
# Download cobertura jars

View File

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

View File

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

View File

@@ -19,10 +19,7 @@ if (Test-IsWin19) {
}
$packagePath = Invoke-DownloadWithRetry $url
$hash = Get-FileHash -Path $packagePath -Algorithm SHA256
if ($hash.Hash -ne $sha256sum) {
throw "Checksum verification failed for $packagePath"
}
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
@@ -33,7 +30,10 @@ if (Test-IsWin19) {
Add-MachinePathItem "C:\mingw64\bin"
} else {
}
if (Test-IsWin22) {
# If Windows 2022, install version specified in the toolset
$version = (Get-ToolsetContent).mingw.version
$runtime = (Get-ToolsetContent).mingw.runtime

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,8 +3,8 @@ $pgUser = "postgres"
$pgPwd = "root"
# Prepare environment variable for validation
[System.Environment]::SetEnvironmentVariable("PGUSER", $pgUser, "Machine")
[System.Environment]::SetEnvironmentVariable("PGPASSWORD", $pgPwd, "Machine")
[Environment]::SetEnvironmentVariable("PGUSER", $pgUser, "Machine")
[Environment]::SetEnvironmentVariable("PGPASSWORD", $pgPwd, "Machine")
# Define latest available version to install based on version specified in the toolset
$toolsetVersion = (Get-ToolsetContent).postgresql.version
@@ -72,9 +72,9 @@ if ($exitCode -ne 0) {
}
# Added PostgreSQL environment variable
[System.Environment]::SetEnvironmentVariable("PGBIN", $pgBin, "Machine")
[System.Environment]::SetEnvironmentVariable("PGROOT", $pgRoot, "Machine")
[System.Environment]::SetEnvironmentVariable("PGDATA", $pgData, "Machine")
[Environment]::SetEnvironmentVariable("PGBIN", $pgBin, "Machine")
[Environment]::SetEnvironmentVariable("PGROOT", $pgRoot, "Machine")
[Environment]::SetEnvironmentVariable("PGDATA", $pgData, "Machine")
# Stop and disable PostgreSQL service
$pgService = Get-Service -Name postgresql*

View File

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

View File

@@ -16,10 +16,11 @@ try {
$release = $metadata.LTSReleaseTag[0] -replace '^v'
$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"
$expectedSHA256Sum = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*PowerShell-${Release}-win-x64.msi*" }).Split(' ')[0]
Install-Binary -Url $downloadUrl -ExpectedSHA256Sum $expectedSHA256Sum
$installerName = Split-Path $downloadUrl -Leaf
$externalHash = Get-ChecksumFromUrl -Type "SHA256" `
-Url ($downloadUrl -replace $installerName, "hashes.sha256") `
-FileName $installerName
Install-Binary -Url $downloadUrl -ExpectedSHA256Sum $externalHash
} finally {
# Restore original value
[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,
# 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.
[System.Environment]::SetEnvironmentVariable("POWERSHELL_UPDATECHECK", "Off", [System.EnvironmentVariableTarget]::Machine)
[Environment]::SetEnvironmentVariable("POWERSHELL_UPDATECHECK", "Off", "Machine")
Invoke-PesterTests -TestFile "Tools" -TestName "PowerShell Core"

View File

@@ -43,31 +43,17 @@ function Get-CertificatesWithoutPropId {
$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 {
# Serialized Certificate Store File
$sstFile = "$env:TEMP\roots.sst"
# 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) {
Write-Host "[Error]: failed to generate $sstFile sst file`n$result"
exit $LASTEXITCODE
@@ -88,7 +74,9 @@ function Import-SSTFromWU {
}
function Clear-CertificatesPropId {
param([hashtable]$CertsWithoutPropId)
param(
[hashtable] $CertsWithoutPropId
)
# List installed certificates
$certs = Get-ChildItem -Path Cert:\LocalMachine\Root

View File

@@ -3,33 +3,6 @@
## 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
# https://github.com/ruby/setup-ruby/blob/master/windows.js
function Install-Ruby {
@@ -45,16 +18,18 @@ function Install-Ruby {
New-Item -ItemType Directory -Path $rubyToolcachePath | Out-Null
}
# Expand archive with binaries
$packageName = [IO.Path]::GetFileNameWithoutExtension((Split-Path -Path $PackagePath -Leaf))
Write-Host "Expanding Ruby archive $packageName"
$tempFolder = Join-Path -Path $rubyToolcachePath -ChildPath $packageName
Expand-7ZipArchive -Path $PackagePath -DestinationPath $rubyToolcachePath
# Get Ruby version from binaries
$rubyVersion = & "$tempFolder\bin\ruby.exe" -e "print RUBY_VERSION"
if (($LASTEXITCODE -ne 0) -or (-not $rubyVersion)) {
throw "Unable to determine Ruby version. Exit code: $LASTEXITCODE, output: '$rubyVersion'"
}
Write-Host "Ruby version is $rubyVersion"
if ($rubyVersion) {
Write-Host "Installing Ruby $rubyVersion"
$rubyVersionPath = Join-Path -Path $rubyToolcachePath -ChildPath $rubyVersion
$rubyArchPath = Join-Path -Path $rubyVersionPath -ChildPath $Architecture
@@ -69,22 +44,19 @@ function Install-Ruby {
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"
Write-Host "Creating complete file for Ruby $rubyVersion $Architecture"
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
}
}
function Set-DefaultRubyVersion {
param(
[Parameter(Mandatory = $true)]
[System.Version] $Version,
[System.String] $Arch = "x64"
[version] $Version,
[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
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" }
$rubyToolVersions = $rubyTools.versions
# Get Ruby versions from the repo
$rubyLatestMajorVersions = Get-RubyVersions
Write-Host "Starting installation Ruby..."
foreach ($rubyVersion in $rubyToolVersions) {
Write-Host "Starting Ruby $rubyVersion installation"
# Get url for the latest major Ruby version
$url = $rubyLatestMajorVersions[$rubyVersion]
if ($url) {
$tempRubyPackagePath = Invoke-DownloadWithRetry $url
Install-Ruby -PackagePath $tempRubyPackagePath
} else {
Write-Host "Url not found for the '$rubyVersion' version"
exit 1
}
$downloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "oneclick/rubyinstaller2" `
-Version "$rubyVersion*" `
-UrlMatchPattern "*-x64.7z"
$packagePath = Invoke-DownloadWithRetry $downloadUrl
Install-Ruby -PackagePath $packagePath
}
Set-DefaultRubyVersion -Version $rubyTools.default -Arch $rubyTools.arch

View File

@@ -5,10 +5,11 @@
################################################################################
Write-Host "Download latest Runner for GitHub Actions"
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/actions/runner/releases/latest"
$version = $release.tag_name.Trim("v")
$downloadUrl = ($release.assets.browser_download_url -ilike "*actions-runner-win-x64-${version}.zip*") | Select-Object -First 1
$fileName = [System.IO.Path]::GetFileName($downloadUrl)
$downloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "actions/runner" `
-Version "latest" `
-UrlMatchPattern "actions-runner-win-x64-*[0-9.].zip"
$fileName = Split-Path $downloadUrl -Leaf
New-Item -Path "C:\ProgramData\runner" -ItemType Directory
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
$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
# Install Rust by running rustup-init.exe (disabling the confirmation prompt with -y)

View File

@@ -5,19 +5,23 @@
################################################################################
Write-Host "Get the latest Stack version..."
$StackReleasesJson = Invoke-RestMethod "https://api.github.com/repos/commercialhaskell/stack/releases/latest"
$Version = $StackReleasesJson.name.TrimStart("v")
$DownloadFilePattern = "windows-x86_64.zip"
$DownloadUrl = $StackReleasesJson.assets | Where-Object { $_.name.EndsWith($DownloadFilePattern) } | Select-Object -ExpandProperty "browser_download_url" -First 1
$version = (Get-GithubReleasesByVersion -Repo "commercialhaskell/stack" -Version "latest" -WithAssetsOnly).version
$downloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "commercialhaskell/stack" `
-Version $version `
-UrlMatchPattern "stack-*-windows-x86_64.zip"
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"
$StackArchivePath = Invoke-DownloadWithRetry $DownloadUrl
$StackArchivePath = Invoke-DownloadWithRetry $downloadUrl
#region Supply chain security - Stack
$hashUrl = $StackReleasesJson.assets | Where-Object { $_.name.EndsWith("$DownloadFilePattern.sha256") } | Select-Object -ExpandProperty "browser_download_url" -First 1
$externalHash = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*$DownloadFilePattern*" }).Split(' ')[0]
$externalHash = Get-ChecksumFromUrl -Type "SHA256" `
-Url "$downloadUrl.sha256" `
-FileName (Split-Path $downloadUrl -Leaf)
Test-FileChecksum $StackArchivePath -ExpectedSHA256Sum $externalHash
#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) } `
| Select-Object -First 1
if (-not $asset) {
throw "Asset for $($tool.name) $toolVersion $($tool.arch) not found in versions manifest"
}
Write-Host "Installing $($tool.name) $toolVersion $($tool.arch)..."
if ($null -ne $asset) {
Install-Asset -ReleaseAsset $asset
} else {
Write-Host "Asset was not found in versions manifest"
exit 1
}
}
}

View File

@@ -3,16 +3,16 @@
## Desc: Install Visual Studio
################################################################################
$toolset = Get-ToolsetContent
$vsToolset = (Get-ToolsetContent).visualStudio
# Install VS
Install-VisualStudio `
-Version $toolset.visualStudio.subversion `
-Edition $toolset.visualStudio.edition `
-Channel $toolset.visualStudio.channel `
-RequiredComponents $toolset.visualStudio.workloads `
-Version $vsToolset.subversion `
-Edition $vsToolset.edition `
-Channel $vsToolset.channel `
-RequiredComponents $vsToolset.workloads `
-ExtraArgs "--allWorkloads --includeRecommended --remove Component.CPython3.x64" `
-SignatureThumbprint $toolset.visualStudio.signature
-SignatureThumbprint $vsToolset.signature
# Find the version of VS installed for this 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
if ($instanceFolders -is [array]) {
Write-Host "More than one instance installed"
exit 1
throw "More than one instance installed"
}
# Updating content of MachineState.json file to disable autoupdate of VSIX extensions

View File

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

View File

@@ -1,3 +1,8 @@
####################################################################################
## File: Install-WindowsFeatures.ps1
## Desc: Install Windows Features
####################################################################################
$windowsFeatures = (Get-ToolsetContent).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) }
if ( $failedUpdates ) {
Write-Host "Windows updates failed to install: $($failedUpdates.KB)"
exit 1
throw "Windows updates failed to install: $($failedUpdates.KB)"
}
}

View File

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

View File

@@ -5,7 +5,7 @@ function Initialize-RustEnvironment {
}
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 {
@@ -26,75 +26,75 @@ function Get-BashVersion {
}
function Get-RustVersion {
rustc --version | Take-Part -Part 1
rustc --version | Get-StringPart -Part 1
}
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 {
cargo --version | Take-Part -Part 1
cargo --version | Get-StringPart -Part 1
}
function Get-RustdocVersion {
rustdoc --version | Take-Part -Part 1
rustdoc --version | Get-StringPart -Part 1
}
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 {
cargo clippy --version | Take-Part -Part 1
cargo clippy --version | Get-StringPart -Part 1
}
function Get-BindgenVersion {
bindgen --version | Take-Part -Part 1
bindgen --version | Get-StringPart -Part 1
}
function Get-CbindgenVersion {
cbindgen --version | Take-Part -Part 1
cbindgen --version | Get-StringPart -Part 1
}
function Get-CargoAuditVersion {
cargo-audit --version | Take-Part -Part 1
cargo-audit --version | Get-StringPart -Part 1
}
function Get-CargoOutdatedVersion {
cargo outdated --version | Take-Part -Part 1
cargo outdated --version | Get-StringPart -Part 1
}
function Get-PythonVersion {
python --version | Take-Part -Part 1
python --version | Get-StringPart -Part 1
}
function Get-PowershellCoreVersion {
pwsh --version | Take-Part -Part 1
pwsh --version | Get-StringPart -Part 1
}
function Get-RubyVersion {
ruby --version | Take-Part -Part 1
ruby --version | Get-StringPart -Part 1
}
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 {
cmd /c "kotlinc -version 2>&1" | Take-Part -Part 2
cmd /c "kotlinc -version 2>&1" | Get-StringPart -Part 2
}
function Get-PHPVersion {
php --version | Out-String | Take-Part -Part 1
php --version | Out-String | Get-StringPart -Part 1
}
function Get-JuliaVersion {
julia --version | Take-Part -Part 2
julia --version | Get-StringPart -Part 2
}
function Get-LLVMVersion {
(clang --version) -match "clang" | Take-Part -Part 2
(clang --version) -match "clang" | Get-StringPart -Part 2
}
function Get-PerlVersion {
@@ -104,7 +104,7 @@ function Get-PerlVersion {
}
function Get-NodeVersion {
node --version | Take-Part -Part 0 -Delimiter ('v')
node --version | Get-StringPart -Part 0 -Delimiter ('v')
}
function Get-ChocoVersion {
@@ -135,7 +135,7 @@ function Get-HelmVersion {
}
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 {
@@ -144,19 +144,19 @@ function Get-CondaVersion {
}
function Get-ComposerVersion {
composer --version | Take-Part -Part 2
composer --version | Get-StringPart -Part 2
}
function Get-NugetVersion {
(nuget help) -match "Nuget Version" | Take-Part -Part 2
(nuget help) -match "Nuget Version" | Get-StringPart -Part 2
}
function Get-AntVersion {
ant -version | Take-Part -Part 3
ant -version | Get-StringPart -Part 3
}
function Get-MavenVersion {
(mvn -version) -match "Apache Maven" | Take-Part -Part 2
(mvn -version) -match "Apache Maven" | Get-StringPart -Part 2
}
function Get-GradleVersion {
@@ -166,7 +166,7 @@ function Get-GradleVersion {
}
function Get-SbtVersion {
(sbt -version) -match "sbt script" | Take-Part -Part 3
(sbt -version) -match "sbt script" | Get-StringPart -Part 3
}
function Get-DotnetSdks {
@@ -208,7 +208,7 @@ function Get-DotnetRuntimes {
function Get-DotnetFrameworkVersions {
$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 {
@@ -289,7 +289,8 @@ function Get-ShellTarget {
} else {
@($_.Target)[0]
}
}} | Sort-Object Name
}
} | Sort-Object Name
}
function Get-PacmanVersion {
@@ -302,7 +303,7 @@ function Get-PacmanVersion {
}
function Get-YAMLLintVersion {
yamllint --version | Take-Part -Part 1
yamllint --version | Get-StringPart -Part 1
}
function Get-BizTalkVersion {

View File

@@ -17,7 +17,7 @@ function Get-PathWithLink {
return "${inputPath}${link}"
}
function Take-Part {
function Get-StringPart {
param (
[Parameter(ValueFromPipeline)]
[string] $toolOutput,

View File

@@ -66,12 +66,12 @@ function Get-DockerComposeVersionV2 {
}
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
}
function Get-GitVersion {
$gitVersion = git --version | Take-Part -Part -1
$gitVersion = git --version | Get-StringPart -Part -1
return $gitVersion
}

View File

@@ -1,4 +1,25 @@
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()]
param(
[Parameter(Mandatory)]
@@ -30,6 +51,25 @@ function Install-ChocoPackage {
}
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(
[Parameter(Mandatory)]
[string] $PackageName,

View File

@@ -2,43 +2,55 @@
param()
. $PSScriptRoot\AndroidHelpers.ps1
. $PSScriptRoot\ChocoHelpers.ps1
. $PSScriptRoot\InstallHelpers.ps1
. $PSScriptRoot\PathHelpers.ps1
. $PSScriptRoot\VisualStudioHelpers.ps1
Export-ModuleMember -Function @(
'Get-AndroidPackages'
'Get-AndroidPlatformPackages'
'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 @(
'Mount-RegistryHive'
'Dismount-RegistryHive'
'Add-MachinePathItem'
'Add-DefaultPathItem'
'Install-Binary'
)
. $PSScriptRoot\VisualStudioHelpers.ps1
Export-ModuleMember -Function @(
'Install-VisualStudio'
'Get-ToolsetContent'
'Get-TCToolVersionPath'
'Get-TCToolPath'
'Invoke-DownloadWithRetry'
'Get-VisualStudioInstance'
'Get-VisualStudioComponents'
'Get-VsixInfoFromMarketplace'
'Install-VSIXFromFile'
'Install-VSIXFromUrl'
'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 {
<#
.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
(
[Parameter(Mandatory)]
@@ -165,6 +192,11 @@ function Invoke-DownloadWithRetry {
$attemptSeconds = [math]::Round(($(Get-Date) - $attemptStartTime).TotalSeconds, 2)
Write-Warning "Package download failed in $attemptSeconds seconds"
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) {
@@ -180,6 +212,15 @@ function Invoke-DownloadWithRetry {
}
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"
$toolsetJson = Get-Content -Path $toolsetPath -Raw
ConvertFrom-Json -InputObject $toolsetJson
@@ -479,6 +520,10 @@ function Get-GithubReleasesByVersion {
Specifies whether to include prerelease versions in the results. By default,
prerelease versions are excluded.
.PARAMETER WithAssetsOnly
Specifies whether to exclude releases without assets. By default, releases without
assets are included.
.EXAMPLE
Get-GithubReleasesByVersion -Repository "Microsoft/PowerShell" -Version "7.2.0"
@@ -500,7 +545,8 @@ function Get-GithubReleasesByVersion {
[Alias("Repo")]
[string] $Repository,
[string] $Version = "*",
[switch] $AllowPrerelease
[switch] $AllowPrerelease,
[switch] $WithAssetsOnly
)
$localCacheFile = Join-Path ${env:TEMP} "github-releases_$($Repository -replace "/", "_").json"
@@ -528,7 +574,9 @@ function Get-GithubReleasesByVersion {
throw "Failed to get releases from ${Repository}"
}
if ($WithAssetsOnly) {
$releases = $releases.Where{ $_.assets }
}
if (-not $AllowPrerelease) {
$releases = $releases.Where{ $_.prerelease -eq $false }
}
@@ -608,7 +656,8 @@ function Resolve-GithubReleaseAssetUrl {
$matchingReleases = Get-GithubReleasesByVersion `
-Repository $Repository `
-AllowPrerelease:$AllowPrerelease `
-Version $Version
-Version $Version `
-WithAssetsOnly
# Add wildcard to the beginning of the pattern if it's not there
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
foreach ($release in $matchingReleases) {
$matchedVersion = $release.version
$matchedUrl = $release.assets.browser_download_url -like $UrlMatchPattern
$matchedUrl = ([string[]] $release.assets.browser_download_url) -like $UrlMatchPattern
if ($matchedUrl) {
break
}
@@ -638,13 +687,13 @@ function Resolve-GithubReleaseAssetUrl {
return ($matchedUrl -as [string])
}
function Get-GithubReleaseAssetHash {
function Get-ChecksumFromGithubRelease {
<#
.SYNOPSIS
Retrieves the hash value of a specific file from a GitHub release body.
.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
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".
.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.
.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.
#>
@@ -693,7 +742,8 @@ function Get-GithubReleaseAssetHash {
$matchingReleases = Get-GithubReleasesByVersion `
-Repository $Repository `
-AllowPrerelease:$AllowPrerelease `
-Version $Version
-Version $Version `
-WithAssetsOnly
foreach ($release in $matchingReleases) {
$matchedVersion = $release.version
@@ -728,6 +778,70 @@ function Get-GithubReleaseAssetHash {
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 {
<#
.SYNOPSIS

View File

@@ -31,8 +31,7 @@ function Mount-RegistryHive {
$result = reg load $SubKey $FileName *>&1
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to load file $FileName to the key ${SubKey}: $result"
exit 1
throw "Failed to load file $FileName to the key ${SubKey}: $result"
}
}
@@ -92,7 +91,7 @@ function Add-MachinePathItem {
$currentPath = [System.Environment]::GetEnvironmentVariable("PATH", "Machine")
$newPath = $PathItem + ';' + $currentPath
[System.Environment]::SetEnvironmentVariable("PATH", $newPath, "Machine")
[Environment]::SetEnvironmentVariable("PATH", $newPath, "Machine")
}
function Add-DefaultPathItem {

View File

@@ -117,18 +117,65 @@ Function Install-VisualStudio {
}
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
$vsInstance = Get-VSSetupInstance -Prerelease -All | Where-Object { $_.DisplayName -match "Visual Studio" } | Select-Object -First 1
$vsInstance | Select-VSSetupInstance -Product *
}
function Get-VisualStudioComponents {
(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}" }
<#
.SYNOPSIS
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 {
<#
.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
(
[Parameter(Mandatory)]
@@ -183,6 +230,25 @@ function Get-VsixInfoFromMarketplace {
}
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
(
[Parameter(Mandatory = $true)]
@@ -228,6 +294,25 @@ function Install-VSIXFromFile {
}
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
(
[Parameter(Mandatory = $true)]
@@ -241,6 +326,22 @@ function Install-VSIXFromUrl {
}
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
(
[Parameter(Mandatory = $true)]