feature: initial commit for all new image changes

This commit is contained in:
Subir Ghosh
2024-11-13 17:16:01 -07:00
parent de6aa9e70e
commit fcf3d0ac96
1042 changed files with 45086 additions and 1 deletions
@@ -0,0 +1,79 @@
################################################################################
## File: Configure-BaseImage.ps1
## Desc: Prepare the base image for software installation
################################################################################
function Disable-InternetExplorerESC {
$adminKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}"
$userKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}"
Set-ItemProperty -Path $adminKey -Name "IsInstalled" -Value 0 -Force
Set-ItemProperty -Path $userKey -Name "IsInstalled" -Value 0 -Force
$ieProcess = Get-Process -Name Explorer -ErrorAction SilentlyContinue
if ($ieProcess) {
Stop-Process -Name Explorer -Force -ErrorAction Continue
}
Write-Host "IE Enhanced Security Configuration (ESC) has been disabled."
}
function Disable-InternetExplorerWelcomeScreen {
$adminKey = "HKLM:\Software\Policies\Microsoft\Internet Explorer\Main"
New-Item -Path $adminKey -Value 1 -Force
Set-ItemProperty -Path $adminKey -Name "DisableFirstRunCustomize" -Value 1 -Force
Write-Host "Disabled IE Welcome screen"
}
function Disable-UserAccessControl {
Set-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "ConsentPromptBehaviorAdmin" -Value 00000000 -Force
Write-Host "User Access Control (UAC) has been disabled."
}
function Disable-WindowsUpdate {
$autoUpdatePath = "HKLM:SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
if (Test-Path -Path $autoUpdatePath) {
Set-ItemProperty -Path $autoUpdatePath -Name NoAutoUpdate -Value 1
Write-Host "Disabled Windows Update"
} else {
Write-Host "Windows Update key does not exist"
}
}
# Enable $ErrorActionPreference='Stop' for AllUsersAllHosts
Add-Content -Path $profile.AllUsersAllHosts -Value '$ErrorActionPreference="Stop"'
Write-Host "Disable Server Manager on Logon"
Get-ScheduledTask -TaskName ServerManager | Disable-ScheduledTask
Write-Host "Disable 'Allow your PC to be discoverable by other PCs' popup"
New-Item -Path HKLM:\System\CurrentControlSet\Control\Network -Name NewNetworkWindowOff -Force
Write-Host 'Disable Windows Update Medic Service'
Set-ItemProperty -Path HKLM:\System\CurrentControlSet\Services\WaaSMedicSvc -Name Start -Value 4 -Force
Write-Host "Disable Windows Update"
Disable-WindowsUpdate
Write-Host "Disable UAC"
Disable-UserAccessControl
Write-Host "Disable IE Welcome Screen"
Disable-InternetExplorerWelcomeScreen
Write-Host "Disable IE ESC"
Disable-InternetExplorerESC
Write-Host "Setting local execution policy"
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine -ErrorAction Continue | Out-Null
Get-ExecutionPolicy -List
Write-Host "Enable long path behavior"
# See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file#maximum-path-length-limitation
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1
# Expand disk size of OS drive
$driveLetter = "C"
$size = Get-PartitionSupportedSize -DriveLetter $driveLetter
Resize-Partition -DriveLetter $driveLetter -Size $size.SizeMax
Get-Volume | Select-Object DriveLetter, SizeRemaining, Size | Sort-Object DriveLetter
@@ -0,0 +1,13 @@
################################################################################
## File: Configure-DeveloperMode.ps1
## Desc: Enables Developer Mode by toggling registry setting. Developer Mode is required to enable certain tools (e.g. WinAppDriver).
################################################################################
# Create AppModelUnlock if it doesn't exist, required for enabling Developer Mode
$registryKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
if (-not(Test-Path -Path $registryKeyPath)) {
New-Item -Path $registryKeyPath -ItemType Directory -Force
}
# Add registry value to enable Developer Mode
New-ItemProperty -Path $registryKeyPath -Name AllowDevelopmentWithoutDevLicense -PropertyType DWORD -Value 1
@@ -0,0 +1,21 @@
################################################################################
## File: Configure-Diagnostics.ps1
## Desc: Disables Just-In-Time Debugger and Windows Error Reporting
################################################################################
Write-Host "Disable Just-In-Time Debugger"
# Turn off Application Error Debugger
New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug" -Name Debugger -Value "-" -Type String -Force
New-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug" -Name Debugger -Value "-" -Type String -Force
# Turn off the Debug dialog
New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\.NETFramework" -Name DbgManagedDebugger -Value "-" -Type String -Force
New-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\.NETFramework" -Name DbgManagedDebugger -Value "-" -Type String -Force
# Disable the WER UI
New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting" -Name DontShowUI -Value 1 -Type DWORD -Force
# Send all reports to the user's queue
New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting" -Name ForceQueue -Value 1 -Type DWORD -Force
# Default consent choice 1 - Always ask (default)
New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\Consent" -Name DefaultConsent -Value 1 -Type DWORD -Force
@@ -0,0 +1,16 @@
################################################################################
## File: Configure-DotnetSecureChannel.ps1
## Desc: Configure .NET to use TLS 1.2
################################################################################
$registryPath = "HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319"
$name = "SchUseStrongCrypto"
$value = "1"
if (Test-Path $registryPath) {
Set-ItemProperty -Path $registryPath -Name $name -Value $value -Type DWORD
}
$registryPath = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319"
if (Test-Path $registryPath) {
Set-ItemProperty -Path $registryPath -Name $name -Value $value -Type DWORD
}
@@ -0,0 +1,27 @@
################################################################################
## File: Configure-DynamicPort.ps1
## Desc: Configure dynamic port range for TCP and UDP to start at port 49152
## and to end at the 65536 (16384 ports)
################################################################################
# https://support.microsoft.com/en-us/help/929851/the-default-dynamic-port-range-for-tcp-ip-has-changed-in-windows-vista
# The new default start port is 49152, and the new default end port is 65535.
# Default port configuration was changed during image generation by Visual Studio Enterprise Installer to:
# Protocol tcp Dynamic Port Range
# ---------------------------------
# Start Port : 1024
# Number of Ports : 64511
Write-Host "Set the dynamic port range to start at port 49152 and to end at the 65536 (16384 ports)"
foreach ($ipVersion in @("ipv4", "ipv6")) {
foreach ($protocol in @("tcp", "udp")) {
$command = "netsh int $ipVersion set dynamicport $protocol start=49152 num=16384"
Invoke-Expression $command | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Host "Failed to set dynamic port range for $ipVersion $protocol"
exit $LASTEXITCODE
}
}
}
Invoke-PesterTests -TestFile "WindowsFeatures" -TestName "DynamicPorts"
@@ -0,0 +1,14 @@
################################################################################
## File: Configure-GDIProcessHandleQuota.ps1
## Desc: Set the GDIProcessHandleQuota value to 20000
################################################################################
# https://docs.microsoft.com/en-us/windows/win32/sysinfo/gdi-objects
# This value can be set to a number between 256 and 65,536
$defaultValue = 20000
Write-Host "Set the GDIProcessHandleQuota value to $defaultValue"
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name GDIProcessHandleQuota -Value $defaultValue
Set-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Windows" -Name GDIProcessHandleQuota -Value $defaultValue
Invoke-PesterTests -TestFile "WindowsFeatures" -TestName "GDIProcessHandleQuota"
@@ -0,0 +1,50 @@
################################################################################
## File: Configure-ImageDataFile.ps1
## Desc: Creates a JSON file with information about the image
################################################################################
$os = Get-CimInstance -ClassName Win32_OperatingSystem
$caption = $os.Caption
$osName = $caption.Substring(0, $caption.LastIndexOf(" "))
$osEdition = $caption.Substring($caption.LastIndexOf(" ") + 1)
$osVersion = $os.Version
$imageVersion = $env:IMAGE_VERSION
$imageVersionComponents = $imageVersion.Split('.')
$imageMajorVersion = $imageVersionComponents[0]
$imageMinorVersion = $imageVersionComponents[1]
$imageDataFile = $env:IMAGEDATA_FILE
$githubUrl = "https://github.com/actions/runner-images/blob"
if (Test-IsWin25) {
$imageLabel = "windows-2025"
$softwareUrl = "${githubUrl}/win25/$imageMajorVersion.$imageMinorVersion/images/windows/Windows2025-Readme.md"
$releaseUrl = "https://github.com/actions/runner-images/releases/tag/win25%2F$imageMajorVersion.$imageMinorVersion"
} elseif (Test-IsWin22) {
$imageLabel = "windows-2022"
$softwareUrl = "${githubUrl}/win22/$imageMajorVersion.$imageMinorVersion/images/windows/Windows2022-Readme.md"
$releaseUrl = "https://github.com/actions/runner-images/releases/tag/win22%2F$imageMajorVersion.$imageMinorVersion"
} elseif (Test-IsWin19) {
$imageLabel = "windows-2019"
$softwareUrl = "${githubUrl}/win19/$imageMajorVersion.$imageMinorVersion/images/windows/Windows2019-Readme.md"
$releaseUrl = "https://github.com/actions/runner-images/releases/tag/win19%2F$imageMajorVersion.$imageMinorVersion"
} else {
throw "Invalid platform version is found. Either Windows Server 2019 or 2022 are required"
}
$json = @"
[
{
"group": "Operating System",
"detail": "${osName}\n${osVersion}\n${osEdition}"
},
{
"group": "Runner Image",
"detail": "Image: ${imageLabel}\nVersion: ${imageVersion}\nIncluded Software: ${softwareUrl}\nImage Release: ${releaseUrl}"
}
]
"@
$json | Out-File -FilePath $imageDataFile
@@ -0,0 +1,38 @@
################################################################################
## File: Configure-Powershell.ps1
## Desc: Manage PowerShell configuration
################################################################################
#region System
Write-Host "Setup PowerShellGet"
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
# Specifies the installation policy
Set-PSRepository -InstallationPolicy Trusted -Name PSGallery
Write-Host 'Warmup PSModuleAnalysisCachePath (speedup first powershell invocation by 20s)'
$PSModuleAnalysisCachePath = 'C:\PSModuleAnalysisCachePath\ModuleAnalysisCache'
[Environment]::SetEnvironmentVariable('PSModuleAnalysisCachePath', $PSModuleAnalysisCachePath, "Machine")
# make variable to be available in the current session
${env:PSModuleAnalysisCachePath} = $PSModuleAnalysisCachePath
New-Item -Path $PSModuleAnalysisCachePath -ItemType 'File' -Force | Out-Null
#endregion
#region User (current user, image generation only)
if (-not (Test-Path $profile)) {
New-Item $profile -ItemType File -Force
}
@"
if ( -not(Get-Module -ListAvailable -Name PowerHTML)) {
Install-Module PowerHTML -Scope CurrentUser
}
if ( -not(Get-Module -Name PowerHTML)) {
Import-Module PowerHTML
}
"@ | Add-Content -Path $profile -Force
#endregion
@@ -0,0 +1,19 @@
# Create shells folder
$shellPath = "C:\shells"
New-Item -Path $shellPath -ItemType Directory | Out-Null
# add a wrapper for C:\msys64\usr\bin\bash.exe
@'
@echo off
setlocal
IF NOT DEFINED MSYS2_PATH_TYPE set MSYS2_PATH_TYPE=strict
IF NOT DEFINED MSYSTEM set MSYSTEM=mingw64
set CHERE_INVOKING=1
C:\msys64\usr\bin\bash.exe -leo pipefail %*
'@ | Out-File -FilePath "$shellPath\msys2bash.cmd" -Encoding ascii
# gitbash <--> C:\Program Files\Git\bin\bash.exe
New-Item -ItemType SymbolicLink -Path "$shellPath\gitbash.exe" -Target "$env:ProgramFiles\Git\bin\bash.exe" | Out-Null
# wslbash <--> C:\Windows\System32\bash.exe
New-Item -ItemType SymbolicLink -Path "$shellPath\wslbash.exe" -Target "$env:SystemRoot\System32\bash.exe" | Out-Null
@@ -0,0 +1,196 @@
################################################################################
## File: Configure-System.ps1
## Desc: Applies various configuration settings to the final image
################################################################################
Write-Host "Cleanup WinSxS"
dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase
if ($LASTEXITCODE -ne 0) {
throw "Failed to cleanup WinSxS"
}
# Set default version to 1 for WSL (aka LXSS - Linux Subsystem)
# The value should be set in the default user registry hive
# https://github.com/actions/runner-images/issues/5760
if (Test-IsWin22) {
Write-Host "Setting WSL default version to 1"
Mount-RegistryHive `
-FileName "C:\Users\Default\NTUSER.DAT" `
-SubKey "HKLM\DEFAULT"
# Create the key if it doesn't exist
$keyPath = "DEFAULT\Software\Microsoft\Windows\CurrentVersion\Lxss"
if (-not (Test-Path $keyPath)) {
Write-Host "Creating $keyPath key"
New-Item -Path (Join-Path "HKLM:\" $keyPath) -Force | Out-Null
}
# Set the DefaultVersion value to 1
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($keyPath, $true)
$key.SetValue("DefaultVersion", "1", "DWord")
$key.Handle.Close()
[System.GC]::Collect()
Dismount-RegistryHive "HKLM\DEFAULT"
}
Write-Host "Clean up various directories"
@(
"$env:SystemDrive\Recovery",
"$env:SystemRoot\logs",
"$env:SystemRoot\winsxs\manifestcache",
"$env:SystemRoot\Temp",
"$env:SystemDrive\Users\$env:INSTALL_USER\AppData\Local\Temp",
"$env:TEMP",
"$env:AZURE_CONFIG_DIR\logs",
"$env:AZURE_CONFIG_DIR\commands",
"$env:AZURE_CONFIG_DIR\telemetry"
) | ForEach-Object {
if (Test-Path $_) {
Write-Host "Removing $_"
cmd /c "takeown /d Y /R /f $_ 2>&1" | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Failed to take ownership of $_"
}
cmd /c "icacls $_ /grant:r administrators:f /t /c /q 2>&1" | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Failed to grant administrators full control of $_"
}
Remove-Item $_ -Recurse -Force -ErrorAction SilentlyContinue | Out-Null
}
}
$winInstallDir = "$env:SystemRoot\Installer"
New-Item -Path $winInstallDir -ItemType Directory -Force | Out-Null
# Remove AllUsersAllHosts profile
Remove-Item $profile.AllUsersAllHosts -Force -ErrorAction SilentlyContinue | Out-Null
# Clean yarn and npm cache
cmd /c "yarn cache clean 2>&1" | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Failed to clean yarn cache"
}
cmd /c "npm cache clean --force 2>&1" | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Failed to clean npm cache"
}
# allow msi to write to temp folder
# see https://github.com/actions/runner-images/issues/1704
cmd /c "icacls $env:SystemRoot\Temp /grant Users:f /t /c /q 2>&1" | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Failed to grant Users full control of $env:SystemRoot\Temp"
}
# Registry settings
$registrySettings = @(
@{Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"; Name = "AUOptions"; Value = 1; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"; Name = "NoAutoUpdate"; Value = 1; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"; Name = "DoNotConnectToWindowsUpdateInternetLocations"; Value = 1; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"; Name = "DisableWindowsUpdateAccess"; Value = 1; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Device Metadata"; Name = "PreventDeviceMetadataFromNetwork"; Value = 1; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection"; Name = "AllowTelemetry"; Value = 0; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Policies\Microsoft\SQMClient\Windows"; Name = "CEIPEnable"; Value = 0; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\AppCompat"; Name = "AITEnable"; Value = 0; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\AppCompat"; Name = "DisableUAR"; Value = 1; PropertyType = "DWORD" }
@{Path = "HKLM:\Software\Policies\Microsoft\Windows\DataCollection"; Name = "AllowTelemetry"; Value = 0; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\DataCollection"; Name = "AllowTelemetry"; Value = 0; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\Maintenance"; Name = "MaintenanceDisabled"; Value = 1; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Policies\Microsoft\MRT"; Name = "DontOfferThroughWUAU"; Value = 1; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Policies\Microsoft\MRT"; Name = "DontReportInfectionInformation"; Value = 1; PropertyType = "DWORD" }
@{Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search"; Name = "AllowCortana"; Value = 0; PropertyType = "DWORD" }
@{Path = "HKLM:\SYSTEM\CurrentControlSet\Control"; Name = "ServicesPipeTimeout"; Value = 120000; PropertyType = "DWORD" }
@{Path = "HKLM:\SYSTEM\CurrentControlSet\Control\WMI\AutoLogger\AutoLogger-Diagtrack-Listener"; Name = "Start"; Value = 0; PropertyType = "DWORD" }
@{Path = "HKLM:\SYSTEM\CurrentControlSet\Control\WMI\AutoLogger\SQMLogger"; Name = "Start"; Value = 0; PropertyType = "DWORD" }
)
$registrySettings | ForEach-Object {
$regPath = $_.Path
if (-not (Test-Path $regPath)) {
New-Item -Path $regPath -Force -ErrorAction Ignore | Out-Null
}
New-ItemProperty @_ -Force -ErrorAction Ignore
} | Out-Null
# Disable Template Services / User Services added by Desktop Experience
$regUserServicesToDisables = @(
"HKLM:\SYSTEM\CurrentControlSet\Services\CDPUserSvc"
"HKLM:\SYSTEM\CurrentControlSet\Services\OneSyncSvc"
"HKLM:\SYSTEM\CurrentControlSet\Services\PimIndexMaintenanceSvc"
"HKLM:\SYSTEM\CurrentControlSet\Services\UnistoreSvc"
"HKLM:\SYSTEM\CurrentControlSet\Services\UserDataSvc"
)
$regUserServicesToDisables | ForEach-Object {
$regPath = $_
if (-not (Test-Path $regPath)) {
New-Item -Path $regPath -Force -ErrorAction Ignore | Out-Null
}
New-ItemProperty -Path $regPath -Name "Start" -Value 4 -PropertyType DWORD -Force -ErrorAction Ignore
New-ItemProperty -Path $regPath -Name "UserServiceFlags" -Value 0 -PropertyType DWORD -Force -ErrorAction Ignore
} | Out-Null
Write-Host 'Disable Windows Update Service'
Set-ItemProperty -Path HKLM:\System\CurrentControlSet\Services\wuauserv -Name Start -Value 4 -Force
# Disabled services
$servicesToDisable = @(
'wuauserv'
'DiagTrack'
'dmwappushservice'
'PcaSvc'
'SysMain'
'gupdate'
'gupdatem'
'StorSvc'
) | Get-Service -ErrorAction SilentlyContinue
Stop-Service $servicesToDisable
$servicesToDisable.WaitForStatus('Stopped', "00:01:00")
$servicesToDisable | Set-Service -StartupType Disabled
# Disable scheduled tasks
$allTasksInTaskPath = @(
"\"
"\Microsoft\Azure\Security\"
"\Microsoft\VisualStudio\"
"\Microsoft\VisualStudio\Updates\"
"\Microsoft\Windows\Application Experience\"
"\Microsoft\Windows\ApplicationData\"
"\Microsoft\Windows\Autochk\"
"\Microsoft\Windows\Chkdsk\"
"\Microsoft\Windows\Customer Experience Improvement Program\"
"\Microsoft\Windows\Data Integrity Scan\"
"\Microsoft\Windows\Defrag\"
"\Microsoft\Windows\Diagnosis\"
"\Microsoft\Windows\DiskCleanup\"
"\Microsoft\Windows\DiskDiagnostic\"
"\Microsoft\Windows\Maintenance\"
"\Microsoft\Windows\PI\"
"\Microsoft\Windows\Power Efficiency Diagnostics\"
"\Microsoft\Windows\Server Manager\"
"\Microsoft\Windows\Speech\"
"\Microsoft\Windows\UpdateOrchestrator\"
"\Microsoft\Windows\Windows Error Reporting\"
"\Microsoft\Windows\WindowsUpdate\"
"\Microsoft\XblGameSave\"
)
$allTasksInTaskPath | ForEach-Object {
Get-ScheduledTask -TaskPath $_ -ErrorAction Ignore | Disable-ScheduledTask -ErrorAction Ignore
} | Out-Null
$disableTaskNames = @(
@{TaskPath = "\Microsoft\Windows\.NET Framework\"; TaskName = ".NET Framework NGEN v4.0.30319" }
@{TaskPath = "\Microsoft\Windows\.NET Framework\"; TaskName = ".NET Framework NGEN v4.0.30319 64" }
@{TaskPath = "\Microsoft\Windows\AppID\"; TaskName = "SmartScreenSpecific" }
)
$disableTaskNames | ForEach-Object {
Disable-ScheduledTask @PSItem -ErrorAction Ignore
} | Out-Null
Write-Host "Configure-System.ps1 - completed"
@@ -0,0 +1,15 @@
################################################################################
## File: Configure-SystemEnvironment.ps1
## Desc: Configures system environment variables
################################################################################
$variables = @{
"ImageVersion" = $env:IMAGE_VERSION
"ImageOS" = $env:IMAGE_OS
"AGENT_TOOLSDIRECTORY" = $env:AGENT_TOOLSDIRECTORY
"RUNNER_TOOL_CACHE" = $env:AGENT_TOOLSDIRECTORY
}
$variables.GetEnumerator() | ForEach-Object {
[Environment]::SetEnvironmentVariable($_.Key, $_.Value, "Machine")
}
@@ -0,0 +1,60 @@
################################################################################
## File: Configure-Toolset.ps1
## Team: CI-Build
## Desc: Configure Toolset
################################################################################
$toolEnvConfigs = @{
Python = @{
pathTemplates = @(
"{0}"
"{0}\Scripts"
)
}
go = @{
pathTemplates = @(
"{0}\bin"
)
envVarTemplate = "GOROOT_{0}_{1}_X64"
}
}
$tools = Get-ToolsetContent `
| Select-Object -ExpandProperty toolcache `
| Where-Object { $toolEnvConfigs.Keys -contains $_.name }
Write-Host "Configure toolset tools environment..."
foreach ($tool in $tools) {
$toolEnvConfig = $toolEnvConfigs[$tool.name]
if (-not ([string]::IsNullOrEmpty($toolEnvConfig.envVarTemplate))) {
foreach ($version in $tool.versions) {
Write-Host "Set $($tool.name) $version environment variable..."
$foundVersionArchPath = Get-TCToolVersionPath -Name $tool.name -Version $version -Arch $tool.arch
$envName = $toolEnvConfig.envVarTemplate -f $version.Split(".")
Write-Host "Set $envName to $foundVersionArchPath"
[Environment]::SetEnvironmentVariable($envName, $foundVersionArchPath, "Machine")
}
}
if (-not ([string]::IsNullOrEmpty($tool.default))) {
Write-Host "Use $($tool.name) $($tool.default) as a system $($tool.name)..."
$toolVersionPath = Get-TCToolVersionPath -Name $tool.name -Version $tool.default -Arch $tool.arch
foreach ($template in $toolEnvConfig.pathTemplates) {
$toolSystemPath = $template -f $toolVersionPath
Write-Host "Add $toolSystemPath to system PATH..."
Add-MachinePathItem -PathItem $toolSystemPath | Out-Null
}
if (-not ([string]::IsNullOrEmpty($tool.defaultVariable))) {
Write-Host "Set $($tool.name) $($tool.default) $($tool.defaultVariable) environment variable..."
[Environment]::SetEnvironmentVariable($tool.defaultVariable, $toolVersionPath, "Machine")
}
}
}
Invoke-PesterTests -TestFile "Toolset"
@@ -0,0 +1,47 @@
################################################################################
## File: Configure-User.ps1
## Desc: Performs user part of warm up and moves data to C:\Users\Default
################################################################################
#
# more: https://github.com/actions/runner-images-internal/issues/5320
# https://github.com/actions/runner-images/issues/5301#issuecomment-1648292990
#
Write-Host "Warmup 'devenv.exe /updateconfiguration'"
$vsInstallRoot = (Get-VisualStudioInstance).InstallationPath
cmd.exe /c "`"$vsInstallRoot\Common7\IDE\devenv.exe`" /updateconfiguration"
if ($LASTEXITCODE -ne 0) {
throw "Failed to warmup 'devenv.exe /updateconfiguration'"
}
# we are fine if some file is locked and cannot be copied
Copy-Item ${env:USERPROFILE}\AppData\Local\Microsoft\VisualStudio -Destination c:\users\default\AppData\Local\Microsoft\VisualStudio -Recurse -ErrorAction SilentlyContinue
Mount-RegistryHive `
-FileName "C:\Users\Default\NTUSER.DAT" `
-SubKey "HKLM\DEFAULT"
reg.exe copy HKCU\Software\Microsoft\VisualStudio HKLM\DEFAULT\Software\Microsoft\VisualStudio /s
if ($LASTEXITCODE -ne 0) {
throw "Failed to copy HKCU\Software\Microsoft\VisualStudio to HKLM\DEFAULT\Software\Microsoft\VisualStudio"
}
if (-not (Test-IsWin25)) {
# disable TSVNCache.exe
$registryKeyPath = 'HKCU:\Software\TortoiseSVN'
if (-not(Test-Path -Path $registryKeyPath)) {
New-Item -Path $registryKeyPath -ItemType Directory -Force
}
New-ItemProperty -Path $registryKeyPath -Name CacheType -PropertyType DWORD -Value 0
reg.exe copy HKCU\Software\TortoiseSVN HKLM\DEFAULT\Software\TortoiseSVN /s
if ($LASTEXITCODE -ne 0) {
throw "Failed to copy HKCU\Software\TortoiseSVN to HKLM\DEFAULT\Software\TortoiseSVN"
}
}
Dismount-RegistryHive "HKLM\DEFAULT"
Write-Host "Configure-User.ps1 - completed"
@@ -0,0 +1,44 @@
################################################################################
## File: Configure-WindowsDefender.ps1
## Desc: Disables Windows Defender
################################################################################
Write-Host "Disable Windows Defender..."
$avPreference = @(
@{DisableArchiveScanning = $true}
@{DisableAutoExclusions = $true}
@{DisableBehaviorMonitoring = $true}
@{DisableBlockAtFirstSeen = $true}
@{DisableCatchupFullScan = $true}
@{DisableCatchupQuickScan = $true}
@{DisableIntrusionPreventionSystem = $true}
@{DisableIOAVProtection = $true}
@{DisablePrivacyMode = $true}
@{DisableScanningNetworkFiles = $true}
@{DisableScriptScanning = $true}
@{MAPSReporting = 0}
@{PUAProtection = 0}
@{SignatureDisableUpdateOnStartupWithoutEngine = $true}
@{SubmitSamplesConsent = 2}
@{ScanAvgCPULoadFactor = 5; ExclusionPath = @("D:\", "C:\")}
@{DisableRealtimeMonitoring = $true}
@{ScanScheduleDay = 8}
)
$avPreference += @(
@{EnableControlledFolderAccess = "Disable"}
@{EnableNetworkProtection = "Disabled"}
)
$avPreference | Foreach-Object {
$avParams = $_
Set-MpPreference @avParams
}
# https://github.com/actions/runner-images/issues/4277
# https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/microsoft-defender-antivirus-compatibility?view=o365-worldwide
$atpRegPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows Advanced Threat Protection'
if (Test-Path $atpRegPath) {
Write-Host "Set Microsoft Defender Antivirus to passive mode"
Set-ItemProperty -Path $atpRegPath -Name 'ForceDefenderPassiveMode' -Value '1' -Type 'DWORD'
}
@@ -0,0 +1,32 @@
################################################################################
## File: Install-AWSTools.ps1
## Desc: Install AWS tools: CLI, Session Manager Plugin, AWS SAM CLI
## Supply chain security: AWS CLI - managed by package manager, Session Manager Plugin for the AWS CLI - missing, AWS SAM CLI - checksum validation
################################################################################
# Install AWS CLI
Install-ChocoPackage awscli
# Install Session Manager Plugin for the AWS CLI
Install-Binary `
-Url "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/windows/SessionManagerPluginSetup.exe" `
-InstallArgs ("/silent", "/install") `
-ExpectedSignature "75A5FB4D02FCB2AB799718F315BAAA3103E9D60C"
$env:Path = $env:Path + ";$env:ProgramFiles\Amazon\SessionManagerPlugin\bin"
# Install AWS SAM CLI
$downloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "awslabs/aws-sam-cli" `
-Version "latest" `
-UrlMatchPattern "AWS_SAM_CLI_64_PY3.msi"
$externalHash = Get-ChecksumFromGithubRelease `
-Repo "awslabs/aws-sam-cli" `
-Version "latest" `
-FileName (Split-Path $downloadUrl -Leaf) `
-HashType "SHA256"
Install-Binary `
-Url $downloadUrl `
-ExpectedSHA256Sum $externalHash
Invoke-PesterTests -TestFile "CLI.Tools" -TestName "AWS"
@@ -0,0 +1,27 @@
################################################################################
## File: Install-ActionsCache.ps1
## Desc: Downloads latest release from https://github.com/actions/action-versions
## Maintainer: #actions-runtime and @TingluoHuang
################################################################################
$actionArchiveCache = "C:\actionarchivecache\"
if (-not (Test-Path $actionArchiveCache)) {
Write-Host "Creating action archive cache folder"
New-Item -ItemType Directory -Path $actionArchiveCache | Out-Null
}
$downloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "actions/action-versions" `
-Version "latest" `
-Asset "action-versions.zip"
Write-Host "Download Latest action-versions archive from $downloadUrl"
$actionVersionsArchivePath = Invoke-DownloadWithRetry $downloadUrl
Write-Host "Expand action-versions archive"
Expand-7ZipArchive -Path $actionVersionsArchivePath -DestinationPath $actionArchiveCache
[Environment]::SetEnvironmentVariable("ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE", $actionArchiveCache, "Machine")
Invoke-PesterTests -TestFile "ActionArchiveCache"
@@ -0,0 +1,30 @@
################################################################################
## File: Install-AliyunCli.ps1
## Desc: Install Alibaba Cloud CLI
## Supply chain security: Alibaba Cloud CLI - checksum validation
################################################################################
Write-Host "Download Latest aliyun-cli archive"
$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
$packageName = Split-Path $downloadUrl -Leaf
$externalHash = Get-ChecksumFromUrl -Type "SHA256" `
-Url ($downloadUrl -replace $packageName, "SHASUMS256.txt") `
-FileName $packageName
Test-FileChecksum $packagePath -ExpectedSHA256Sum $externalHash
#endregion
Write-Host "Expand aliyun-cli archive"
$aliyunPath = "C:\aliyun-cli"
New-Item -Path $aliyunPath -ItemType Directory -Force
Expand-7ZipArchive -Path $packagePath -DestinationPath $aliyunPath
# Add aliyun-cli to path
Add-MachinePathItem $aliyunPath
Invoke-PesterTests -TestFile "CLI.Tools" -TestName "Aliyun CLI"
@@ -0,0 +1,166 @@
################################################################################
## File: Install-AndroidSDK.ps1
## Desc: Install and update Android SDK and tools
## Supply chain security: checksum validation
################################################################################
# Actual Android SDK installation directory
$SDKInstallRoot = "C:\Program Files (x86)\Android\android-sdk"
# Hardlink to the Android SDK installation directory with no spaces in the path.
# ANDROID_NDK* env vars should not contain spaces, otherwise ndk-build.cmd gives an error
# https://github.com/actions/runner-images/issues/1122
$SDKRootPath = "C:\Android\android-sdk"
#region functions
function Install-AndroidSDKPackages {
<#
.SYNOPSIS
This function installs the specified Android SDK packages.
.DESCRIPTION
The Install-AndroidSDKPackages function takes an array of package names as a parameter and installs each of them using the sdkmanager.bat script.
.PARAMETER Packages
An array of package names in the format of SDK-style paths to be installed.
.EXAMPLE
Install-AndroidSDKPackages -Packages "platforms;android-29", "build-tools;29.0.2"
This command installs the Android SDK Platform 29 and Build-Tools 29.0.2.
#>
Param
(
[Parameter(Mandatory = $true)]
[AllowEmptyCollection()]
[AllowNull()]
[string[]] $Packages
)
# The sdkmanager.bat script is used to install Android SDK packages.
$SDKManager = "$SDKRootPath\cmdline-tools\latest\bin\sdkmanager.bat"
$errors = @()
foreach ($package in $Packages) {
& $SDKManager --install "$package" --sdk_root=$SDKRootPath
if ($LASTEXITCODE -ne 0) {
$errors += "Failed to install package $package with exit code $LASTEXITCODE"
}
}
if ($errors.Count -gt 0) {
throw $errors
}
}
#endregion
# get packages to install from the toolset
$androidToolset = (Get-ToolsetContent).android
# Newer version(s) require Java 11 by default
# See https://github.com/actions/runner-images/issues/6960
$cmdlineToolsUrl = $androidToolset.commandline_tools_url
$cmdlineToolsArchPath = Invoke-DownloadWithRetry $cmdlineToolsUrl
Test-FileChecksum $cmdlineToolsArchPath -ExpectedSHA256Sum $androidToolset.hash
Expand-7ZipArchive -Path $cmdlineToolsArchPath -DestinationPath "${SDKInstallRoot}\cmdline-tools"
# cmdline tools should be installed in ${SDKInstallRoot}\cmdline-tools\latest\bin, but archive contains ${SDKInstallRoot}\cmdline-tools\bin
# we need to create the proper folder structure
Invoke-ScriptBlockWithRetry -Command {
Rename-Item "${SDKInstallRoot}\cmdline-tools\cmdline-tools" "latest" -ErrorAction Stop
}
# Create hardlink at $SDKRootPath pointing to SDK installation directory in Program Files
New-Item -Path (Split-Path $SDKRootPath -Parent) -ItemType Directory -Force
New-Item -Path "$SDKRootPath" -ItemType SymbolicLink -Value "$SDKInstallRoot"
# Install the standard Android SDK licenses. Currently, there isn't a better way to do this,
# so we are base64-encoded a zip of the licenses directory from another installation.
# To create this base64 string, create a zip file that contains nothing but a 'licenses' folder,
# which folder contains the accepted license files found in 'C:\Program Files (x86)\Android\android-sdk\licenses'.
# Then, run this in PowerShell:
# $LicensesZipFileName = 'C:\Program Files (x86)\Android\android-sdk\Licenses.zip'
# $base64Content = [Convert]::ToBase64String([IO.File]::ReadAllBytes($LicensesZipFileName))
# echo $base64Content
# Another possible solution that works in powershell core:
# Write-Ouptut "y" | $sdkmanager.bat <packagename>
$licenseContentBase64 = "UEsDBBQAAAAAAKNK11IAAAAAAAAAAAAAAAAJAAAAbGljZW5zZXMvUEsDBAoAAAAAAJ1K11K7n0IrKgAAACoAAAAhAAAAbGljZW5zZXMvYW5kcm9pZC1nb29nbGV0di1saWNlbnNlDQo2MDEwODViOTRjZDc3ZjBiNTRmZjg2NDA2OTU3MDk5ZWJlNzljNGQ2UEsDBAoAAAAAAKBK11LzQumJKgAAACoAAAAkAAAAbGljZW5zZXMvYW5kcm9pZC1zZGstYXJtLWRidC1saWNlbnNlDQo4NTlmMzE3Njk2ZjY3ZWYzZDdmMzBhNTBhNTU2MGU3ODM0YjQzOTAzUEsDBAoAAAAAAKFK11IKSOJFKgAAACoAAAAcAAAAbGljZW5zZXMvYW5kcm9pZC1zZGstbGljZW5zZQ0KMjQzMzNmOGE2M2I2ODI1ZWE5YzU1MTRmODNjMjgyOWIwMDRkMWZlZVBLAwQKAAAAAACiStdSec1a4SoAAAAqAAAAJAAAAGxpY2Vuc2VzL2FuZHJvaWQtc2RrLXByZXZpZXctbGljZW5zZQ0KODQ4MzFiOTQwOTY0NmE5MThlMzA1NzNiYWI0YzljOTEzNDZkOGFiZFBLAwQKAAAAAACiStdSk6vQKCoAAAAqAAAAGwAAAGxpY2Vuc2VzL2dvb2dsZS1nZGstbGljZW5zZQ0KMzNiNmEyYjY0NjA3ZjExYjc1OWYzMjBlZjlkZmY0YWU1YzQ3ZDk3YVBLAwQKAAAAAACiStdSrE3jESoAAAAqAAAAJAAAAGxpY2Vuc2VzL2ludGVsLWFuZHJvaWQtZXh0cmEtbGljZW5zZQ0KZDk3NWY3NTE2OThhNzdiNjYyZjEyNTRkZGJlZWQzOTAxZTk3NmY1YVBLAwQKAAAAAACjStdSkb1vWioAAAAqAAAAJgAAAGxpY2Vuc2VzL21pcHMtYW5kcm9pZC1zeXNpbWFnZS1saWNlbnNlDQplOWFjYWI1YjVmYmI1NjBhNzJjZmFlY2NlODk0Njg5NmZmNmFhYjlkUEsBAj8AFAAAAAAAo0rXUgAAAAAAAAAAAAAAAAkAJAAAAAAAAAAQAAAAAAAAAGxpY2Vuc2VzLwoAIAAAAAAAAQAYACIHOBcRaNcBIgc4FxFo1wHBTVQTEWjXAVBLAQI/AAoAAAAAAJ1K11K7n0IrKgAAACoAAAAhACQAAAAAAAAAIAAAACcAAABsaWNlbnNlcy9hbmRyb2lkLWdvb2dsZXR2LWxpY2Vuc2UKACAAAAAAAAEAGACUEFUTEWjXAZQQVRMRaNcB6XRUExFo1wFQSwECPwAKAAAAAACgStdS80LpiSoAAAAqAAAAJAAkAAAAAAAAACAAAACQAAAAbGljZW5zZXMvYW5kcm9pZC1zZGstYXJtLWRidC1saWNlbnNlCgAgAAAAAAABABgAsEM0FBFo1wGwQzQUEWjXAXb1MxQRaNcBUEsBAj8ACgAAAAAAoUrXUgpI4kUqAAAAKgAAABwAJAAAAAAAAAAgAAAA/AAAAGxpY2Vuc2VzL2FuZHJvaWQtc2RrLWxpY2Vuc2UKACAAAAAAAAEAGAAsMGUVEWjXASwwZRURaNcB5whlFRFo1wFQSwECPwAKAAAAAACiStdSec1a4SoAAAAqAAAAJAAkAAAAAAAAACAAAABgAQAAbGljZW5zZXMvYW5kcm9pZC1zZGstcHJldmlldy1saWNlbnNlCgAgAAAAAAABABgA7s3WFRFo1wHuzdYVEWjXAfGm1hURaNcBUEsBAj8ACgAAAAAAokrXUpOr0CgqAAAAKgAAABsAJAAAAAAAAAAgAAAAzAEAAGxpY2Vuc2VzL2dvb2dsZS1nZGstbGljZW5zZQoAIAAAAAAAAQAYAGRDRxYRaNcBZENHFhFo1wFfHEcWEWjXAVBLAQI/AAoAAAAAAKJK11KsTeMRKgAAACoAAAAkACQAAAAAAAAAIAAAAC8CAABsaWNlbnNlcy9pbnRlbC1hbmRyb2lkLWV4dHJhLWxpY2Vuc2UKACAAAAAAAAEAGADGsq0WEWjXAcayrRYRaNcBxrKtFhFo1wFQSwECPwAKAAAAAACjStdSkb1vWioAAAAqAAAAJgAkAAAAAAAAACAAAACbAgAAbGljZW5zZXMvbWlwcy1hbmRyb2lkLXN5c2ltYWdlLWxpY2Vuc2UKACAAAAAAAAEAGAA4LjgXEWjXATguOBcRaNcBIgc4FxFo1wFQSwUGAAAAAAgACACDAwAACQMAAAAA"
$licenseContent = [System.Convert]::FromBase64String($licenseContentBase64)
Set-Content -Path "$SDKInstallRoot\android-sdk-licenses.zip" -Value $licenseContent -Encoding Byte
Expand-7ZipArchive -Path "$SDKInstallRoot\android-sdk-licenses.zip" -DestinationPath $SDKInstallRoot
# Install platform-tools
$platformToolsPath = Join-Path -Path $SDKInstallRoot -ChildPath "platform-tools"
if (Test-Path $platformToolsPath) {
Write-Host "Removing previous platform-tools installation from Visual Studio component"
Remove-Item $platformToolsPath -Recurse -Force
}
Install-AndroidSDKPackages "platform-tools"
# Get Android SDK packages list
$androidPackages = Get-AndroidPackages -SDKRootPath $SDKRootPath
# Install Android platform versions
# that are greater than or equal to the minimum version
Write-Host "Installing Android SDK packages for platforms..."
$platformList = Get-AndroidPlatformPackages `
-SDKRootPath $SDKRootPath `
-minVersion $androidToolset.platform_min_version
Install-AndroidSDKPackages $platformList
# Install Android build-tools versions
# that are greater than or equal to the minimum version
Write-Host "Installing Android SDK packages for build tools..."
$buildToolsList = Get-AndroidBuildToolPackages `
-SDKRootPath $SDKRootPath `
-minVersion $androidToolset.build_tools_min_version
Install-AndroidSDKPackages $buildToolsList
# Install Android Emulator
Install-AndroidSDKPackages "emulator"
# Install extras, add-ons and additional tools
Write-Host "Installing Android SDK extras, add-ons and additional tools..."
Install-AndroidSDKPackages ($androidToolset.extras | ForEach-Object { "extras;$_" })
Install-AndroidSDKPackages ($androidToolset.addons | ForEach-Object { "add-ons;$_" })
Install-AndroidSDKPackages ($androidToolset.additional_tools)
# Install NDKs
$ndkMajorVersions = $androidToolset.ndk.versions
$ndkDefaultMajorVersion = $androidToolset.ndk.default
$ndkLatestMajorVersion = $ndkMajorVersions | Select-Object -Last 1
$androidNDKs = @()
foreach ($version in $ndkMajorVersions) {
$packageNamePrefix = "ndk;$version"
$package = $androidPackages | Where-Object { $_.StartsWith($packageNamePrefix) } | Sort-Object -Unique | Select-Object -Last 1
$androidNDKs += $package
}
Write-Host "Installing Android SDK packages for NDKs..."
Install-AndroidSDKPackages $androidNDKs
$ndkLatestVersion = ($androidNDKs | Where-Object { $_ -match "ndk;$ndkLatestMajorVersion" }).Split(';')[1]
$ndkDefaultVersion = ($androidNDKs | Where-Object { $_ -match "ndk;$ndkDefaultMajorVersion" }).Split(';')[1]
$ndkRoot = "$SDKRootPath\ndk\$ndkDefaultVersion"
# Create env variables
[Environment]::SetEnvironmentVariable("ANDROID_HOME", $SDKRootPath, "Machine")
[Environment]::SetEnvironmentVariable("ANDROID_SDK_ROOT", $SDKRootPath, "Machine")
# ANDROID_NDK, ANDROID_NDK_HOME, and ANDROID_NDK_ROOT variables should be set as many customer builds depend on them https://github.com/actions/runner-images/issues/5879
[Environment]::SetEnvironmentVariable("ANDROID_NDK", $ndkRoot, "Machine")
[Environment]::SetEnvironmentVariable("ANDROID_NDK_HOME", $ndkRoot, "Machine")
[Environment]::SetEnvironmentVariable("ANDROID_NDK_ROOT", $ndkRoot, "Machine")
$ndkLatestPath = "$SDKRootPath\ndk\$ndkLatestVersion"
if (Test-Path $ndkLatestPath) {
[Environment]::SetEnvironmentVariable("ANDROID_NDK_LATEST_HOME", $ndkLatestPath, "Machine")
} else {
Write-Host "Latest NDK $ndkLatestVersion is not installed at path $ndkLatestPath"
exit 1
}
Invoke-PesterTests -TestFile "Android"
@@ -0,0 +1,23 @@
################################################################################
## File: Install-Apache.ps1
## Desc: Install Apache HTTP Server
################################################################################
# Stop w3svc service
# commented below code w3svc service is not present in 2025
Stop-Service -Name w3svc
# Install latest apache in chocolatey
$installDir = "C:\tools"
Install-ChocoPackage apache-httpd -ArgumentList "--force", "--params", "/installLocation:$installDir /port:80"
# Stop and disable Apache service
Stop-Service -Name Apache
Set-Service -Name Apache -StartupType Disabled
# Start w3svc service
# commented below code w3svc service is not present in 2025
Start-Service -Name w3svc
# Invoke Pester Tests
Invoke-PesterTests -TestFile "Apache"
@@ -0,0 +1,29 @@
################################################################################
## File: Install-AzureCli.ps1
## Desc: Install and warm-up Azure CLI
################################################################################
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, "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 '245D262748012A4FE6CE8BA6C951A4C4AFBC3E5D' #'F9A7CF9FBE13BAC767F4781061332DA6E8B4E0EE'
Update-Environment
# Warm-up Azure CLI
Write-Host "Warmup 'az'"
az --help | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Command 'az --help' failed"
}
Invoke-PesterTests -TestFile 'CLI.Tools' -TestName 'Azure CLI'
@@ -0,0 +1,10 @@
####################################################################################
## File: Install-AzureCosmosDbEmulator.ps1
## Desc: Install Azure CosmosDb Emulator
####################################################################################
Install-Binary -Type MSI `
-Url "https://aka.ms/cosmosdb-emulator" `
-ExpectedSHA256Sum "DB9D5E496C5FDAE17C12C03385D2BAC973DA61C280023D9FDC9A6020220BEE41"
Invoke-PesterTests -TestFile "Tools" -TestName "Azure Cosmos DB Emulator"
@@ -0,0 +1,35 @@
################################################################################
## File: Install-AzureDevOpsCli.ps1
## Desc: Install Azure DevOps CLI
################################################################################
$azureDevOpsCliConfigPath = 'C:\azureDevOpsCli'
# Store azure-devops-cli cache outside of the provisioning user's profile
[Environment]::SetEnvironmentVariable('AZ_DEVOPS_GLOBAL_CONFIG_DIR', $azureDevOpsCliConfigPath, "Machine")
$azureDevOpsCliCachePath = Join-Path $azureDevOpsCliConfigPath 'cache'
New-Item -ItemType 'Directory' -Path $azureDevOpsCliCachePath | Out-Null
[Environment]::SetEnvironmentVariable('AZURE_DEVOPS_CACHE_DIR', $azureDevOpsCliCachePath, "Machine")
Update-Environment
az extension add -n azure-devops
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) {
throw "Command 'az $_ --help' failed"
}
}
# calling az devops login to force it to install `keyring`. Login will actually fail, redirecting error to null
Write-Output 'fake token' | az devops login | Out-Null
# calling az devops logout to be sure no credentials remain.
az devops logout | out-null
Invoke-PesterTests -TestFile 'CLI.Tools' -TestName 'Azure DevOps CLI'
@@ -0,0 +1,13 @@
################################################################################
## File: Install-Bazel.ps1
## Desc: Install Bazel and Bazelisk (A user-friendly launcher for Bazel)
################################################################################
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"
@@ -0,0 +1,28 @@
################################################################################
## File: Install-BizTalkBuildComponent.ps1
## Desc: Install BizTalk Project Build Component
################################################################################
$downloadUrl = "https://aka.ms/BuildComponentSetup.EN"
$signatureThumbprint = "8740DF4ACB749640AD318E4BE842F72EC651AD80"
Write-Host "Downloading BizTalk Project Build Component archive..."
$zipFile = Invoke-DownloadWithRetry $downloadUrl
$setupPath = Join-Path $env:TEMP "BizTalkBuildComponent"
if (-not (Test-Path -Path $setupPath)) {
New-Item -Path $setupPath -ItemType Directory -Force | Out-Null
}
Expand-7ZipArchive -Path $zipFile -DestinationPath $setupPath
Write-Host "Installing BizTalk Project Build Component..."
Install-Binary `
-LocalPath "$setupPath\Bootstrap.msi" `
-ExtraInstallArgs ("/l*v", "$setupPath\bootstrap.log") `
-ExpectedSignature $signatureThumbprint
Install-Binary `
-LocalPath "$setupPath\BuildComponentSetup.msi" `
-ExtraInstallArgs ("/l*v", "$setupPath\buildComponentSetup.log") `
-ExpectedSignature $signatureThumbprint
Invoke-PesterTests -TestFile "BizTalk" -TestName "BizTalk Build Component Setup"
@@ -0,0 +1,26 @@
################################################################################
## File: Install-Chocolatey.ps1
## Desc: Install Chocolatey package manager
################################################################################
Write-Host "Set TLS1.2"
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor "Tls12"
Write-Host "Install chocolatey"
# Add to system PATH
Add-MachinePathItem 'C:\ProgramData\Chocolatey\bin'
Update-Environment
# Verify and run choco installer
$signatureThumbprint = "B009C875F4E10FFBC62B785BAF4FC4D6BC2D5711"
$installScriptPath = Invoke-DownloadWithRetry 'https://chocolatey.org/install.ps1'
Test-FileSignature -Path $installScriptPath -ExpectedThumbprint $signatureThumbprint
Invoke-Expression $installScriptPath
# Turn off confirmation
choco feature enable -n allowGlobalConfirmation
# Initialize environmental variable ChocolateyToolsLocation by invoking choco Get-ToolsLocation function
Import-Module "$env:ChocolateyInstall\helpers\chocolateyInstaller.psm1" -Force
Get-ToolsLocation
@@ -0,0 +1,12 @@
################################################################################
## File: Install-ChocolateyPackages.ps1
## Desc: Install common Chocolatey packages
################################################################################
$commonPackages = (Get-ToolsetContent).choco.common_packages
foreach ($package in $commonPackages) {
Install-ChocoPackage $package.name -ArgumentList $package.args
}
Invoke-PesterTests -TestFile "ChocoPackages"
@@ -0,0 +1,82 @@
################################################################################
## File: Install-Chrome.ps1
## Desc: Install Google Chrome browser and Chrome WebDriver
################################################################################
# Download and install latest Chrome browser
Install-Binary `
-Url 'https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise64.msi' `
-ExpectedSignature '607A3EDAA64933E94422FC8F0C80388E0590986C'
# Prepare firewall rules
Write-Host "Adding the firewall rule for Google update blocking..."
New-NetFirewallRule -DisplayName "BlockGoogleUpdate" -Direction Outbound -Action Block -Program "C:\Program Files (x86)\Google\Update\GoogleUpdate.exe"
$googleServices = Get-Service -Name "GoogleUpdater*"
Stop-Service $googleServices
$googleServices.WaitForStatus('Stopped', "00:01:00")
$googleServices | Set-Service -StartupType Disabled
$regGoogleUpdatePath = "HKLM:\SOFTWARE\Policies\Google\Update"
$regGoogleUpdateChrome = "HKLM:\SOFTWARE\Policies\Google\Chrome"
($regGoogleUpdatePath, $regGoogleUpdateChrome) | ForEach-Object {
New-Item -Path $_ -Force
}
$regGoogleParameters = @(
@{ Name = "AutoUpdateCheckPeriodMinutes"; Value = 00000000},
@{ Name = "UpdateDefault"; Value = 00000000 },
@{ Name = "DisableAutoUpdateChecksCheckboxValue"; Value = 00000001 },
@{ Name = "Update{8A69D345-D564-463C-AFF1-A69D9E530F96}"; Value = 00000000 },
@{ Path = $regGoogleUpdateChrome; Name = "DefaultBrowserSettingEnabled"; Value = 00000000 }
)
$regGoogleParameters | ForEach-Object {
$arguments = $_
if (-not ($arguments.Path)) {
$arguments.Add("Path", $regGoogleUpdatePath)
}
$arguments.Add("Force", $true)
New-ItemProperty @arguments
}
# Install Chrome WebDriver
Write-Host "Install Chrome WebDriver..."
$chromeDriverPath = "$($env:SystemDrive)\SeleniumWebDrivers\ChromeDriver"
if (-not (Test-Path -Path $chromeDriverPath)) {
New-Item -Path $chromeDriverPath -ItemType Directory -Force
}
Write-Host "Get the Chrome WebDriver download URL..."
$registryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths"
$chromePath = (Get-ItemProperty "$registryPath\chrome.exe").'(default)'
[version] $chromeVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($chromePath).ProductVersion
$chromeBuild = "$($chromeVersion.Major).$($chromeVersion.Minor).$($chromeVersion.Build)"
$chromeDriverVersionsUrl = "https://googlechromelabs.github.io/chrome-for-testing/latest-patch-versions-per-build-with-downloads.json"
Write-Host "Chrome version is $chromeVersion"
$chromeDriverVersions = Invoke-RestMethod -Uri $chromeDriverVersionsUrl
$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"
}
$chromeDriverVersion.version | Out-File -FilePath "$chromeDriverPath\versioninfo.txt" -Force;
Write-Host "Chrome WebDriver version to install is $($chromeDriverVersion.version)"
$chromeDriverZipDownloadUrl = ($chromeDriverVersion.downloads.chromedriver | Where-Object platform -eq "win64").url
Write-Host "Download Chrome WebDriver from $chromeDriverZipDownloadUrl..."
$chromeDriverArchPath = Invoke-DownloadWithRetry $chromeDriverZipDownloadUrl
Write-Host "Expand Chrome WebDriver archive (without using directory names)..."
Expand-7ZipArchive -Path $chromeDriverArchPath -DestinationPath $chromeDriverPath -ExtractMethod "e"
Write-Host "Setting the environment variables..."
[Environment]::SetEnvironmentVariable("ChromeWebDriver", $chromeDriverPath, "Machine")
Add-MachinePathItem $chromeDriverPath
Update-Environment
Invoke-PesterTests -TestFile "Browsers" -TestName "Chrome"
@@ -0,0 +1,26 @@
################################################################################
## File: Install-CloudFoundryCli.ps1
## Desc: Install Cloud Foundry CLI
################################################################################
# Download the latest cf cli exe
$cloudFoundryCliUrl = "https://packages.cloudfoundry.org/stable?release=windows64-exe&source=github"
$cloudFoundryArchPath = Invoke-DownloadWithRetry $cloudFoundryCliUrl
# Create directory for cf cli
$cloudFoundryCliPath = "C:\cf-cli"
New-Item -Path $cloudFoundryCliPath -ItemType Directory -Force
# Extract the zip archive
Write-Host "Extracting cf cli..."
Expand-7ZipArchive -Path $cloudFoundryArchPath -DestinationPath $cloudFoundryCliPath
# Add cf to path
Add-MachinePathItem $cloudFoundryCliPath
# Validate cf signature
$cloudFoundrySignatureThumbprint = "2C6B2F1562698503A6E4A25F2DF058E12E23A190"
Test-FileSignature -Path "$cloudFoundryCliPath\cf.exe" -ExpectedThumbprint $cloudFoundrySignatureThumbprint
Invoke-PesterTests -TestFile "CLI.Tools" -TestName "CloudFoundry CLI"
@@ -0,0 +1,36 @@
################################################################################
## File: Install-CodeQLBundle.ps1
## Desc: Install the CodeQL CLI Bundle to the toolcache.
################################################################################
# Retrieve the CLI version of the latest CodeQL bundle.
$defaults = (Invoke-RestMethod "https://raw.githubusercontent.com/github/codeql-action/v2/src/defaults.json")
$cliVersion = $defaults.cliVersion
$tagName = "codeql-bundle-v" + $cliVersion
Write-Host "Downloading CodeQL bundle $($cliVersion)..."
# Note that this is the all-platforms CodeQL bundle, to support scenarios where customers run
# different operating systems within containers.
$codeQLBundlePath = Invoke-DownloadWithRetry "https://github.com/github/codeql-action/releases/download/$($tagName)/codeql-bundle.tar.gz"
$downloadDirectoryPath = (Get-Item $codeQLBundlePath).Directory.FullName
$codeQLToolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY -ChildPath "CodeQL" | Join-Path -ChildPath $cliVersion | Join-Path -ChildPath "x64"
New-Item -Path $codeQLToolcachePath -ItemType Directory -Force | Out-Null
Write-Host "Unpacking the downloaded CodeQL bundle archive..."
Expand-7ZipArchive -Path $codeQLBundlePath -DestinationPath $downloadDirectoryPath
$unGzipedCodeQLBundlePath = Join-Path $downloadDirectoryPath "codeql-bundle.tar"
Expand-7ZipArchive -Path $unGzipedCodeQLBundlePath -DestinationPath $codeQLToolcachePath
Write-Host "CodeQL bundle at $($codeQLToolcachePath) contains the following directories:"
Get-ChildItem -Path $codeQLToolcachePath -Depth 2
# Touch a file to indicate to the CodeQL Action that this bundle shipped with the toolcache. This is
# to support overriding the CodeQL version specified in defaults.json on GitHub Enterprise.
New-Item -ItemType file (Join-Path $codeQLToolcachePath -ChildPath "pinned-version")
# Touch a file to indicate to the toolcache that setting up CodeQL is complete.
New-Item -ItemType file "$codeQLToolcachePath.complete"
# Test that the tools have been extracted successfully.
Invoke-PesterTests -TestFile "Tools" -TestName "CodeQL Bundle"
@@ -0,0 +1,10 @@
####################################################################################
## File: Install-DACFx.ps1
## Desc: Install SQL Server® Data-Tier Application Framework (DacFx) for Windows
####################################################################################
Install-Binary -Type MSI `
-Url 'https://aka.ms/dacfx-msi' `
-ExpectedSignature 'C2048FB509F1C37A8C3E9EC6648118458AA01780'
Invoke-PesterTests -TestFile "Tools" -TestName "DACFx"
@@ -0,0 +1,56 @@
################################################################################
## File: Install-Docker.ps1
## Desc: Install Docker.
## Must be an independent step because it requires a restart before we
## can continue.
################################################################################
Write-Host "Get latest Moby release"
$toolsetVersion = (Get-ToolsetContent).docker.components.docker
$mobyVersion = (Get-GithubReleasesByVersion -Repo "moby/moby" -Version "${toolsetVersion}").version
$dockerceUrl = "https://download.docker.com/win/static/stable/x86_64/"
$dockerceBinaries = Invoke-WebRequest -Uri $dockerceUrl -UseBasicParsing
Write-Host "Check Moby version $mobyVersion"
$mobyRelease = $dockerceBinaries.Links.href -match "${mobyVersion}\.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 }
$mobyRelease = $versions | Select-Object -ExpandProperty Value -Last 1
Write-Host "Found $mobyRelease"
}
$mobyReleaseUrl = $dockerceUrl + $mobyRelease
Write-Host "Install Moby $mobyRelease..."
$mobyArchivePath = Invoke-DownloadWithRetry $mobyReleaseUrl
Expand-Archive -Path $mobyArchivePath -DestinationPath $env:TEMP
$dockerPath = "$env:TEMP\docker\docker.exe"
$dockerdPath = "$env:TEMP\docker\dockerd.exe"
Write-Host "Install Docker CE"
$instScriptUrl = "https://raw.githubusercontent.com/microsoft/Windows-Containers/Main/helpful_tools/Install-DockerCE/install-docker-ce.ps1"
$instScriptPath = Invoke-DownloadWithRetry $instScriptUrl
& $instScriptPath -DockerPath $dockerPath -DockerDPath $dockerdPath
if ($LastExitCode -ne 0) {
Write-Host "Docker installation failed with exit code $LastExitCode"
exit $exitCode
}
# Fix AZ CLI DOCKER_COMMAND_ERROR
# cli.azure.cli.command_modules.acr.custom: Could not run 'docker.exe' command.
# https://github.com/Azure/azure-cli/issues/18766
New-Item -ItemType SymbolicLink -Path "C:\Windows\SysWOW64\docker.exe" -Target "C:\Windows\System32\docker.exe"
Write-Host "Download docker images"
$dockerImages = (Get-ToolsetContent).docker.images
foreach ($dockerImage in $dockerImages) {
Write-Host "Pulling docker image $dockerImage ..."
docker pull $dockerImage
if (!$?) {
throw "Docker pull failed with a non-zero exit code ($LastExitCode)"
}
}
Invoke-PesterTests -TestFile "Docker" -TestName "Docker"
Invoke-PesterTests -TestFile "Docker" -TestName "DockerImages"
@@ -0,0 +1,13 @@
################################################################################
## File: Install-Docker-Compose.ps1
## Desc: Install Docker Compose.
################################################################################
Write-Host "Install-Package Docker-Compose v2"
$toolsetVersion = (Get-ToolsetContent).docker.components.compose
$composeVersion = (Get-GithubReleasesByVersion -Repo "docker/compose" -Version "${toolsetVersion}").version
$dockerComposev2Url = "https://github.com/docker/compose/releases/download/v${composeVersion}/docker-compose-windows-x86_64.exe"
$cliPluginsDir = "C:\ProgramData\docker\cli-plugins"
New-Item -Path $cliPluginsDir -ItemType Directory
Invoke-DownloadWithRetry -Url $dockerComposev2Url -Path "$cliPluginsDir\docker-compose.exe"
Invoke-PesterTests -TestFile "Docker" -TestName "DockerCompose"
@@ -0,0 +1,22 @@
################################################################################
## File: Install-Docker-WinCred.ps1
## Desc: Install Docker credential helper.
## Supply chain security: checksum validation
################################################################################
Write-Host "Install docker-wincred"
$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
$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"
@@ -0,0 +1,135 @@
################################################################################
## File: Install-DotnetSDK.ps1
## Desc: Install all released versions of the dotnet sdk and populate package
## cache. Should run after VS and Node
## Supply chain security: checksum validation
################################################################################
# Set environment variables
[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 {
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
$releases = $releasesData.'releases' | Where-Object { !$_.'release-version'.Contains('-') }
$sdks = @()
foreach ($release in $releases) {
$sdks += $release.'sdk'
$sdks += $release.'sdks'
}
return $sdks.version `
| Sort-Object { [Version] $_ } -Unique `
| Group-Object { $_.Substring(0, $_.LastIndexOf('.') + 2) } `
| ForEach-Object { $_.Group[-1] }
}
function Invoke-DotnetWarmup {
param (
[Parameter(Mandatory)]
[string] $SDKVersion
)
# warm up dotnet for first time experience
$projectTypes = @('console', 'mstest', 'web', 'mvc', 'webapi')
foreach ($template in $projectTypes) {
$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"
if ($LastExitCode -ne 0) {
throw "Dotnet new globaljson failed with exit code $LastExitCode"
}
& "$env:ProgramFiles\dotnet\dotnet.exe" new $template
if ($LastExitCode -ne 0) {
throw "Dotnet new $template failed with exit code $LastExitCode"
}
Pop-Location
Remove-Item $projectPath -Force -Recurse
}
}
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
# Installer is PowerShell script that doesn't set exit code on failure
# If installation failed, tests will fail anyway
#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
$dotnetToolset = (Get-ToolsetContent).dotnet
# Download installation script.
$installScriptPath = Invoke-DownloadWithRetry -Url "https://dot.net/v1/dotnet-install.ps1"
# Install and warm up dotnet
foreach ($dotnetVersion in $dotnetToolset.versions) {
$sdkVersionsToInstall = Get-SDKVersionsToInstall -DotnetVersion $dotnetVersion
foreach ($sdkVersion in $sdkVersionsToInstall) {
Install-DotnetSDK -InstallScriptPath $installScriptPath -SDKVersion $sdkVersion -DotnetVersion $dotnetVersion
if ($dotnetToolset.warmup) {
Invoke-DotnetWarmup -SDKVersion $sdkVersion
}
}
}
# Add dotnet to PATH
Add-MachinePathItem "C:\Program Files\dotnet"
# Remove NuGet Folder
$nugetPath = "$env:APPDATA\NuGet"
if (Test-Path $nugetPath) {
Remove-Item -Path $nugetPath -Force -Recurse
}
# Generate and copy new NuGet.Config config
dotnet nuget list source | Out-Null
if ($LastExitCode -ne 0) {
throw "Dotnet nuget list source failed with exit code $LastExitCode"
}
Copy-Item -Path $nugetPath -Destination "C:\Users\Default\AppData\Roaming" -Force -Recurse
# 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
if ($LastExitCode -ne 0) {
throw "Dotnet tool install failed with exit code $LastExitCode"
}
}
Invoke-PesterTests -TestFile "DotnetSDK"
@@ -0,0 +1,39 @@
################################################################################
## File: Install-EdgeDriver.ps1
## Desc: Install Edge WebDriver and configure Microsoft Edge
################################################################################
# Disable Edge auto-updates
Rename-Item -Path "C:\Program Files (x86)\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe" -NewName "Disabled_MicrosoftEdgeUpdate.exe" -ErrorAction Stop
Write-Host "Get the Microsoft Edge WebDriver version..."
$edgeBinaryPath = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\msedge.exe").'(default)'
[version] $edgeVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($edgeBinaryPath).ProductVersion
$edgeDriverPath = "$($env:SystemDrive)\SeleniumWebDrivers\EdgeDriver"
if (-not (Test-Path -Path $edgeDriverPath)) {
New-Item -Path $edgeDriverPath -ItemType Directory -Force
}
$versionInfoUrl = "https://msedgedriver.azureedge.net/LATEST_RELEASE_$($edgeVersion.Major)_WINDOWS"
$versionInfoFile = Invoke-DownloadWithRetry -Url $versionInfoUrl -Path "$edgeDriverPath\versioninfo.txt"
$latestVersion = Get-Content -Path $versionInfoFile
Write-Host "Download Microsoft Edge WebDriver..."
$downloadUrl = "https://msedgedriver.azureedge.net/$latestVersion/edgedriver_win64.zip"
$archivePath = Invoke-DownloadWithRetry $downloadUrl
Write-Host "Expand Microsoft Edge WebDriver archive..."
Expand-7ZipArchive -Path $archivePath -DestinationPath $edgeDriverPath
#Validate the EdgeDriver signature
$signatureThumbprint = "CB9C4FBEA1D87D2D468AC5A9CAAB0163F6AD8401","573EF451A68C33FB904346D44551BEF3BB5BBF68", `
"7920AC8FB05E0FFFE21E8FF4B4F03093BA6AC16E", "0BD8C56733FDCC06F8CB919FF5A200E39B1ACF71"
Test-FileSignature -Path "$edgeDriverPath\msedgedriver.exe" -ExpectedThumbprint $signatureThumbprint
Write-Host "Setting the environment variables..."
[Environment]::SetEnvironmentVariable("EdgeWebDriver", $EdgeDriverPath, "Machine")
Add-MachinePathItem "$edgeDriverPath\"
Invoke-PesterTests -TestFile "Browsers" -TestName "Edge"
@@ -0,0 +1,63 @@
################################################################################
## File: Install-Firefox.ps1
## Desc: Install Mozilla Firefox browser and Gecko WebDriver
## Supply chain security: Firefox browser - checksum validation
################################################################################
# Install and configure Firefox browser
Write-Host "Get the latest Firefox version..."
$versionsManifest = Invoke-RestMethod "https://product-details.mozilla.org/1.0/firefox_versions.json"
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 = Get-ChecksumFromUrl -Type "SHA256" `
-Url $hashUrl `
-FileName "win64/en-US/Firefox Setup*exe"
Install-Binary -Type EXE `
-Url $installerUrl `
-InstallArgs @("/silent", "/install") `
-ExpectedSHA256Sum $externalHash
Write-Host "Disable autoupdate..."
$firefoxDirectoryPath = Join-Path $env:ProgramFiles "Mozilla Firefox"
New-Item -path $firefoxDirectoryPath -Name 'mozilla.cfg' -Value '//
pref("browser.shell.checkDefaultBrowser", false);
pref("app.update.enabled", false);' -ItemType file -force
$firefoxPreferencesFolder = Join-Path $firefoxDirectoryPath "defaults\pref"
New-Item -path $firefoxPreferencesFolder -Name 'local-settings.js' -Value 'pref("general.config.obscure_value", 0);
pref("general.config.filename", "mozilla.cfg");' -ItemType file -force
# Download and install Gecko WebDriver
Write-Host "Install Gecko WebDriver..."
$geckoDriverPath = "$($env:SystemDrive)\SeleniumWebDrivers\GeckoDriver"
if (-not (Test-Path -Path $geckoDriverPath)) {
New-Item -Path $geckoDriverPath -ItemType Directory -Force
}
Write-Host "Get the Gecko WebDriver version..."
$geckoDriverVersion = (Get-GithubReleasesByVersion -Repo "mozilla/geckodriver" -Version "latest").version
$geckoDriverVersion | Out-File -FilePath "$geckoDriverPath\versioninfo.txt" -Force
Write-Host "Download Gecko WebDriver WebDriver..."
$geckoDriverDownloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "mozilla/geckodriver" `
-Version $geckoDriverVersion `
-UrlMatchPattern "geckodriver-*-win64.zip"
$geckoDriverArchPath = Invoke-DownloadWithRetry $geckoDriverDownloadUrl
Write-Host "Expand Gecko WebDriver archive..."
Expand-7ZipArchive -Path $geckoDriverArchPath -DestinationPath $geckoDriverPath
# Validate Gecko WebDriver signature
$geckoDriverSignatureThumbprint = "40890F2FE1ACAE18072FA7F3C0AE456AACC8570D"
Test-FileSignature -Path "$geckoDriverPath/geckodriver.exe" -ExpectedThumbprint $geckoDriverSignatureThumbprint
Write-Host "Setting the environment variables..."
Add-MachinePathItem -PathItem $geckoDriverPath
[Environment]::SetEnvironmentVariable("GeckoWebDriver", $geckoDriverPath, "Machine")
Invoke-PesterTests -TestFile "Browsers" -TestName "Firefox"
@@ -0,0 +1,52 @@
################################################################################
## File: Install-Git.ps1
## Desc: Install Git for Windows
## Supply chain security: Git - checksum validation, Hub CLI - managed by package manager
################################################################################
# Install the latest version of Git for Windows
$downloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "git-for-windows/git" `
-Version "latest" `
-UrlMatchPattern "Git-*-64-bit.exe"
$externalHash = Get-ChecksumFromGithubRelease `
-Repo "git-for-windows/git" `
-Version "latest" `
-FileName (Split-Path $downloadUrl -Leaf) `
-HashType "SHA256"
Install-Binary `
-Url $downloadUrl `
-InstallArgs @(`
"/VERYSILENT", `
"/NORESTART", `
"/NOCANCEL", `
"/SP-", `
"/CLOSEAPPLICATIONS", `
"/RESTARTAPPLICATIONS", `
"/o:PathOption=CmdTools", `
"/o:BashTerminalOption=ConHost", `
"/o:EnableSymlinks=Enabled", `
"/COMPONENTS=gitlfs") `
-ExpectedSHA256Sum $externalHash
Update-Environment
git config --system --add safe.directory "*"
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to configure safe.directory for Git with exit code $LASTEXITCODE"
}
# Disable GCM machine-wide
[Environment]::SetEnvironmentVariable("GCM_INTERACTIVE", "Never", "Machine")
# Add to PATH
Add-MachinePathItem "C:\Program Files\Git\bin"
# Add well-known SSH host keys to ssh_known_hosts
ssh-keyscan -t rsa, ecdsa, ed25519 github.com >> "C:\Program Files\Git\etc\ssh\ssh_known_hosts"
ssh-keyscan -t rsa ssh.dev.azure.com >> "C:\Program Files\Git\etc\ssh\ssh_known_hosts"
Invoke-PesterTests -TestFile "Git"
@@ -0,0 +1,28 @@
################################################################################
## File: Install-GitHub-CLI.ps1
## Desc: Install GitHub CLI
## Supply chain security: GitHub CLI - checksum validation
################################################################################
Write-Host "Get the latest gh version..."
$downloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "cli/cli" `
-Version "latest" `
-UrlMatchPattern "gh_*_windows_amd64.msi"
$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 `
-ExpectedSHA256Sum $externalHash
Add-MachinePathItem "C:\Program Files (x86)\GitHub CLI"
Invoke-PesterTests -TestFile "CLI.Tools" -TestName "GitHub CLI"
@@ -0,0 +1,12 @@
################################################################################
## File: Install-GoogleCloudCLI.ps1
## Desc: Install Google Cloud CLI
################################################################################
# https://cloud.google.com/sdk/docs/downloads-interactive
Install-Binary `
-Url 'https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe' `
-InstallArgs @("/S", "/allusers", "/noreporting") `
-ExpectedSignature '607A3EDAA64933E94422FC8F0C80388E0590986C'
Invoke-PesterTests -TestFile "Tools" -TestName "GoogleCloudCLI"
@@ -0,0 +1,64 @@
################################################################################
## File: Install-Haskell.ps1
## Desc: Install Haskell for Windows
################################################################################
# install minimal ghcup, utilizing pre-installed msys2 at C:\msys64
Write-Host 'Installing ghcup...'
$msysPath = "C:\msys64"
$ghcupPrefix = "C:\"
$cabalDir = "C:\cabal"
$ghcupDownloadURL = "https://downloads.haskell.org/~ghcup/x86_64-mingw64-ghcup.exe"
# If you want to install a specific version of ghcup, uncomment the following lines
# $ghver = "0.1.19.4"
# $ghcupDownloadURL = "https://downloads.haskell.org/~ghcup/${ghver}/x86_64-mingw64-ghcup-${ghver}.exe"
# Other option is to download ghcup from GitHub releases:
# https://github.com/haskell/ghcup-hs/releases/latest
New-Item -Path "$ghcupPrefix\ghcup" -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"
[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
# Get 3 latest versions of GHC
$versions = ghcup list -t ghc -r | Where-Object { $_ -notlike "prerelease" }
$versionsOutput = [version[]]($versions | ForEach-Object { $_.Split(' ')[1]; })
$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
# The latest version will be installed as a default
foreach ($version in $versionsList) {
Write-Host "Installing ghc $version..."
ghcup install ghc $version
if ($LastExitCode -ne 0) {
throw "GHC installation failed with exit code $LastExitCode"
}
ghcup set ghc $version
if ($LastExitCode -ne 0) {
throw "Setting GHC version failed with exit code $LastExitCode"
}
}
# Add default version of GHC to path
$defaultGhcVersion = $versionsList | Select-Object -Last 1
ghcup set ghc $defaultGhcVersion
if ($LastExitCode -ne 0) {
throw "Setting default GHC version failed with exit code $LastExitCode"
}
Write-Host 'Installing cabal...'
ghcup install cabal latest
if ($LastExitCode -ne 0) {
throw "Cabal installation failed with exit code $LastExitCode"
}
Invoke-PesterTests -TestFile 'Haskell'
@@ -0,0 +1,30 @@
################################################################################
## File: Install-IEWebDriver.ps1
## Desc: Install IE Web Driver
################################################################################
$seleniumMajorVersion = (Get-ToolsetContent).selenium.version
$ieDriverUrl = Resolve-GithubReleaseAssetUrl `
-Repo "SeleniumHQ/selenium" `
-Version "$seleniumMajorVersion.*" `
-Asset "IEDriverServer_x64_*.zip"
# Download IE selenium driver
Write-Host "Selenium IEDriverServer download and install..."
$driverZipFile = Invoke-DownloadWithRetry $ieDriverUrl
$ieDriverPath = "C:\SeleniumWebDrivers\IEDriver"
if (-not (Test-Path -Path $ieDriverPath)) {
New-Item -Path $ieDriverPath -ItemType Directory -Force | Out-Null
}
Expand-7ZipArchive -Path $driverZipFile -DestinationPath $ieDriverPath
Remove-Item $driverZipFile
Write-Host "Get the IEDriver version..."
(Get-Item "$ieDriverPath\IEDriverServer.exe").VersionInfo.FileVersion | Out-File -FilePath "$ieDriverPath\versioninfo.txt"
Write-Host "Setting the IEWebDriver environment variables"
[Environment]::SetEnvironmentVariable("IEWebDriver", $ieDriverPath, "Machine")
Invoke-PesterTests -TestFile "Browsers" -TestName "Internet Explorer"
@@ -0,0 +1,141 @@
################################################################################
## File: Install-JavaTools.ps1
## Desc: Install various JDKs and java tools
## Supply chain security: JDK - checksum validation
################################################################################
function Set-JavaPath {
param (
[string] $Version,
[string] $Architecture = "x64",
[switch] $Default
)
$javaPathPattern = Join-Path -Path $env:AGENT_TOOLSDIRECTORY -ChildPath "Java_Temurin-Hotspot_jdk/${Version}*/${Architecture}"
$javaPath = (Get-Item -Path $javaPathPattern).FullName
if ([string]::IsNullOrEmpty($javaPath)) {
Write-Host "Not found path to Java '${Version}'"
exit 1
}
Write-Host "Set 'JAVA_HOME_${Version}_X64' environmental variable as $javaPath"
[Environment]::SetEnvironmentVariable("JAVA_HOME_${Version}_X64", $javaPath, "Machine")
if ($Default) {
# Clean up any other Java folders from PATH to make sure that they won't conflict with each other
$currentPath = [System.Environment]::GetEnvironmentVariable("PATH", "Machine")
$pathSegments = $currentPath.Split(';')
$newPathSegments = @()
foreach ($pathSegment in $pathSegments) {
if ($pathSegment -notlike '*java*') {
$newPathSegments += $pathSegment
}
}
$newPath = [string]::Join(';', $newPathSegments)
$newPath = $javaPath + '\bin;' + $newPath
Write-Host "Add $javaPath\bin to PATH"
[Environment]::SetEnvironmentVariable("PATH", $newPath, "Machine")
Write-Host "Set JAVA_HOME environmental variable as $javaPath"
[Environment]::SetEnvironmentVariable("JAVA_HOME", $javaPath, "Machine")
}
}
function Install-JavaJDK {
param(
[string] $JDKVersion,
[string] $Architecture = "x64"
)
# Get Java version from api
$assetUrl = Invoke-RestMethod -Uri "https://api.adoptium.net/v3/assets/latest/${JDKVersion}/hotspot"
$asset = $assetUrl | Where-Object {
$_.binary.os -eq "windows" `
-and $_.binary.architecture -eq $Architecture `
-and $_.binary.image_type -eq "jdk"
}
# Download and extract java binaries to temporary folder
$downloadUrl = $asset.binary.package.link
$archivePath = Invoke-DownloadWithRetry $downloadUrl
Test-FileChecksum $archivePath -ExpectedSHA256Sum $asset.binary.package.checksum
# We have to replace '+' sign in the version to '-' due to the issue with incorrect path in Android builds https://github.com/actions/runner-images/issues/3014
$fullJavaVersion = $asset.version.semver -replace '\+', '-'
# Remove 'LTS' suffix from the version if present
$fullJavaVersion = $fullJavaVersion -replace '\.LTS$', ''
# Create directories in toolcache path
$javaToolcachePath = Join-Path -Path $env:AGENT_TOOLSDIRECTORY -ChildPath "Java_Temurin-Hotspot_jdk"
$javaVersionPath = Join-Path -Path $javaToolcachePath -ChildPath $fullJavaVersion
$javaArchPath = Join-Path -Path $javaVersionPath -ChildPath $Architecture
if (-not (Test-Path $javaToolcachePath)) {
Write-Host "Creating Temurin-Hotspot toolcache folder"
New-Item -ItemType Directory -Path $javaToolcachePath | Out-Null
}
Write-Host "Creating Java '${fullJavaVersion}' folder in '${javaVersionPath}'"
New-Item -ItemType Directory -Path $javaVersionPath -Force | Out-Null
# Complete the installation by extracting Java binaries to toolcache and creating the complete file
Expand-7ZipArchive -Path $archivePath -DestinationPath $javaVersionPath
Invoke-ScriptBlockWithRetry -Command {
Get-ChildItem -Path $javaVersionPath | Rename-Item -NewName $javaArchPath -ErrorAction Stop
}
New-Item -ItemType File -Path $javaVersionPath -Name "$Architecture.complete" | Out-Null
}
$toolsetJava = (Get-ToolsetContent).java
$defaultVersion = $toolsetJava.default
$jdkVersionsToInstall = $toolsetJava.versions
foreach ($jdkVersionToInstall in $jdkVersionsToInstall) {
$isDefaultVersion = $jdkVersionToInstall -eq $defaultVersion
Install-JavaJDK -JDKVersion $jdkVersionToInstall
if ($isDefaultVersion) {
Set-JavaPath -Version $jdkVersionToInstall -Default
} else {
Set-JavaPath -Version $jdkVersionToInstall
}
}
# Install Java tools
# Force chocolatey to ignore dependencies on Ant and Maven or else they will download the Oracle JDK
Install-ChocoPackage ant -ArgumentList "--ignore-dependencies"
# Maven 3.9.x has multiple compatibilities problems
$toolsetMavenVersion = (Get-ToolsetContent).maven.version
$versionToInstall = Resolve-ChocoPackageVersion -PackageName "maven" -TargetVersion $toolsetMavenVersion
Install-ChocoPackage maven -ArgumentList "--version=$versionToInstall"
Install-ChocoPackage gradle
# Add maven env variables to Machine
[string] $m2Path = ([Environment]::GetEnvironmentVariable("PATH", "Machine")).Split(";") -match "maven"
$m2RepoPath = 'C:\ProgramData\m2'
New-Item -Path $m2RepoPath -ItemType Directory -Force | Out-Null
[Environment]::SetEnvironmentVariable("M2", $m2Path, "Machine")
[Environment]::SetEnvironmentVariable("M2_REPO", $m2RepoPath, "Machine")
[Environment]::SetEnvironmentVariable("MAVEN_OPTS", "-Xms256m", "Machine")
# Download cobertura jars
$uri = 'https://repo1.maven.org/maven2/net/sourceforge/cobertura/cobertura/2.1.1/cobertura-2.1.1-bin.zip'
$sha256sum = '79479DDE416B082F38ECD1F2F7C6DEBD4D0C2249AF80FD046D1CE05D628F2EC6'
$coberturaPath = "C:\cobertura-2.1.1"
$archivePath = Invoke-DownloadWithRetry $uri
Test-FileChecksum $archivePath -ExpectedSHA256Sum $sha256sum
Expand-7ZipArchive -Path $archivePath -DestinationPath "C:\"
[Environment]::SetEnvironmentVariable("COBERTURA_HOME", $coberturaPath, "Machine")
Invoke-PesterTests -TestFile "Java"
@@ -0,0 +1,28 @@
################################################################################
## File: Install-Kotlin.ps1
## Desc: Install Kotlin
## Supply chain security: Kotlin - checksum validation
################################################################################
# Install Kotlin
$kotlinVersion = (Get-ToolsetContent).kotlin.version
$kotlinDownloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "JetBrains/kotlin" `
-Version "$kotlinVersion" `
-Asset "kotlin-compiler-*.zip"
$kotlinArchivePath = Invoke-DownloadWithRetry $kotlinDownloadUrl
#region Supply chain security
$externalHash = Get-Content $(Invoke-DownloadWithRetry "$kotlinDownloadUrl.sha256")
Test-FileChecksum $kotlinArchivePath -ExpectedSHA256Sum $externalHash
#endregion
Write-Host "Expand Kotlin archive"
$kotlinPath = "C:\tools"
Expand-7ZipArchive -Path $kotlinArchivePath -DestinationPath $kotlinPath
# Add to PATH
Add-MachinePathItem "$kotlinPath\kotlinc\bin"
Invoke-PesterTests -TestFile "Tools" -TestName "Kotlin"
@@ -0,0 +1,37 @@
################################################################################
## File: Install-KubernetesTools.ps1
## Desc: Install tools for K8s.
## Supply chain security: GitHub Kind - checksum validation, Kubectl, Helm, Minikube - by package manager
################################################################################
Write-Host "Install Kind"
# Choco installation can't be used because it depends on docker-desktop
$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
$externalHash = Get-ChecksumFromUrl -Type "SHA256" `
-Url "$downloadUrl.sha256sum" `
-FileName (Split-Path $downloadUrl -Leaf)
Test-FileChecksum $packagePath -ExpectedSHA256Sum $externalHash
#endregion
Add-MachinePathItem $targetDir
Write-Host "Install Kubectl"
Install-ChocoPackage kubernetes-cli
Write-Host "Install Helm"
Install-ChocoPackage kubernetes-helm
Write-Host "Install Minikube"
Install-ChocoPackage minikube
Invoke-PesterTests -TestFile "Tools" -TestName "KubernetesTools"
@@ -0,0 +1,10 @@
################################################################################
## File: Install-LLVM.ps1
## Desc: Install the latest stable version of llvm and clang compilers
################################################################################
$llvmVersion = (Get-ToolsetContent).llvm.version
$latestChocoVersion = Resolve-ChocoPackageVersion -PackageName "llvm" -TargetVersion $llvmVersion
Install-ChocoPackage llvm -ArgumentList '--version', $latestChocoVersion
Invoke-PesterTests -TestFile "LLVM"
@@ -0,0 +1,11 @@
################################################################################
## File: Install-Mercurial.ps1
## Desc: Install Mercurial
################################################################################
Install-ChocoPackage hg -ArgumentList "--version", "5.0.0"
Add-MachinePathItem "${env:ProgramFiles}\Mercurial\"
Update-Environment
Invoke-PesterTests -TestFile "Tools" -TestName "Mercurial"
@@ -0,0 +1,70 @@
################################################################################
## File: Install-Mingw64.ps1
## Desc: Install GNU tools for Windows
################################################################################
if (Test-IsWin25 -or Test-IsWin19) {
# If Windows 2019, install version 8.1.0 form sourceforge
$baseUrl = "https://download.qt.io/development_releases/prebuilt"
$("mingw32", "mingw64") | ForEach-Object {
if ($_ -eq "mingw32") {
$url = "$baseUrl/mingw_32/i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z"
$sha256sum = 'adb84b70094c0225dd30187ff995e311d19424b1eb8f60934c60e4903297f946'
} elseif ($_ -eq "mingw64") {
$url = "$baseUrl/mingw_64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z"
$sha256sum = '853970527b5de4a55ec8ca4d3fd732c00ae1c69974cc930c82604396d43e79f8'
} else {
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 -or Test-IsWin25) {
# 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')
}
Add-MachinePathItem "C:\mingw64\bin"
}
Invoke-PesterTests -TestFile "Tools" -TestName "Mingw64"
@@ -0,0 +1,32 @@
################################################################################
## File: Install-Miniconda.ps1
## Desc: Install the latest version of Miniconda and set $env:CONDA
## Supply chain security: checksum validation
################################################################################
$condaDestination = "C:\Miniconda"
$installerName = "Miniconda3-latest-Windows-x86_64.exe"
#region Supply chain security
$distributorFileHash = $null
$checksums = (ConvertFrom-HTML -Uri 'https://repo.anaconda.com/miniconda/').SelectNodes('//html/body/table/tr')
foreach ($node in $checksums) {
if ($node.ChildNodes[1].InnerText -eq $installerName) {
$distributorFileHash = $node.ChildNodes[7].InnerText
}
}
if ($null -eq $distributorFileHash) {
throw "Unable to find checksum for $installerName in https://repo.anaconda.com/miniconda/"
}
#endregion
Install-Binary `
-Url "https://repo.anaconda.com/miniconda/${installerName}" `
-InstallArgs @("/S", "/AddToPath=0", "/RegisterPython=0", "/D=$condaDestination") `
-ExpectedSHA256Sum $distributorFileHash
[Environment]::SetEnvironmentVariable("CONDA", $condaDestination, "Machine")
Invoke-PesterTests -TestFile "Miniconda"
@@ -0,0 +1,56 @@
####################################################################################
## File: Install-MongoDB.ps1
## Desc: Install MongoDB
####################################################################################
# Install mongodb package
$toolsetContent = Get-ToolsetContent
$toolsetVersion = $toolsetContent.mongodb.version
$getMongoReleases = Invoke-WebRequest -Uri "mongodb.com/docs/manual/release-notes/$toolsetVersion/" -UseBasicParsing
$targetReleases = $getMongoReleases.Links.href | Where-Object { $_ -like "#$toolsetVersion*---*" }
$minorVersions = @()
foreach ($release in $targetReleases) {
if ($release -notlike "*upcoming*") {
$pattern = '\d+\.\d+\.\d+'
$version = $release | Select-String -Pattern $pattern -AllMatches | ForEach-Object { $_.Matches } | ForEach-Object { $_.Value }
$minorVersions += $version
}
}
$latestVersion = $minorVersions[0]
Install-Binary `
-Url "https://fastdl.mongodb.org/windows/mongodb-windows-x86_64-$latestVersion-signed.msi" `
-ExtraInstallArgs @('TARGETDIR=C:\PROGRA~1\MongoDB ADDLOCAL=ALL') `
-ExpectedSignature $toolsetContent.mongodb.signature
# Add mongodb to the PATH
$mongoPath = (Get-CimInstance Win32_Service -Filter "Name LIKE 'mongodb'").PathName
$mongoBin = Split-Path -Path $mongoPath.split('"')[1]
Add-MachinePathItem "$mongoBin"
# Wait for mongodb service running
$mongodbService = Get-Service "mongodb"
$mongodbService.WaitForStatus('Running', '00:01:00')
# Stop and disable mongodb service
Stop-Service $mongodbService
$mongodbService | Set-Service -StartupType Disabled
# Install mongodb shell for mongodb > 5
if (Test-IsWin25) {
$mongoshVersion = (Get-GithubReleasesByVersion -Repo "mongodb-js/mongosh" -Version "latest").version
$mongoshDownloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "mongodb-js/mongosh" `
-Version $mongoshVersion `
-UrlMatchPattern "mongosh-*-x64.msi"
Install-Binary -Type MSI `
-Url $mongoshDownloadUrl `
-ExpectedSignature 'F2D7C28591847BB2CB2B1C2A0C59459FDC728A38'
}
Invoke-PesterTests -TestFile "Databases" -TestName "MongoDB"
@@ -0,0 +1,136 @@
################################################################################
## File: Install-Msys2.ps1
## Desc: Install Msys2 and 64 & 32 bit gcc, cmake, & llvm
################################################################################
# References
# https://github.com/msys2/MINGW-packages/blob/master/azure-pipelines.yml
# https://packages.msys2.org/group/
$logPrefix = "`n" + ("-" * 40) + "`n---"
$origPath = $env:PATH
function Install-Msys2 {
# 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 "Download msys2 installer $installerName"
$installerPath = Invoke-DownloadWithRetry $downloadUri
#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
Write-Host "Starting msys2 installation"
& $installerPath in --confirm-command --accept-messages --root C:/msys64
if ($LastExitCode -ne 0) {
throw "MSYS2 installation failed with exit code $LastExitCode"
}
Remove-Item $installerPath
}
function Install-Msys2Packages {
param (
[Parameter(Mandatory = $true)]
[AllowEmptyCollection()]
[string[]]$Packages
)
if (-not $Packages) {
return
}
Write-Host "$logPrefix Install msys2 packages"
pacman.exe -S --noconfirm --needed --noprogressbar $Packages
if ($LastExitCode -ne 0) {
throw "MSYS2 packages installation failed with exit code $LastExitCode"
}
taskkill /f /fi "MODULES eq msys-2.0.dll"
Write-Host "$logPrefix Remove p7zip/7z package due to conflicts"
pacman.exe -R --noconfirm --noprogressbar p7zip
if ($LastExitCode -ne 0) {
throw "Removal of p7zip/7z package failed with exit code $LastExitCode"
}
}
function Install-MingwPackages {
param (
[Parameter(Mandatory = $true)]
[AllowEmptyCollection()]
[object[]] $Packages
)
if (-not $Packages) {
return
}
Write-Host "$logPrefix Install mingw packages"
$archs = $Packages.arch
foreach ($arch in $archs) {
Write-Host "Installing $arch packages"
$archPackages = $toolsetContent.mingw | Where-Object { $_.arch -eq $arch }
$runtimePackages = $archPackages.runtime_packages.name | ForEach-Object { "${arch}-$_" }
$additionalPackages = $archPackages.additional_packages | ForEach-Object { "${arch}-$_" }
$packagesToInstall = $runtimePackages + $additionalPackages
Write-Host "The following packages will be installed: $packagesToInstall"
pacman.exe -S --noconfirm --needed --noprogressbar $packagesToInstall
if ($LastExitCode -ne 0) {
throw "Installation of $arch packages failed with exit code $LastExitCode"
}
}
# clean all packages to decrease image size
Write-Host "$logPrefix Clean packages"
pacman.exe -Scc --noconfirm
if ($LastExitCode -ne 0) {
throw "Cleaning of packages failed with exit code $LastExitCode"
}
$pkgs = pacman.exe -Q
if ($LastExitCode -ne 0) {
throw "Listing of packages failed with exit code $LastExitCode"
}
foreach ($arch in $archs) {
Write-Host "$logPrefix Installed $arch packages"
$pkgs | Select-String -Pattern "^${arch}-"
}
}
Install-Msys2
# Add msys2 bin tools folders to PATH temporary
$env:PATH = "C:\msys64\mingw64\bin;C:\msys64\usr\bin;$origPath"
Write-Host "$logPrefix pacman --noconfirm -Syyuu"
pacman.exe -Syyuu --noconfirm
if ($LastExitCode -ne 0) {
throw "Updating of packages failed with exit code $LastExitCode"
}
taskkill /f /fi "MODULES eq msys-2.0.dll"
Write-Host "$logPrefix pacman --noconfirm -Syuu (2nd pass)"
pacman.exe -Syuu --noconfirm
if ($LastExitCode -ne 0) {
throw "Second pass updating of packages failed with exit code $LastExitCode"
}
taskkill /f /fi "MODULES eq msys-2.0.dll"
$toolsetContent = (Get-ToolsetContent).MsysPackages
Install-Msys2Packages -Packages $toolsetContent.msys2
Install-MingwPackages -Packages $toolsetContent.mingw
$env:PATH = $origPath
Write-Host "`nMSYS2 installation completed"
Invoke-PesterTests -TestFile "MSYS2"
@@ -0,0 +1,40 @@
################################################################################
## File: Install-MysqlCli.ps1
## Desc: Install Mysql CLI
## Supply chain security: checksum validation (visual c++ redistributable package)
################################################################################
# Installing visual c++ redistributable package.
Install-Binary `
-Url 'https://download.microsoft.com/download/0/5/6/056dcda9-d667-4e27-8001-8a0c6971d6b1/vcredist_x64.exe' `
-InstallArgs @("/install", "/quiet", "/norestart") `
-ExpectedSHA256Sum '20E2645B7CD5873B1FA3462B99A665AC8D6E14AAE83DED9D875FEA35FFDD7D7E'
# Downloading mysql
[version] $mysqlVersion = (Get-ToolsetContent).mysql.version
$mysqlVersionMajorMinor = $mysqlVersion.ToString(2)
if ($mysqlVersion.Build -lt 0) {
if ($mysqlVersionMajorMinor -eq "5.7") {
$downloadsPageUrl = "https://downloads.mysql.com/archives/community/"
} else {
$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()
$mysqlVersionUrl = "https://cdn.mysql.com/Downloads/MySQL-${mysqlVersionMajorMinor}/mysql-${mysqlVersionFull}-winx64.msi"
Install-Binary `
-Url $mysqlVersionUrl `
-ExpectedSignature (Get-ToolsetContent).mysql.signature
# Adding mysql in system environment path
$mysqlPath = $(Get-ChildItem -Path "C:\PROGRA~1\MySQL" -Directory)[0].FullName
Add-MachinePathItem "${mysqlPath}\bin"
Invoke-PesterTests -TestFile "Databases" -TestName "MySQL"
@@ -0,0 +1,13 @@
################################################################################
## File: Install-NET48-devpack.ps1
## Desc: Install .NET 4.8 devpack
## Supply chain security: checksum validation
################################################################################
# .NET 4.8 Dev pack
Install-Binary `
-Url 'https://download.visualstudio.microsoft.com/download/pr/014120d7-d689-4305-befd-3cb711108212/0307177e14752e359fde5423ab583e43/ndp48-devpack-enu.exe' `
-InstallArgs @("Setup", "/passive", "/norestart") `
-ExpectedSHA256Sum '0A7AC4A9B44CED6BB7A0EBF3AD9BA29F60BD4D3BEB2047E19F4D8749DE61F5AC'
Invoke-PesterTests -TestFile "Tools" -TestName "NET48"
@@ -0,0 +1,11 @@
################################################################################
## File: Install-NET48.ps1
## Desc: Install .NET 4.8
## Supply chain security: checksum validation
################################################################################
# .NET 4.8 Dev pack
Install-Binary `
-Url 'https://download.visualstudio.microsoft.com/download/pr/2d6bb6b2-226a-4baa-bdec-798822606ff1/8494001c276a4b96804cde7829c04d7f/ndp48-x86-x64-allos-enu.exe' `
-InstallArgs @("Setup", "/passive", "/norestart") `
-ExpectedSHA256Sum '68C9986A8DCC0214D909AA1F31BEE9FB5461BB839EDCA996A75B08DDFFC1483F'
@@ -0,0 +1,14 @@
################################################################################
## File: Install-NSIS.ps1
## Desc: Install NSIS
## Supply chain security: NSIS - managed by package manager
################################################################################
$nsisVersion = (Get-ToolsetContent).nsis.version
Install-ChocoPackage nsis -ArgumentList "--version", "$nsisVersion"
Add-MachinePathItem "${env:ProgramFiles(x86)}\NSIS\"
Update-Environment
Invoke-PesterTests -TestFile "Tools" -TestName "NSIS"
@@ -0,0 +1,22 @@
################################################################################
## File: Install-NativeImages.ps1
## Desc: Generate and install native images for .NET assemblies
################################################################################
Write-Host "NGen: install Microsoft.PowerShell.Utility.Activities..."
& $env:SystemRoot\Microsoft.NET\Framework64\v4.0.30319\ngen.exe install "Microsoft.PowerShell.Utility.Activities, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Installation of Microsoft.PowerShell.Utility.Activities failed with exit code $LASTEXITCODE"
}
Write-Host "NGen: update x64 native images..."
& $env:SystemRoot\Microsoft.NET\Framework64\v4.0.30319\ngen.exe update | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Update of x64 native images failed with exit code $LASTEXITCODE"
}
Write-Host "NGen: update x86 native images..."
& $env:SystemRoot\Microsoft.NET\Framework\v4.0.30319\ngen.exe update | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Update of x86 native images failed with exit code $LASTEXITCODE"
}
@@ -0,0 +1,22 @@
################################################################################
## File: Install-Nginx.ps1
## Desc: Install Nginx
################################################################################
# Stop w3svc service
Stop-Service -Name w3svc
# Install latest nginx in chocolatey
$installDir = "C:\tools"
Install-ChocoPackage nginx -ArgumentList "--force", "--params", "/installLocation:$installDir /port:80"
# Stop and disable Nginx service
Stop-Service -Name nginx
Set-Service -Name nginx -StartupType Disabled
# Start w3svc service
Start-Service -Name w3svc
# Invoke Pester Tests
Invoke-PesterTests -TestFile "Nginx"
@@ -0,0 +1,32 @@
################################################################################
## File: Install-NodeJS.ps1
## Desc: Install nodejs-lts and other common node tools.
## Must run after python is configured
################################################################################
$prefixPath = 'C:\npm\prefix'
$cachePath = 'C:\npm\cache'
New-Item -Path $prefixPath -Force -ItemType Directory
New-Item -Path $cachePath -Force -ItemType Directory
$defaultVersion = (Get-ToolsetContent).node.default
$versionToInstall = Resolve-ChocoPackageVersion -PackageName "nodejs" -TargetVersion $defaultVersion
Install-ChocoPackage "nodejs" -ArgumentList "--version=$versionToInstall"
Add-MachinePathItem $prefixPath
Update-Environment
[Environment]::SetEnvironmentVariable("npm_config_prefix", $prefixPath, "Machine")
$env:npm_config_prefix = $prefixPath
npm config set cache $cachePath --global
npm config set registry https://registry.npmjs.org/
$globalNpmPackages = (Get-ToolsetContent).npm.global_packages
$globalNpmPackages | ForEach-Object {
npm install -g $_.name
}
Invoke-PesterTests -TestFile "Node"
@@ -0,0 +1,44 @@
################################################################################
## File: Install-OpenSSL.ps1
## Desc: Install win64-openssl.
## Supply chain security: checksum validation
################################################################################
$arch = 'INTEL'
$bits = '64'
$light = $false
$installerType = "exe"
$version = (Get-ToolsetContent).openssl.version
$installDir = "$env:ProgramFiles\OpenSSL"
# Fetch available installers list
$jsonUrl = 'https://raw.githubusercontent.com/slproweb/opensslhashes/master/win32_openssl_hashes.json'
$installersAvailable = (Invoke-RestMethod $jsonUrl).files
$installerNames = $installersAvailable | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name
$installerUrl = $null
$installerHash = $null
foreach ($key in $installerNames) {
$installer = $installersAvailable.$key
if (($installer.light -eq $light) -and ($installer.arch -eq $arch) -and ($installer.bits -eq $bits) -and ($installer.installer -eq $installerType) -and ($installer.basever -eq $version)) {
$installerUrl = $installer.url
$installerHash = $installer.sha512
}
}
if ($null -eq $installerUrl) {
throw "Installer not found for version $version"
}
Install-Binary `
-Url $installerUrl `
-InstallArgs @('/silent', '/sp-', '/suppressmsgboxes', "/DIR=`"$installDir`"") `
-ExpectedSHA512Sum $installerHash
# Update PATH
Add-MachinePathItem "$installDir\bin"
Update-Environment
Invoke-PesterTests -TestFile "Tools" -TestName "OpenSSL"
@@ -0,0 +1,22 @@
################################################################################
## File: Install-PHP.ps1
## Desc: Install PHP
################################################################################
# Install latest PHP in chocolatey
$installDir = "c:\tools\php"
$phpMajorMinor = (Get-ToolsetContent).php.version
$phpVersionToInstall = Resolve-ChocoPackageVersion -PackageName "php" -TargetVersion $phpMajorMinor
Install-ChocoPackage php -ArgumentList "--params", "/InstallDir:$installDir", "--version=$phpVersionToInstall"
# Install latest Composer in chocolatey
Install-ChocoPackage composer -ArgumentList "--install-args", "/DEV=$installDir /PHP=$installDir"
# update path to extensions and enable curl and mbstring extensions, and enable php openssl extensions.
((Get-Content -path $installDir\php.ini -Raw) -replace ';extension=curl','extension=curl' -replace ';extension=mbstring','extension=mbstring' -replace ';extension_dir = "ext"','extension_dir = "ext"' -replace ';extension=openssl','extension=openssl') | Set-Content -Path $installDir\php.ini
# Set the PHPROOT environment variable.
[Environment]::SetEnvironmentVariable("PHPROOT", $installDir, "Machine")
# Invoke Pester Tests
Invoke-PesterTests -TestFile "PHP"
@@ -0,0 +1,39 @@
################################################################################
## File: Install-Pipx.ps1
## Desc: Install pipx and pipx packages
################################################################################
Write-Host "Installing pipx..."
$env:PIPX_BIN_DIR = "${env:ProgramFiles(x86)}\pipx_bin"
$env:PIPX_HOME = "${env:ProgramFiles(x86)}\pipx"
pip install pipx
if ($LASTEXITCODE -ne 0) {
throw "pipx installation failed with exit code $LASTEXITCODE"
}
Add-MachinePathItem "${env:PIPX_BIN_DIR}"
[Environment]::SetEnvironmentVariable("PIPX_BIN_DIR", $env:PIPX_BIN_DIR, "Machine")
[Environment]::SetEnvironmentVariable("PIPX_HOME", $env:PIPX_HOME, "Machine")
Invoke-PesterTests -TestFile "Tools" -TestName "Pipx"
Write-Host "Installing pipx packages..."
$pipxToolset = (Get-ToolsetContent).pipx
foreach ($tool in $pipxToolset) {
if ($tool.python) {
$pythonPath = (Get-Item -Path "${env:AGENT_TOOLSDIRECTORY}\Python\${tool.python}.*\x64\python-${tool.python}*").FullName
Write-Host "Install ${tool.package} into python ${tool.python}"
pipx install $tool.package --python $pythonPath
} else {
Write-Host "Install ${tool.package} into default python"
pipx install $tool.package
}
if ($LASTEXITCODE -ne 0) {
throw "Package ${tool.package} installation failed with exit code $LASTEXITCODE"
}
}
Invoke-PesterTests -TestFile "PipxPackages"
@@ -0,0 +1,97 @@
################################################################################
## File: Install-PostgreSQL.ps1
## Desc: Install PostgreSQL
################################################################################
# Define user and password for PostgreSQL database
$pgUser = "postgres"
$pgPwd = "root"
# Prepare environment variable for validation
[Environment]::SetEnvironmentVariable("PGUSER", $pgUser, "Machine")
[Environment]::SetEnvironmentVariable("PGPASSWORD", $pgPwd, "Machine")
$toolsetVersion = (Get-ToolsetContent).postgresql.version
if ($null -ne ($toolsetVersion | Select-String -Pattern '\d+\.\d+\.\d+')) {
$majorVersion = ([version]$toolsetVersion).Major
$minorVersion = ([version]$toolsetVersion).Minor
$patchVersion = ([version]$toolsetVersion).Build
$installerUrl = "https://get.enterprisedb.com/postgresql/postgresql-$majorVersion.$minorVersion-$patchVersion-windows-x64.exe"
} else {
# Define latest available version to install based on version specified in the toolset
$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)
$targetReleases = $getPostgreReleases.Links.href | Where-Object { $_ -match "a=log;h=refs/tags/REL_$toolsetVersion" }
[Int32] $outNumber = $null
$minorVersions = @()
foreach ($release in $targetReleases) {
$version = $release.split('/')[-1]
# 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)) {
$minorVersions += $outNumber
}
}
# Sorting and getting the last one
$targetMinorVersions = ($minorVersions | Sort-Object)[-1]
# In order to get rid of error messages (we know we will have them), force ErrorAction to SilentlyContinue
$errorActionOldValue = $ErrorActionPreference
$ErrorActionPreference = 'SilentlyContinue'
# Install latest PostgreSQL
# Starting from number 9 and going down, check if the installer is available. If yes, break the loop.
# If an installer with $targetMinorVersions is not to be found, the $targetMinorVersions will be decreased by 1
$increment = 9
do {
$url = "https://get.enterprisedb.com/postgresql/postgresql-$toolsetVersion.$targetMinorVersions-$increment-windows-x64.exe"
$checkAccess = [System.Net.WebRequest]::Create($url)
$response = $null
$response = $checkAccess.GetResponse()
if ($response) {
$installerUrl = $response.ResponseUri.OriginalString
} elseif (!$response -and ($increment -eq 0)) {
$increment = 9
$targetMinorVersions--
} else {
$increment--
}
} while (!$response)
}
# Return the previous value of ErrorAction and invoke Install-Binary function
$ErrorActionPreference = $errorActionOldValue
$installerArgs = @("--install_runtimes 0", "--superpassword root", "--enable_acledit 1", "--unattendedmodeui none", "--mode unattended")
Install-Binary `
-Url $installerUrl `
-InstallArgs $installerArgs `
-ExpectedSignature (Get-ToolsetContent).postgresql.signature
# Get Path to pg_ctl.exe
$pgPath = (Get-CimInstance Win32_Service -Filter "Name LIKE 'postgresql-%'").PathName
# Parse output of command above to obtain pure path
$pgBin = Split-Path -Path $pgPath.split('"')[1]
$pgRoot = Split-Path -Path $pgPath.split('"')[5]
$pgData = Join-Path $pgRoot "data"
# Validate PostgreSQL installation
$pgReadyPath = Join-Path $pgBin "pg_isready.exe"
$pgReady = Start-Process -FilePath $pgReadyPath -Wait -PassThru
$exitCode = $pgReady.ExitCode
if ($exitCode -ne 0) {
Write-Host -Object "PostgreSQL is not ready. Exitcode: $exitCode"
exit $exitCode
}
# Added PostgreSQL environment variable
[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*
Stop-Service $pgService
$pgService | Set-Service -StartupType Disabled
Invoke-PesterTests -TestFile "Databases" -TestName "PostgreSQL"
@@ -0,0 +1,27 @@
################################################################################
## File: Install-PowershellModules.ps1
## Desc: Install common PowerShell modules
################################################################################
# Set TLS1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor "Tls12"
# Install PowerShell modules
$modules = (Get-ToolsetContent).powershellModules
foreach ($module in $modules) {
$moduleName = $module.name
Write-Host "Installing ${moduleName} module"
if ($module.versions) {
foreach ($version in $module.versions) {
Write-Host " - $version"
Install-Module -Name $moduleName -RequiredVersion $version -Scope AllUsers -SkipPublisherCheck -Force
}
} else {
Install-Module -Name $moduleName -Scope AllUsers -SkipPublisherCheck -Force
}
}
Import-Module Pester
Invoke-PesterTests -TestFile "PowerShellModules" -TestName "PowerShellModules"
@@ -0,0 +1,48 @@
################################################################################
## File: Install-PowershellAzModules.ps1
## Desc: Install PowerShell modules used by AzureFileCopy@4, AzureFileCopy@5, AzurePowerShell@4, AzurePowerShell@5 tasks
## Supply chain security: package manager
################################################################################
# The correct Modules need to be saved in C:\Modules
$installPSModulePath = "C:\\Modules"
if (-not (Test-Path -LiteralPath $installPSModulePath)) {
Write-Host "Creating ${installPSModulePath} folder to store PowerShell Azure modules..."
New-Item -Path $installPSModulePath -ItemType Directory | Out-Null
}
# Get modules content from toolset
$modules = (Get-ToolsetContent).azureModules
$psModuleMachinePath = ""
foreach ($module in $modules) {
$moduleName = $module.name
Write-Host "Installing ${moduleName} to the ${installPSModulePath} path..."
foreach ($version in $module.versions) {
$modulePath = Join-Path -Path $installPSModulePath -ChildPath "${moduleName}_${version}"
Write-Host " - $version [$modulePath]"
Save-Module -Path $modulePath -Name $moduleName -RequiredVersion $version -Force -ErrorAction Stop
}
foreach ($version in $module.zip_versions) {
$modulePath = Join-Path -Path $installPSModulePath -ChildPath "${moduleName}_${version}"
Save-Module -Path $modulePath -Name $moduleName -RequiredVersion $version -Force -ErrorAction Stop
Compress-Archive -Path $modulePath -DestinationPath "${modulePath}.zip"
Remove-Item $modulePath -Recurse -Force
}
# Append default tool version to machine path
if ($null -ne $module.default) {
$defaultVersion = $module.default
Write-Host "Use ${moduleName} ${defaultVersion} as default version..."
$psModuleMachinePath += "${installPSModulePath}\${moduleName}_${defaultVersion};"
}
}
# Add modules to the PSModulePath
$psModuleMachinePath += $env:PSModulePath
[Environment]::SetEnvironmentVariable("PSModulePath", $psModuleMachinePath, "Machine")
Invoke-PesterTests -TestFile "PowerShellAzModules" -TestName "AzureModules"
@@ -0,0 +1,43 @@
################################################################################
## File: Install-PowershellCore.ps1
## Desc: Install PowerShell Core
## Supply chain security: checksum validation
################################################################################
$ErrorActionPreference = "Stop"
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName())
New-Item -ItemType Directory -Path $tempDir -Force -ErrorAction SilentlyContinue | Out-Null
try {
$originalValue = [Net.ServicePointManager]::SecurityProtocol
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
$metadata = Invoke-RestMethod https://raw.githubusercontent.com/PowerShell/PowerShell/master/tools/metadata.json
$pwshMajorMinor = (Get-ToolsetContent).pwsh.version
$releases = $metadata.LTSReleaseTag -replace '^v'
foreach ($release in $releases) {
if ($release -like "${pwshMajorMinor}*") {
$downloadUrl = "https://github.com/PowerShell/PowerShell/releases/download/v${release}/PowerShell-${release}-win-x64.msi"
break
}
}
$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
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
}
# about_update_notifications
# 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.
[Environment]::SetEnvironmentVariable("POWERSHELL_UPDATECHECK", "Off", "Machine")
Invoke-PesterTests -TestFile "Tools" -TestName "PowerShell Core"
@@ -0,0 +1,108 @@
################################################################################
## File: Install-PyPy.ps1
## Desc: Install PyPy
## Supply chain security: checksum validation
################################################################################
function Install-PyPy {
param(
[String] $PackagePath,
[String] $Architecture
)
# Create PyPy toolcache folder
$pypyToolcachePath = Join-Path -Path $env:AGENT_TOOLSDIRECTORY -ChildPath "PyPy"
if (-not (Test-Path $pypyToolcachePath)) {
Write-Host "Create PyPy toolcache folder"
New-Item -ItemType Directory -Path $pypyToolcachePath | Out-Null
}
# Expand archive with binaries
$packageName = [IO.Path]::GetFileNameWithoutExtension((Split-Path -Path $packagePath -Leaf))
$tempFolder = Join-Path -Path $pypyToolcachePath -ChildPath $packageName
Expand-7ZipArchive -Path $packagePath -DestinationPath $pypyToolcachePath
# Get Python version from binaries
$pypyApp = Get-ChildItem -Path "$tempFolder\pypy*.exe" | Where-Object Name -match "pypy(\d+)?.exe" | Select-Object -First 1
$pythonVersion = & $pypyApp -c "import sys;print('{}.{}.{}'.format(sys.version_info[0],sys.version_info[1],sys.version_info[2]))"
$pypyFullVersion = & $pypyApp -c "import sys;print('{}.{}.{}'.format(*sys.pypy_version_info[0:3]))"
Write-Host "Put '$pypyFullVersion' to PYPY_VERSION file"
New-Item -Path "$tempFolder\PYPY_VERSION" -Value $pypyFullVersion | Out-Null
if ($pythonVersion) {
Write-Host "Installing PyPy $pythonVersion"
$pypyVersionPath = Join-Path -Path $pypyToolcachePath -ChildPath $pythonVersion
$pypyArchPath = Join-Path -Path $pypyVersionPath -ChildPath $architecture
Write-Host "Create PyPy '${pythonVersion}' folder in '${pypyVersionPath}'"
New-Item -ItemType Directory -Path $pypyVersionPath -Force | Out-Null
Write-Host "Move PyPy '${pythonVersion}' files to '${pypyArchPath}'"
Invoke-ScriptBlockWithRetry -Command {
Move-Item -Path $tempFolder -Destination $pypyArchPath -ErrorAction Stop | Out-Null
}
Write-Host "Install PyPy '${pythonVersion}' in '${pypyArchPath}'"
if (Test-Path "$pypyArchPath\python.exe") {
cmd.exe /c "cd /d $pypyArchPath && python.exe -m ensurepip && python.exe -m pip install --upgrade pip"
} else {
$pypyName = $pypyApp.Name
cmd.exe /c "cd /d $pypyArchPath && mklink python.exe $pypyName && python.exe -m ensurepip && python.exe -m pip install --upgrade pip"
}
# Create pip.exe if missing
$pipPath = Join-Path -Path $pypyArchPath -ChildPath "Scripts/pip.exe"
if (-not (Test-Path $pipPath)) {
$pip3Path = Join-Path -Path $pypyArchPath -ChildPath "Scripts/pip3.exe"
Copy-Item -Path $pip3Path -Destination $pipPath
}
if ($LASTEXITCODE -ne 0) {
throw "PyPy installation failed with exit code $LASTEXITCODE"
}
Write-Host "Create complete file"
New-Item -ItemType File -Path $pypyVersionPath -Name "$architecture.complete" | Out-Null
} else {
throw "PyPy application is not found. Failed to expand '$packagePath' archive"
}
}
# Get PyPy content from toolset
$toolsetVersions = Get-ToolsetContent | Select-Object -ExpandProperty toolcache | Where-Object Name -eq "PyPy"
# Get PyPy releases
$pypyVersions = Invoke-RestMethod https://downloads.python.org/pypy/versions.json
# required for html parsing
$checksums = (Invoke-RestMethod -Uri 'https://www.pypy.org/checksums.html' | ConvertFrom-HTML).SelectNodes('//*[@id="content"]/article/div/pre')
Write-Host "Start PyPy installation"
foreach ($toolsetVersion in $toolsetVersions.versions) {
# Query latest PyPy version
$latestMajorPyPyVersion = $pypyVersions |
Where-Object { $_.python_version.StartsWith("$toolsetVersion") -and $_.stable -eq $true } |
Select-Object -ExpandProperty files -First 1 |
Where-Object platform -like "win*"
if (-not $latestMajorPyPyVersion) {
throw "Failed to query PyPy version '$toolsetVersion'"
}
$filename = $latestMajorPyPyVersion.filename
Write-Host "Found PyPy '$filename' package"
$tempPyPyPackagePath = Invoke-DownloadWithRetry $latestMajorPyPyVersion.download_url
#region Supply chain security
$distributorFileHash = $null
foreach ($node in $checksums) {
if ($node.InnerText -ilike "*${filename}*") {
$distributorFileHash = $node.InnerText.ToString().Split("`n").Where({ $_ -ilike "*${filename}*" }).Split(' ')[0]
}
}
Test-FileChecksum $tempPyPyPackagePath -ExpectedSHA256Sum $distributorFileHash
#endregion
Install-PyPy -PackagePath $tempPyPyPackagePath -Architecture $toolsetVersions.arch
}
@@ -0,0 +1,11 @@
################################################################################
## File: Install-R.ps1
## Desc: Install R for Windows
################################################################################
Install-ChocoPackage R.Project
Install-ChocoPackage rtools
$rscriptPath = Resolve-Path "C:\Program Files\R\*\bin\x64"
Add-MachinePathItem $rscriptPath
Invoke-PesterTests -TestFile "Tools" -TestName "R"
@@ -0,0 +1,136 @@
################################################################################
## File: Install-RootCA.ps1
## Desc: Install Root CA certificates
################################################################################
# https://www.sysadmins.lv/blog-en/how-to-retrieve-certificate-purposes-property-with-cryptoapi-and-powershell.aspx
# https://www.sysadmins.lv/blog-en/dump-authroot-and-disallowed-certificates-with-powershell.aspx
# https://www.sysadmins.lv/blog-en/constraining-extended-key-usages-in-microsoft-windows.aspx
function Add-ExtendedCertType {
$signature = @"
[DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CertGetCertificateContextProperty(
IntPtr pCertContext,
uint dwPropId,
Byte[] pvData,
ref uint pcbData
);
[DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CertSetCertificateContextProperty(
IntPtr pCertContext,
int dwPropId,
uint dwFlags,
IntPtr pvData
);
"@
Add-Type -MemberDefinition $signature -Namespace PKI -Name Cert
}
function Get-CertificatesWithoutPropId {
# List installed certificates
$certs = Get-ChildItem -Path "Cert:\LocalMachine\Root"
Write-Host "Certificates without CERT_NOT_BEFORE_FILETIME_PROP_ID property"
$certsWithoutPropId = @{}
$certs | ForEach-Object -Process {
$certHandle = $_.Handle
$isPropertySet = [PKI.Cert]::CertGetCertificateContextProperty(
$certHandle, $CERT_NOT_BEFORE_FILETIME_PROP_ID, $null, [ref] $null
)
if (-not $isPropertySet) {
Write-Host "Subject: $($_.Subject)"
$certsWithoutPropId[$_.Thumbprint] = $null
}
}
$certsWithoutPropId
}
function Import-SSTFromWU {
# Serialized Certificate Store File
$sstFile = "$env:TEMP\roots.sst"
# Generate SST from Windows Update
$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
}
$result = certutil.exe -dump $sstFile
if ($LASTEXITCODE -ne 0) {
Write-Host "[Error]: failed to dump $sstFile sst file`n$result"
exit $LASTEXITCODE
}
Import-Certificate -FilePath $sstFile -CertStoreLocation Cert:\LocalMachine\Root
}
function Clear-CertificatesPropId {
param(
[hashtable] $CertsWithoutPropId
)
# List installed certificates
$certs = Get-ChildItem -Path Cert:\LocalMachine\Root
# Clear property CERT_NOT_BEFORE_FILETIME_PROP_ID
$certs | ForEach-Object -Process {
$thumbprint = $_.Thumbprint
if ($certsWithoutPropId.ContainsKey($thumbprint)) {
$subject = $_.Subject
$certHandle = $_.Handle
$result = [PKI.Cert]::CertSetCertificateContextProperty(
$certHandle, $CERT_NOT_BEFORE_FILETIME_PROP_ID, 0, [System.IntPtr]::Zero
)
if ($result) {
Write-Host "[Success] Clear CERT_NOT_BEFORE_FILETIME_PROP_ID property $subject"
} else {
Write-Host "[Fail] Clear CERT_NOT_BEFORE_FILETIME_PROP_ID property $subject"
}
}
}
}
function Disable-RootAutoUpdate {
Write-Host "Disable auto root update mechanism"
$regPath = "HKLM:\Software\Policies\Microsoft\SystemCertificates\AuthRoot"
$regKey = "DisableRootAutoUpdate"
# Create the registry key if it doesn't exist
if (-not (Test-Path $regPath)) {
Write-Verbose "Creating $regPath"
New-Item $regPath | Out-Null
}
Set-ItemProperty $regPath -Name $regKey -Type DWord -Value 1
}
# Property to remove
$CERT_NOT_BEFORE_FILETIME_PROP_ID = 126
# Add extended cert type
Add-ExtendedCertType
# Get certificates without property CERT_NOT_BEFORE_FILETIME_PROP_ID
$certsWithoutPropId = Get-CertificatesWithoutPropId
# Download and install the latest version of root ca list
Import-SSTFromWU
# Clear property CERT_NOT_BEFORE_FILETIME_PROP_ID
if ($certsWithoutPropId.Count -gt 0) {
Clear-CertificatesPropId -CertsWithoutPropId $certsWithoutPropId
} else {
Write-Host "Nothing to clear"
}
# Disable auto root update mechanism
Disable-RootAutoUpdate
@@ -0,0 +1,81 @@
################################################################################
## File: Install-Ruby.ps1
## Desc: Install Ruby using the RubyInstaller2 package and set the default Ruby version
################################################################################
# Most of this logic is from
# https://github.com/ruby/setup-ruby/blob/master/windows.js
function Install-Ruby {
param(
[String] $PackagePath,
[String] $Architecture = "x64"
)
# Create Ruby toolcache folder
$rubyToolcachePath = Join-Path -Path $env:AGENT_TOOLSDIRECTORY -ChildPath "Ruby"
if (-not (Test-Path $rubyToolcachePath)) {
Write-Host "Creating Ruby toolcache folder"
New-Item -ItemType Directory -Path $rubyToolcachePath | Out-Null
}
$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"
$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 {
param(
[Parameter(Mandatory = $true)]
[version] $Version,
[Alias("Arch")]
[string] $Architecture = "x64"
)
$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"
Add-MachinePathItem -PathItem $rubyDir | Out-Null
}
# Install Ruby
$rubyTools = (Get-ToolsetContent).toolcache | Where-Object { $_.name -eq "Ruby" }
$rubyToolVersions = $rubyTools.versions
Write-Host "Starting installation Ruby..."
foreach ($rubyVersion in $rubyToolVersions) {
Write-Host "Starting Ruby $rubyVersion installation"
$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
@@ -0,0 +1,16 @@
################################################################################
## File: Install-Runner.ps1
## Desc: Install Runner for GitHub Actions
## Supply chain security: none
################################################################################
Write-Host "Download latest Runner for GitHub Actions"
$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"
Invoke-PesterTests -TestFile "RunnerCache"
@@ -0,0 +1,51 @@
################################################################################
## File: Install-Rust.ps1
## Desc: Install Rust for Windows
## Supply chain security: checksum validation for bootstrap, managed by rustup for workloads
################################################################################
# Rust Env
$env:RUSTUP_HOME = "C:\Users\Default\.rustup"
$env:CARGO_HOME = "C:\Users\Default\.cargo"
# Download the latest rustup-init.exe for Windows x64
# See https://rustup.rs/#
$rustupPath = Invoke-DownloadWithRetry "https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe"
#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 $rustupPath -ExpectedSHA256Sum $distributorFileHash
#endregion
# Install Rust by running rustup-init.exe (disabling the confirmation prompt with -y)
& $rustupPath -y --default-toolchain=stable --profile=minimal
if ($LASTEXITCODE -ne 0) {
throw "Rust installation failed with exit code $LASTEXITCODE"
}
# Add %USERPROFILE%\.cargo\bin to USER PATH
Add-DefaultPathItem "%USERPROFILE%\.cargo\bin"
# Add Rust binaries to the path
$env:Path += ";$env:CARGO_HOME\bin"
# Add i686 target for building 32-bit binaries
rustup target add i686-pc-windows-msvc
# Add target for building mingw-w64 binaries
rustup target add x86_64-pc-windows-gnu
# Install common tools
rustup component add rustfmt clippy
if ($LASTEXITCODE -ne 0) {
throw "Rust component installation failed with exit code $LASTEXITCODE"
}
# bindgen-cli commenting it
cargo install cbindgen cargo-audit cargo-outdated
if ($LASTEXITCODE -ne 0) {
throw "Rust tools installation failed with exit code $LASTEXITCODE"
}
# Cleanup Cargo crates cache
Remove-Item "${env:CARGO_HOME}\registry\*" -Recurse -Force
Invoke-PesterTests -TestFile "Rust"
@@ -0,0 +1,9 @@
################################################################################
## File: Install-SQLOLEDBDriver.ps1
## Desc: Install OLE DB Driver for SQL Server
################################################################################
Install-Binary -Type MSI `
-Url "https://go.microsoft.com/fwlink/?linkid=2242656" `
-ExtraInstallArgs @("ADDLOCAL=ALL", "IACCEPTMSOLEDBSQLLICENSETERMS=YES") `
-ExpectedSignature '6E78B3DCE2998F6C2457C3E54DA90A01034916AE'
@@ -0,0 +1,20 @@
################################################################################
## File: Install-SQLPowerShellTools.ps1
## Desc: Install SQL PowerShell tool
################################################################################
$baseUrl = "https://download.microsoft.com/download/B/1/7/B1783FE9-717B-4F78-A39A-A2E27E3D679D/ENU/x64"
$signatureThumbrint = "9ACA9419E53D3C9E56396DD2335FF683A8B0B8F3"
# install required MSIs
Install-Binary `
-Url "${baseUrl}/SQLSysClrTypes.msi" `
-ExpectedSignature $signatureThumbrint
Install-Binary `
-Url "${baseUrl}/SharedManagementObjects.msi" `
-ExpectedSignature $signatureThumbrint
Install-Binary `
-Url "${baseUrl}/PowerShellTools.msi" `
-ExpectedSignature $signatureThumbrint
@@ -0,0 +1,15 @@
################################################################################
## File: Install-Sbt.ps1
## Desc: Install sbt for Windows
################################################################################
# Install the latest version of sbt.
# See https://chocolatey.org/packages/sbt
Install-ChocoPackage sbt
$env:SBT_HOME="${env:ProgramFiles(x86)}\sbt"
# Add sbt binaries to the path
Add-MachinePathItem "$env:SBT_HOME\bin"
Invoke-PesterTests -TestFile "Tools" -TestName "Sbt"
@@ -0,0 +1,29 @@
################################################################################
## File: Install-Selenium.ps1
## Desc: Install Selenium Server standalone
################################################################################
# Create Selenium directory
$seleniumDirectory = "C:\selenium\"
New-Item -ItemType directory -Path $seleniumDirectory
# Download Selenium
$seleniumMajorVersion = (Get-ToolsetContent).selenium.version
$seleniumDownloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "SeleniumHQ/selenium" `
-Version "$seleniumMajorVersion.*" `
-Asset "selenium-server-*.jar" `
-AllowMultipleMatches
$seleniumBinPath = Join-Path $seleniumDirectory "selenium-server.jar"
Invoke-DownloadWithRetry -Url $seleniumDownloadUrl -Path $seleniumBinPath
# Create an empty file to retrieve Selenium version
$seleniumFullVersion = $seleniumDownloadUrl.Split("-")[1].Split("/")[0]
New-Item -Path $seleniumDirectory -Name "selenium-server-$seleniumFullVersion"
# Add SELENIUM_JAR_PATH environment variable
[Environment]::SetEnvironmentVariable("SELENIUM_JAR_PATH", $seleniumBinPath, "Machine")
Invoke-PesterTests -TestFile "Browsers" -TestName "Selenium"
@@ -0,0 +1,29 @@
################################################################################
## File: Install-ServiceFabricSDK.ps1
## Desc: Install webpicmd and then the service fabric sdk
## must be install after Visual Studio
## Supply chain security: checksum validation
################################################################################
# Creating 'Installer' cache folder if it doesn't exist
New-Item -Path 'C:\Windows\Installer' -ItemType Directory -Force
# Get Service Fabric components versions
$runtimeVersion = (Get-ToolsetContent).serviceFabric.runtime.version
$sdkVersion = (Get-ToolsetContent).serviceFabric.sdk.version
$urlBase = "https://download.microsoft.com/download/b/8/a/b8a2fb98-0ec1-41e5-be98-9d8b5abf7856"
# Install Service Fabric Runtime for Windows
Install-Binary `
-Url "${urlBase}/MicrosoftServiceFabric.${runtimeVersion}.exe" `
-InstallArgs @("/accepteula ", "/quiet", "/force") `
-ExpectedSHA256Sum (Get-ToolsetContent).serviceFabric.runtime.checksum
# Install Service Fabric SDK
Install-Binary `
-Url "${urlBase}/MicrosoftServiceFabricSDK.${sdkVersion}.msi" `
-ExpectedSHA256Sum (Get-ToolsetContent).serviceFabric.sdk.checksum
Invoke-PesterTests -TestFile "Tools" -TestName "ServiceFabricSDK"
@@ -0,0 +1,35 @@
################################################################################
## File: Install-Stack.ps1
## Desc: Install Stack for Windows
## Supply chain security: Stack - checksum validation
################################################################################
Write-Host "Get the latest Stack version..."
$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"
$destinationPath = Join-Path $stackToolcachePath "x64"
$stackArchivePath = Invoke-DownloadWithRetry $downloadUrl
#region Supply chain security - Stack
$externalHash = Get-ChecksumFromUrl -Type "SHA256" `
-Url "$downloadUrl.sha256" `
-FileName (Split-Path $downloadUrl -Leaf)
Test-FileChecksum $stackArchivePath -ExpectedSHA256Sum $externalHash
#endregion
Write-Host "Expand stack archive"
Expand-7ZipArchive -Path $stackArchivePath -DestinationPath $destinationPath
New-Item -Name "x64.complete" -Path $stackToolcachePath
Add-MachinePathItem -PathItem $destinationPath
Invoke-PesterTests -TestFile "Tools" -TestName "Stack"
@@ -0,0 +1,60 @@
################################################################################
## File: Install-Toolset.ps1
## Team: CI-Build
## Desc: Install toolset
################################################################################
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13
Function Install-Asset {
param(
[Parameter(Mandatory=$true)]
[object] $ReleaseAsset
)
$releaseAssetName = [System.IO.Path]::GetFileNameWithoutExtension($ReleaseAsset.filename)
$assetFolderPath = Join-Path $env:TEMP $releaseAssetName
$assetArchivePath = Invoke-DownloadWithRetry $ReleaseAsset.download_url
Write-Host "Extract $($ReleaseAsset.filename) content..."
if ($assetArchivePath.EndsWith(".tar.gz")) {
$assetTarPath = $assetArchivePath.TrimEnd(".tar.gz")
Expand-7ZipArchive -Path $assetArchivePath -DestinationPath $assetTarPath
Expand-7ZipArchive -Path $assetTarPath -DestinationPath $assetFolderPath
} else {
Expand-7ZipArchive -Path $assetArchivePath -DestinationPath $assetFolderPath
}
Write-Host "Invoke installation script..."
Push-Location -Path $assetFolderPath
Invoke-Expression .\setup.ps1
Pop-Location
}
# Get toolcache content from toolset
$toolsToInstall = @("Python", "Node", "Go")
$tools = Get-ToolsetContent | Select-Object -ExpandProperty toolcache | Where-Object { $toolsToInstall -contains $_.Name }
foreach ($tool in $tools) {
# Get versions manifest for current tool
# Invoke-RestMethod doesn't support retry in PowerShell 5.1
$assets = Invoke-ScriptBlockWithRetry -Command {
Invoke-RestMethod $tool.url
}
# Get github release asset for each version
foreach ($toolVersion in $tool.versions) {
$asset = $assets `
| Where-Object version -like $toolVersion `
| Select-Object -ExpandProperty files `
| 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)..."
Install-Asset -ReleaseAsset $asset
}
}
@@ -0,0 +1,6 @@
################################################################################
## File: Install-TortoiseSvn.ps1
## Desc: Install TortoiseSvn
################################################################################
Install-ChocoPackage tortoisesvn
@@ -0,0 +1,20 @@
################################################################################
## File: Install-VCRedist.ps1
## Desc: Install Visual C++ Redistributable
## Supply chain security: checksum validation
################################################################################
$baseUrl = "https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC"
$argumentList = ("/install", "/quiet", "/norestart")
Install-Binary `
-Url "${baseUrl}/vcredist_x86.exe" `
-InstallArgs $argumentList `
-ExpectedSHA256Sum '99DCE3C841CC6028560830F7866C9CE2928C98CF3256892EF8E6CF755147B0D8'
Install-Binary `
-Url "${baseUrl}/vcredist_x64.exe" `
-InstallArgs $argumentList `
-ExpectedSHA256Sum 'F3B7A76D84D23F91957AA18456A14B4E90609E4CE8194C5653384ED38DADA6F3'
Invoke-PesterTests -TestFile "Tools" -TestName "VCRedist"
@@ -0,0 +1,27 @@
###################################################################################
## File: Install-VSExtensions.ps1
## Desc: Install the Visual Studio Extensions from toolset.json
###################################################################################
$toolset = Get-ToolsetContent
$vsixPackagesList = $toolset.visualStudio.vsix
if (-not $vsixPackagesList) {
Write-Host "No extensions to install"
exit 0
}
$vsixPackagesList | ForEach-Object {
# Retrieve cdn endpoint to avoid HTTP error 429
# https://github.com/actions/runner-images/issues/3074
$vsixPackage = Get-VsixInfoFromMarketplace $_
Write-Host "Installing $vsixPackage"
if ($vsixPackage.FileName.EndsWith(".vsix")) {
Install-VSIXFromUrl $vsixPackage.DownloadUri
} else {
Install-Binary `
-Url $vsixPackage.DownloadUri `
-InstallArgs @('/install', '/quiet', '/norestart')
}
}
Invoke-PesterTests -TestFile "Vsix"
@@ -0,0 +1,27 @@
################################################################################
## File: Install-Vcpkg.ps1
## Desc: Install vcpkg
################################################################################
$Uri = 'https://github.com/Microsoft/vcpkg.git'
$InstallDir = 'C:\vcpkg'
$VcpkgExecPath = 'vcpkg.exe'
git clone $Uri $InstallDir -q
# Build and integrate vcpkg
Invoke-Expression "$InstallDir\bootstrap-vcpkg.bat"
if ($LASTEXITCODE -ne 0) {
throw "vcpkg bootstrap failed with exit code $LASTEXITCODE"
}
Invoke-Expression "$InstallDir\$VcpkgExecPath integrate install"
if ($LASTEXITCODE -ne 0) {
throw "vcpkg integration failed with exit code $LASTEXITCODE"
}
# Add vcpkg to system environment
Add-MachinePathItem $InstallDir
[Environment]::SetEnvironmentVariable("VCPKG_INSTALLATION_ROOT", $InstallDir, "Machine")
Update-Environment
Invoke-PesterTests -TestFile "Tools" -TestName "Vcpkg"
@@ -0,0 +1,57 @@
################################################################################
## File: Install-VisualStudio.ps1
## Desc: Install Visual Studio
################################################################################
$vsToolset = (Get-ToolsetContent).visualStudio
# Install VS
Install-VisualStudio `
-Version $vsToolset.subversion `
-Edition $vsToolset.edition `
-Channel $vsToolset.channel `
-RequiredComponents $vsToolset.workloads `
-ExtraArgs "--allWorkloads --includeRecommended --remove Component.CPython3.x64" `
-SignatureThumbprint $vsToolset.signature
# Find the version of VS installed for this instance
# Only supports a single instance
$vsProgramData = Get-Item -Path "C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances"
$instanceFolders = Get-ChildItem -Path $vsProgramData.FullName
if ($instanceFolders -is [array]) {
throw "More than one instance installed"
}
# Updating content of MachineState.json file to disable autoupdate of VSIX extensions
$vsInstallRoot = (Get-VisualStudioInstance).InstallationPath
$newContent = '{"Extensions":[{"Key":"1e906ff5-9da8-4091-a299-5c253c55fdc9","Value":{"ShouldAutoUpdate":false}},{"Key":"Microsoft.VisualStudio.Web.AzureFunctions","Value":{"ShouldAutoUpdate":false}}],"ShouldAutoUpdate":false,"ShouldCheckForUpdates":false}'
Set-Content -Path "$vsInstallRoot\Common7\IDE\Extensions\MachineState.json" -Value $newContent
if (Test-IsWin19) {
# Install Windows 10 SDK version 10.0.14393.795
Install-Binary -Type EXE `
-Url 'https://go.microsoft.com/fwlink/p/?LinkId=838916' `
-InstallArgs @("/q", "/norestart", "/ceip off", "/features OptionId.WindowsSoftwareDevelopmentKit") `
-ExpectedSignature 'C91545B333C52C4465DE8B90A3FAF4E1D9C58DFA'
# Install Windows 11 SDK version 10.0.22621.0
Install-Binary -Type EXE `
-Url 'https://go.microsoft.com/fwlink/p/?linkid=2196241' `
-InstallArgs @("/q", "/norestart", "/ceip off", "/features OptionId.UWPManaged OptionId.UWPCPP OptionId.UWPLocalized OptionId.DesktopCPPx86 OptionId.DesktopCPPx64 OptionId.DesktopCPParm64") `
-ExpectedSignature 'E4C5C5FCDB68B930EE4E19BC25D431EF6D864C51'
}
if (Test-IsWin22) {
# Install Windows 10 SDK version 10.0.17763
Install-Binary -Type EXE `
-Url 'https://go.microsoft.com/fwlink/p/?LinkID=2033908' `
-InstallArgs @("/q", "/norestart", "/ceip off", "/features OptionId.UWPManaged OptionId.UWPCPP OptionId.UWPLocalized OptionId.DesktopCPPx86 OptionId.DesktopCPPx64 OptionId.DesktopCPParm64") `
-ExpectedSignature '7535269B94C1FEA4A5EF6D808E371DA242F27936'
}
if (Test-IsWin25){
Write-Host "It is for windows-25 testing"
}
# Disable pester tests for now
# Invoke-PesterTests -TestFile "VisualStudio"
@@ -0,0 +1,40 @@
################################################################################
## File: Install-WDK.ps1
## Desc: Install the Windows Driver Kit
################################################################################
# Requires Windows SDK with the same version number as the WDK
if (Test-IsWin19) {
# Install all features without showing the GUI using winsdksetup.exe
Install-Binary -Type EXE `
-Url 'https://go.microsoft.com/fwlink/?linkid=2173743' `
-InstallArgs @("/features", "+", "/quiet") `
-ExpectedSignature '44796EB5BD439B4BFB078E1DC2F8345AE313CBB1'
$wdkUrl = "https://go.microsoft.com/fwlink/?linkid=2166289"
$wdkSignatureThumbprint = "914A09C2E02C696AF394048BCB8D95449BCD5B9E"
$wdkExtensionPath = "C:\Program Files (x86)\Windows Kits\10\Vsix\VS2019\WDK.vsix"
} elseif (Test-IsWin22) {
# SDK is available through Visual Studio
$wdkUrl = "https://go.microsoft.com/fwlink/?linkid=2249371"
$wdkSignatureThumbprint = "7C94971221A799907BB45665663BBFD587BAC9F8"
$wdkExtensionPath = "C:\Program Files (x86)\Windows Kits\10\Vsix\VS2022\*\WDK.vsix"
} elseif (Test-IsWin25) {
# SDK is available through Visual Studio
$wdkUrl = "https://go.microsoft.com/fwlink/?linkid=2249371"
$wdkSignatureThumbprint = "7C94971221A799907BB45665663BBFD587BAC9F8"
$wdkExtensionPath = "C:\Program Files (x86)\Windows Kits\10\Vsix\VS2022\*\WDK.vsix"
}else {
throw "Invalid version of Visual Studio is found. Either 2019 or 2022 are required"
}
# Install all features without showing the GUI using wdksetup.exe
Install-Binary -Type EXE `
-Url $wdkUrl `
-InstallArgs @("/features", "+", "/quiet") `
-ExpectedSignature $wdkSignatureThumbprint
# Need to install the VSIX to get the build targets when running VSBuild
Install-VSIXFromFile (Resolve-Path -Path $wdkExtensionPath)
Invoke-PesterTests -TestFile "WDK"
@@ -0,0 +1,10 @@
################################################################################
## File: Install-WebPI.ps1
## Desc: Install WebPlatformInstaller
################################################################################
Install-Binary -Type MSI `
-Url 'http://go.microsoft.com/fwlink/?LinkId=287166' `
-ExpectedSignature 'C3A3D43788E7ABCD287CB4F5B6583043774F99D2'
Invoke-PesterTests -TestFile "Tools" -TestName "WebPlatformInstaller"
@@ -0,0 +1,16 @@
####################################################################################
## File: Install-WinAppDriver.ps1
## Desc: Install Windows Application Driver (WinAppDriver)
####################################################################################
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$downloadUrl = Resolve-GithubReleaseAssetUrl `
-Repo "microsoft/WinAppDriver" `
-Version "latest" `
-UrlMatchPattern "WindowsApplicationDriver_*.msi"
Install-Binary `
-Url $downloadUrl `
-ExpectedSignature '2485A7AFA98E178CB8F30C9838346B514AEA4769'
Invoke-PesterTests -TestFile "WinAppDriver" -TestName "WinAppDriver"
@@ -0,0 +1,47 @@
####################################################################################
## File: Install-WindowsFeatures.ps1
## Desc: Install Windows Features
####################################################################################
$windowsFeatures = (Get-ToolsetContent).windowsFeatures
foreach ($feature in $windowsFeatures) {
if ($feature.optionalFeature) {
Write-Host "Activating Windows Optional Feature '$($feature.name)'..."
Enable-WindowsOptionalFeature -Online -FeatureName $feature.name -NoRestart
$resultSuccess = $?
} else {
Write-Host "Activating Windows Feature '$($feature.name)'..."
$arguments = @{
Name = $feature.name
IncludeAllSubFeature = [System.Convert]::ToBoolean($feature.includeAllSubFeatures)
IncludeManagementTools = [System.Convert]::ToBoolean($feature.includeManagementTools)
}
if ($feature.name -eq "NET-Framework-Features") {
$arguments += @{ LogPath = $(Join-Path $env:IMAGE_FOLDER "NET-Framework-Features.log") }
}
$result = Install-WindowsFeature @arguments
$resultSuccess = $result.Success
}
if ($feature.name -eq "NET-Framework-Features") {
$dotNetFeatureLog = Get-Content -Path $(Join-Path $env:IMAGE_FOLDER "NET-Framework-Features.log")
Write-Host "The log of NET-Framework-Features"
Write-Host $dotNetFeatureLog
}
if ($resultSuccess) {
Write-Host "Windows Feature '$($feature.name)' was activated successfully"
} else {
throw "Failed to activate Windows Feature '$($feature.name)'"
}
}
# it improves Android emulator launch on Windows Server
# https://learn.microsoft.com/en-us/windows-server/virtualization/hyper-v/manage/manage-hyper-v-scheduler-types
bcdedit /set hypervisorschedulertype root
if ($LASTEXITCODE -ne 0) {
throw "Failed to set hypervisorschedulertype to root"
}
@@ -0,0 +1,50 @@
################################################################################
## File: Install-WindowsUpdates.ps1
## Desc: Install Windows Updates.
## Should be run at end, just before SoftwareReport and Finalize-VM.ps1.
################################################################################
function Install-WindowsUpdates {
Write-Host "Starting wuauserv"
Start-Service -Name wuauserv -PassThru | Out-Host
# Temporarily exclude Windows update KB5034439 since it throws an error.
# The known issue (https://support.microsoft.com/en-au/topic/kb5034439-windows-recovery-environment-update-for-azure-stack-hci-version-22h2-and-windows-server-2022-january-9-2024-6f9d26e6-784c-4503-a3c6-0beedda443ca)
Write-Host "Getting list of available windows updates"
# Added KB5044030 to the excluded list since it is failing for 2025
$excludedKBs = @()
if (Test-IsWin25) {
$excludedKBs = @("KB5034439", "KB5044030", "KB5044284")
}
else {
$excludedKBs = @("KB5034439")
}
Get-WindowsUpdate -MicrosoftUpdate -NotKBArticleID $excludedKBs -OutVariable updates | Out-Host
if ( -not $updates ) {
Write-Host "There are no windows updates to install"
return
}
Write-Host "Installing windows updates"
Get-WindowsUpdate -MicrosoftUpdate -NotKBArticleID $excludedKBs -AcceptAll -Install -IgnoreUserInput -IgnoreReboot | Out-Host
Write-Host "Validating windows updates installation"
# Get-WUHistory doesn't support Windows Server 2022
$notFailedUpdateNames = Get-WindowsUpdateStates | Where-Object { $_.State -in ("Installed", "Running") } | Select-Object -ExpandProperty Title
# We ignore Microsoft Defender Antivirus updates; Azure service updates AV automatically
$failedUpdates = $updates[0] | Where-Object Title -notmatch "Microsoft Defender Antivirus" | Where-Object { -not ($notFailedUpdateNames -match $_.KB) }
if ( $failedUpdates ) {
throw "Windows updates failed to install: $($failedUpdates.KB)"
}
}
Install-WindowsUpdates
# Create complete windows update file
New-Item -Path $env:windir -Name WindowsUpdateDone.txt -ItemType File | Out-Null
@@ -0,0 +1,12 @@
################################################################################
## File: Install-WindowsUpdatesAfterReboot.ps1
## Desc: Waits for Windows Updates to finish installing after reboot
################################################################################
Invoke-ScriptBlockWithRetry -RetryCount 10 -RetryIntervalSeconds 120 -Command {
$inProgress = Get-WindowsUpdateStates | Where-Object State -eq "Running" | Where-Object Title -notmatch "Microsoft Defender Antivirus"
if ( $inProgress ) {
$title = $inProgress.Title -join "`n"
throw "Windows updates are still installing: $title"
}
}
@@ -0,0 +1,14 @@
################################################################################
## File: Install-Wix.ps1
## Desc: Install WIX.
################################################################################
Install-ChocoPackage wixtoolset -ArgumentList "--force"
Update-Environment
$currentPath = [System.Environment]::GetEnvironmentVariable("PATH", "Machine")
$newPath = $currentPath + ";$(Join-Path -Path $env:WIX -ChildPath "bin")"
[Environment]::SetEnvironmentVariable("PATH", $newPath, "Machine")
Update-Environment
Invoke-PesterTests -TestFile "Wix"
@@ -0,0 +1,29 @@
################################################################################
## File: Install-Zstd.ps1
## Desc: Install zstd
################################################################################
$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
$filesInArchive = 7z l $zstdArchivePath | Out-String
if ($filesInArchive.Contains($zstdName)) {
Expand-7ZipArchive -Path $zstdArchivePath -DestinationPath $toolPath
Invoke-ScriptBlockWithRetry -Command {
Move-Item -Path "${zstdPath}*" -Destination $zstdPath -ErrorAction Stop
}
} else {
Expand-7ZipArchive -Path $zstdArchivePath -DestinationPath $zstdPath
}
# Add zstd-win64 to PATH
Add-MachinePathItem $zstdPath
Invoke-PesterTests -TestFile "Tools" -TestName "Zstd"
@@ -0,0 +1,253 @@
using module ./software-report-base/SoftwareReport.psm1
using module ./software-report-base/SoftwareReport.Nodes.psm1
$global:ErrorActionPreference = "Stop"
$global:ProgressPreference = "SilentlyContinue"
$ErrorView = "NormalView"
Set-StrictMode -Version Latest
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Android.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Browsers.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.CachedTools.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Common.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Databases.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Helpers.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Tools.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Java.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.WebServers.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.VisualStudio.psm1") -DisableNameChecking
# Software report
$softwareReport = [SoftwareReport]::new($(Build-OSInfoSection))
$optionalFeatures = $softwareReport.Root.AddHeader("Windows features")
$optionalFeatures.AddToolVersion("Windows Subsystem for Linux (WSLv1):", "Enabled")
$installedSoftware = $softwareReport.Root.AddHeader("Installed Software")
# Language and Runtime
$languageAndRuntime = $installedSoftware.AddHeader("Language and Runtime")
$languageAndRuntime.AddToolVersion("Bash", $(Get-BashVersion))
$languageAndRuntime.AddToolVersion("Go", $(Get-GoVersion))
$languageAndRuntime.AddToolVersion("Julia", $(Get-JuliaVersion))
$languageAndRuntime.AddToolVersion("Kotlin", $(Get-KotlinVersion))
$languageAndRuntime.AddToolVersion("LLVM", $(Get-LLVMVersion))
$languageAndRuntime.AddToolVersion("Node", $(Get-NodeVersion))
$languageAndRuntime.AddToolVersion("Perl", $(Get-PerlVersion))
$languageAndRuntime.AddToolVersion("PHP", $(Get-PHPVersion))
$languageAndRuntime.AddToolVersion("Python", $(Get-PythonVersion))
$languageAndRuntime.AddToolVersion("Ruby", $(Get-RubyVersion))
# Package Management
$packageManagement = $installedSoftware.AddHeader("Package Management")
$packageManagement.AddToolVersion("Chocolatey", $(Get-ChocoVersion))
$packageManagement.AddToolVersion("Composer", $(Get-ComposerVersion))
$packageManagement.AddToolVersion("Helm", $(Get-HelmVersion))
$packageManagement.AddToolVersion("Miniconda", $(Get-CondaVersion))
$packageManagement.AddToolVersion("NPM", $(Get-NPMVersion))
$packageManagement.AddToolVersion("NuGet", $(Get-NugetVersion))
$packageManagement.AddToolVersion("pip", $(Get-PipVersion))
$packageManagement.AddToolVersion("Pipx", $(Get-PipxVersion))
$packageManagement.AddToolVersion("RubyGems", $(Get-RubyGemsVersion))
$packageManagement.AddToolVersion("Vcpkg", $(Get-VcpkgVersion))
$packageManagement.AddToolVersion("Yarn", $(Get-YarnVersion))
$packageManagement.AddHeader("Environment variables").AddTable($(Build-PackageManagementEnvironmentTable))
# Project Management
$projectManagement = $installedSoftware.AddHeader("Project Management")
$projectManagement.AddToolVersion("Ant", $(Get-AntVersion))
$projectManagement.AddToolVersion("Gradle", $(Get-GradleVersion))
$projectManagement.AddToolVersion("Maven", $(Get-MavenVersion))
$projectManagement.AddToolVersion("sbt", $(Get-SbtVersion))
# Tools
$tools = $installedSoftware.AddHeader("Tools")
$tools.AddToolVersion("7zip", $(Get-7zipVersion))
$tools.AddToolVersion("aria2", $(Get-Aria2Version))
$tools.AddToolVersion("azcopy", $(Get-AzCopyVersion))
$tools.AddToolVersion("Bazel", $(Get-BazelVersion))
$tools.AddToolVersion("Bazelisk", $(Get-BazeliskVersion))
$tools.AddToolVersion("Bicep", $(Get-BicepVersion))
$tools.AddToolVersion("Cabal", $(Get-CabalVersion))
$tools.AddToolVersion("CMake", $(Get-CMakeVersion))
$tools.AddToolVersion("CodeQL Action Bundle", $(Get-CodeQLBundleVersion))
$tools.AddToolVersion("Docker", $(Get-DockerVersion))
$tools.AddToolVersion("Docker Compose v2", $(Get-DockerComposeVersionV2))
$tools.AddToolVersion("Docker-wincred", $(Get-DockerWincredVersion))
$tools.AddToolVersion("ghc", $(Get-GHCVersion))
$tools.AddToolVersion("Git", $(Get-GitVersion))
$tools.AddToolVersion("Git LFS", $(Get-GitLFSVersion))
if (Test-IsWin19) {
$tools.AddToolVersion("Google Cloud CLI", $(Get-GoogleCloudCLIVersion))
}
$tools.AddToolVersion("ImageMagick", $(Get-ImageMagickVersion))
if (-not (Test-IsWin25)) {
$tools.AddToolVersion("InnoSetup", $(Get-InnoSetupVersion))
}
$tools.AddToolVersion("jq", $(Get-JQVersion))
$tools.AddToolVersion("Kind", $(Get-KindVersion))
$tools.AddToolVersion("Kubectl", $(Get-KubectlVersion))
if (-not (Test-IsWin25)) {
$tools.AddToolVersion("Mercurial", $(Get-MercurialVersion))
}
$tools.AddToolVersion("gcc", $(Get-GCCVersion))
$tools.AddToolVersion("gdb", $(Get-GDBVersion))
$tools.AddToolVersion("GNU Binutils", $(Get-GNUBinutilsVersion))
$tools.AddToolVersion("Newman", $(Get-NewmanVersion))
if (-not (Test-IsWin25)) {
$tools.AddToolVersion("NSIS", $(Get-NSISVersion))
}
$tools.AddToolVersion("OpenSSL", $(Get-OpenSSLVersion))
$tools.AddToolVersion("Packer", $(Get-PackerVersion))
if (Test-IsWin19) {
$tools.AddToolVersion("Parcel", $(Get-ParcelVersion))
}
$tools.AddToolVersion("Pulumi", $(Get-PulumiVersion))
$tools.AddToolVersion("R", $(Get-RVersion))
$tools.AddToolVersion("Service Fabric SDK", $(Get-ServiceFabricSDKVersion))
$tools.AddToolVersion("Stack", $(Get-StackVersion))
#$tools.AddToolVersion("Swift", $(Get-SwiftVersion))
if (-not (Test-IsWin25)) {
$tools.AddToolVersion("Subversion (SVN)", $(Get-SVNVersion))
}
$tools.AddToolVersion("Swig", $(Get-SwigVersion))
$tools.AddToolVersion("VSWhere", $(Get-VSWhereVersion))
$tools.AddToolVersion("WinAppDriver", $(Get-WinAppDriver))
$tools.AddToolVersion("WiX Toolset", $(Get-WixVersion))
$tools.AddToolVersion("yamllint", $(Get-YAMLLintVersion))
$tools.AddToolVersion("zstd", $(Get-ZstdVersion))
# CLI Tools
$cliTools = $installedSoftware.AddHeader("CLI Tools")
if (-not (Test-IsWin25)) {
$cliTools.AddToolVersion("Alibaba Cloud CLI", $(Get-AlibabaCLIVersion))
}
$cliTools.AddToolVersion("AWS CLI", $(Get-AWSCLIVersion))
$cliTools.AddToolVersion("AWS SAM CLI", $(Get-AWSSAMVersion))
$cliTools.AddToolVersion("AWS Session Manager CLI", $(Get-AWSSessionManagerVersion))
$cliTools.AddToolVersion("Azure CLI", $(Get-AzureCLIVersion))
$cliTools.AddToolVersion("Azure DevOps CLI extension", $(Get-AzureDevopsExtVersion))
if (Test-IsWin19) {
$cliTools.AddToolVersion("Cloud Foundry CLI", $(Get-CloudFoundryVersion))
}
$cliTools.AddToolVersion("GitHub CLI", $(Get-GHVersion))
# Rust Tools
Initialize-RustEnvironment
$rustTools = $installedSoftware.AddHeader("Rust Tools")
$rustTools.AddToolVersion("Cargo", $(Get-RustCargoVersion))
$rustTools.AddToolVersion("Rust", $(Get-RustVersion))
$rustTools.AddToolVersion("Rustdoc", $(Get-RustdocVersion))
$rustTools.AddToolVersion("Rustup", $(Get-RustupVersion))
$rustToolsPackages = $rustTools.AddHeader("Packages")
if (-not (Test-IsWin25)) {
$rustToolsPackages.AddToolVersion("bindgen", $(Get-BindgenVersion))
}
$rustToolsPackages.AddToolVersion("cargo-audit", $(Get-CargoAuditVersion))
$rustToolsPackages.AddToolVersion("cargo-outdated", $(Get-CargoOutdatedVersion))
$rustToolsPackages.AddToolVersion("cbindgen", $(Get-CbindgenVersion))
$rustToolsPackages.AddToolVersion("Clippy", $(Get-RustClippyVersion))
$rustToolsPackages.AddToolVersion("Rustfmt", $(Get-RustfmtVersion))
# Browsers and Drivers
$browsersAndWebdrivers = $installedSoftware.AddHeader("Browsers and Drivers")
$browsersAndWebdrivers.AddNodes($(Build-BrowserSection))
$browsersAndWebdrivers.AddHeader("Environment variables").AddTable($(Build-BrowserWebdriversEnvironmentTable))
# Java
$installedSoftware.AddHeader("Java").AddTable($(Get-JavaVersions))
# Shells
$installedSoftware.AddHeader("Shells").AddTable($(Get-ShellTarget))
# MSYS2
$msys2 = $installedSoftware.AddHeader("MSYS2")
$msys2.AddToolVersion("Pacman", $(Get-PacmanVersion))
$notes = @'
Location: C:\msys64
Note: MSYS2 is pre-installed on image but not added to PATH.
'@
$msys2.AddHeader("Notes").AddNote($notes)
# BizTalk Server
if (Test-IsWin19)
{
$installedSoftware.AddHeader("BizTalk Server").AddNode($(Get-BizTalkVersion))
}
# Cached Tools
$installedSoftware.AddHeader("Cached Tools").AddNodes($(Build-CachedToolsSection))
# Databases
$databases = $installedSoftware.AddHeader("Databases")
$databases.AddHeader("PostgreSQL").AddTable($(Get-PostgreSQLTable))
$databases.AddHeader("MongoDB").AddTable($(Get-MongoDBTable))
# Database tools
$databaseTools = $installedSoftware.AddHeader("Database tools")
$databaseTools.AddToolVersion("Azure CosmosDb Emulator", $(Get-AzCosmosDBEmulatorVersion))
$databaseTools.AddToolVersion("DacFx", $(Get-DacFxVersion))
$databaseTools.AddToolVersion("MySQL", $(Get-MySQLVersion))
$databaseTools.AddToolVersion("SQL OLEDB Driver", $(Get-SQLOLEDBDriverVersion))
$databaseTools.AddToolVersion("SQLPS", $(Get-SQLPSVersion))
if (Test-IsWin25) {
$databaseTools.AddToolVersion("MongoDB Shell (mongosh)", $(Get-MongoshVersion))
}
# Web Servers
$installedSoftware.AddHeader("Web Servers").AddTable($(Build-WebServersSection))
# Visual Studio
$vsTable = Get-VisualStudioVersion
$visualStudio = $installedSoftware.AddHeader($vsTable.Name)
$visualStudio.AddTable($vsTable)
$workloads = $visualStudio.AddHeader("Workloads, components and extensions")
$workloads.AddTable((Get-VisualStudioComponents) + (Get-VisualStudioExtensions))
$msVisualCpp = $visualStudio.AddHeader("Microsoft Visual C++")
$msVisualCpp.AddTable($(Get-VisualCPPComponents))
$visualStudio.AddToolVersionsList("Installed Windows SDKs", $(Get-WindowsSDKs).Versions, '^.+')
# .NET Core Tools
$netCoreTools = $installedSoftware.AddHeader(".NET Core Tools")
if (Test-IsWin19) {
# Visual Studio 2019 brings own version of .NET Core which is different from latest official version
$netCoreTools.AddToolVersionsListInline(".NET Core SDK", $(Get-DotnetSdks).Versions, '^\d+\.\d+\.\d{2}')
} else {
$netCoreTools.AddToolVersionsListInline(".NET Core SDK", $(Get-DotnetSdks).Versions, '^\d+\.\d+\.\d')
}
$netCoreTools.AddToolVersionsListInline(".NET Framework", $(Get-DotnetFrameworkVersions), '^.+')
Get-DotnetRuntimes | ForEach-Object {
$netCoreTools.AddToolVersionsListInline($_.Runtime, $_.Versions, '^.+')
}
$netCoreTools.AddNodes($(Get-DotnetTools))
# PowerShell Tools
$psTools = $installedSoftware.AddHeader("PowerShell Tools")
$psTools.AddToolVersion("PowerShell", $(Get-PowershellCoreVersion))
$psModules = $psTools.AddHeader("Powershell Modules")
$psModules.AddNodes($(Get-PowerShellModules))
$azPsNotes = @'
Azure PowerShell module 2.1.0 and AzureRM PowerShell module 2.1.0 are installed
and are available via 'Get-Module -ListAvailable'.
All other versions are saved but not installed.
'@
$psModules.AddNote($azPsNotes)
# Android
$android = $installedSoftware.AddHeader("Android")
$android.AddTable($(Build-AndroidTable))
$android.AddHeader("Environment variables").AddTable($(Build-AndroidEnvironmentTable))
# Cached Docker images
$installedSoftware.AddHeader("Cached Docker images").AddTable($(Get-CachedDockerImagesTableData))
# Generate reports
$softwareReport.ToJson() | Out-File -FilePath "C:\software-report.json" -Encoding UTF8NoBOM
$softwareReport.ToMarkdown() | Out-File -FilePath "C:\software-report.md" -Encoding UTF8NoBOM
@@ -0,0 +1,174 @@
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Helpers.psm1") -DisableNameChecking
function Split-TableRowByColumns {
param(
[string] $Row
)
return $Row.Split("|") | ForEach-Object { $_.trim() }
}
function Get-AndroidSDKRoot {
param(
[string] $ComponentName
)
$path = Join-Path $env:ANDROID_HOME $ComponentName
return "Location $path"
}
function Build-AndroidTable {
$packageInfo = Get-AndroidInstalledPackages
return @(
@{
"Package" = "Android Command Line Tools"
"Version" = Get-AndroidCommandLineToolsVersion
},
@{
"Package" = "Android Emulator"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "Android Emulator"
},
@{
"Package" = "Android SDK Build-tools"
"Version" = Get-AndroidBuildToolVersions -PackageInfo $packageInfo
},
@{
"Package" = "Android SDK Platforms"
"Version" = Get-AndroidPlatformVersions -PackageInfo $packageInfo
},
@{
"Package" = "Android SDK Platform-Tools"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "Android SDK Platform-Tools"
},
@{
"Package" = "Android Support Repository"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "Android Support Repository"
},
@{
"Package" = "CMake"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "cmake"
},
@{
"Package" = "Google APIs"
"Version" = Get-AndroidGoogleAPIsVersions -PackageInfo $packageInfo
},
@{
"Package" = "Google Play services"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "Google Play services"
},
@{
"Package" = "Google Repository"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "Google Repository"
},
@{
"Package" = "NDK"
"Version" = Get-AndroidNdkVersions -PackageInfo $packageInfo
},
@{
"Package" = "SDK Patch Applier v4"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "SDK Patch Applier v4"
}
) | Where-Object { $_.Version } | ForEach-Object {
[PSCustomObject] @{
"Package Name" = $_.Package
"Version" = $_.Version
}
}
}
function Get-AndroidPackageVersions {
param (
[Parameter(Mandatory)]
[object] $PackageInfo,
[Parameter(Mandatory)]
[object] $MatchedString
)
$versions = $packageInfo | Where-Object { $_ -Match $MatchedString } | ForEach-Object {
$packageInfoParts = Split-TableRowByColumns $_
return $packageInfoParts[1]
}
return ($versions -Join "<br>")
}
function Get-AndroidPlatformVersions {
param (
[Parameter(Mandatory)]
[object] $PackageInfo
)
$versions = $packageInfo | Where-Object { $_ -Match "Android SDK Platform " } | ForEach-Object {
$packageInfoParts = Split-TableRowByColumns $_
$revision = $packageInfoParts[1]
$version = $packageInfoParts[0].split(";")[1]
return "$version (rev $revision)"
}
[array]::Reverse($versions)
return ($versions -Join "<br>")
}
function Get-AndroidCommandLineToolsVersion {
$commandLineTools = (Join-Path $env:ANDROID_HOME "cmdline-tools\latest\bin\sdkmanager.bat")
(cmd /c "$commandLineTools --version 2>NUL" | Out-String).Trim() -match "(?<version>^(\d+\.){1,}\d+$)" | Out-Null
$commandLineToolsVersion = $Matches.Version
return $commandLineToolsVersion
}
function Get-AndroidBuildToolVersions {
param (
[Parameter(Mandatory)]
[object] $PackageInfo
)
$versions = $packageInfo | Where-Object { $_ -Match "Android SDK Build-Tools" } | ForEach-Object {
$packageInfoParts = Split-TableRowByColumns $_
return $packageInfoParts[1]
}
$groupVersions = @()
$versions | ForEach-Object {
$majorVersion = $_.Split(".")[0]
$groupVersions += $versions | Where-Object { $_.StartsWith($majorVersion) } | Join-String -Separator " "
}
return ($groupVersions | Sort-Object -Descending -Unique | Join-String -Separator "<br>")
}
function Get-AndroidGoogleAPIsVersions {
param (
[Parameter(Mandatory)]
[object] $PackageInfo
)
$versions = $packageInfo | Where-Object { $_ -Match "addon-google_apis" } | ForEach-Object {
$packageInfoParts = Split-TableRowByColumns $_
return $packageInfoParts[0].split(";")[1]
}
return ($versions -Join "<br>")
}
function Get-AndroidNdkVersions {
param (
[Parameter(Mandatory)]
[object] $PackageInfo
)
$ndkDefaultFullVersion = Get-ChildItem $env:ANDROID_NDK_HOME -Name
$versions = $packageInfo | Where-Object { $_ -Match "ndk;" } | ForEach-Object {
$version = (Split-TableRowByColumns $_)[1]
if ($version -eq $ndkDefaultFullVersion) {
$version += " (default)"
}
$version
}
return ($versions -Join "<br>")
}
function Build-AndroidEnvironmentTable {
$androidVersions = Get-Item env:ANDROID_*
$shoulddResolveLink = 'ANDROID_NDK', 'ANDROID_NDK_HOME', 'ANDROID_NDK_ROOT', 'ANDROID_NDK_LATEST_HOME'
return $androidVersions | Sort-Object -Property Name | ForEach-Object {
[PSCustomObject] @{
"Name" = $_.Name
"Value" = if ($shoulddResolveLink.Contains($_.Name )) { Get-PathWithLink($_.Value) } else {$_.Value}
}
}
}
@@ -0,0 +1,100 @@
$browsers = @{
chrome = @{
Name="Google Chrome";
File="chrome.exe"
};
edge = @{
Name="Microsoft Edge";
File="msedge.exe"
};
firefox = @{
Name="Mozilla Firefox";
File="firefox.exe"
}
}
$webDrivers = @{
chrome = @{
Name="Chrome Driver";
Path="C:\SeleniumWebDrivers\ChromeDriver"
};
edge = @{
Name="Microsoft Edge Driver";
Path="C:\SeleniumWebDrivers\EdgeDriver"
};
firefox = @{
Name="Gecko Driver";
Path="C:\SeleniumWebDrivers\GeckoDriver"
};
iexplorer = @{
Name="IE Driver";
Path="C:\SeleniumWebDrivers\IEDriver"
}
}
function Build-BrowserSection {
return @(
$(Get-BrowserVersion -Browser "chrome"),
$(Get-SeleniumWebDriverVersion -Driver "chrome"),
$(Get-BrowserVersion -Browser "edge"),
$(Get-SeleniumWebDriverVersion -Driver "edge"),
$(Get-BrowserVersion -Browser "firefox"),
$(Get-SeleniumWebDriverVersion -Driver "firefox"),
$(Get-SeleniumWebDriverVersion -Driver "iexplorer"),
$(Get-SeleniumVersion)
)
}
function Get-BrowserVersion {
param(
[string] $Browser
)
$browserName = $browsers.$Browser.Name
$browserFile = $browsers.$Browser.File
$registryKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\$browserFile"
$browserVersion = (Get-Item (Get-ItemProperty $registryKey)."(Default)").VersionInfo.FileVersion
return [ToolVersionNode]::new($browserName, $browserVersion)
}
function Get-SeleniumWebDriverVersion {
param(
[string] $Driver
)
$driverName = $webDrivers.$Driver.Name
$driverPath = $webDrivers.$Driver.Path
$versionFileName = "versioninfo.txt";
$webDriverVersion = Get-Content -Path "$driverPath\$versionFileName"
return [ToolVersionNode]::new($driverName, $webDriverVersion)
}
function Get-SeleniumVersion {
$seleniumBinaryName = "selenium-server"
$fullSeleniumVersion = (Get-ChildItem "C:\selenium\${seleniumBinaryName}-*").Name -replace "${seleniumBinaryName}-"
return [ToolVersionNode]::new("Selenium server", $fullSeleniumVersion)
}
function Build-BrowserWebdriversEnvironmentTable {
return @(
@{
"Name" = "CHROMEWEBDRIVER"
"Value" = $env:CHROMEWEBDRIVER
},
@{
"Name" = "EDGEWEBDRIVER"
"Value" = $env:EDGEWEBDRIVER
},
@{
"Name" = "GECKOWEBDRIVER"
"Value" = $env:GECKOWEBDRIVER
},
@{
"Name" = "SELENIUM_JAR_PATH"
"Value" = $env:SELENIUM_JAR_PATH
}
) | ForEach-Object {
[PSCustomObject] @{
"Name" = $_.Name
"Value" = $_.Value
}
}
}
@@ -0,0 +1,40 @@
function Get-ToolcacheGoVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Go"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
}
function Get-ToolcacheNodeVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Node"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
}
function Get-ToolcachePythonVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Python"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
}
function Get-ToolcacheRubyVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Ruby"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
}
function Get-ToolcachePyPyVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "PyPy"
Get-ChildItem -Path $toolcachePath -Name | Sort-Object { [Version] $_ } | ForEach-Object {
$pypyRootPath = Join-Path $toolcachePath $_ "x86"
[string] $pypyVersionOutput = & "$pypyRootPath\python.exe" -c "import sys;print(sys.version)"
$pypyVersionOutput -match "^([\d\.]+) \(.+\) \[PyPy ([\d\.]+\S*) .+]$" | Out-Null
return "{0} [PyPy {1}]" -f $Matches[1], $Matches[2]
}
}
function Build-CachedToolsSection
{
return @(
[ToolVersionsListNode]::new("Go", $(Get-ToolcacheGoVersions), '^\d+\.\d+', 'List'),
[ToolVersionsListNode]::new("Node.js", $(Get-ToolcacheNodeVersions), '^\d+', 'List'),
[ToolVersionsListNode]::new("Python", $(Get-ToolcachePythonVersions), '^\d+\.\d+', 'List'),
[ToolVersionsListNode]::new("PyPy", $(Get-ToolcachePyPyVersions), '^\d+\.\d+', 'List'),
[ToolVersionsListNode]::new("Ruby", $(Get-ToolcacheRubyVersions), '^\d+\.\d+', 'List')
)
}
@@ -0,0 +1,329 @@
function Initialize-RustEnvironment {
$env:RUSTUP_HOME = "C:\Users\Default\.rustup"
$env:CARGO_HOME = "C:\Users\Default\.cargo"
$env:Path += ";$env:CARGO_HOME\bin"
}
function Get-OSName {
return (Get-CimInstance -ClassName Win32_OperatingSystem).Caption | Get-StringPart -Part 1,2,3
}
function Get-OSVersion {
$OSVersion = (Get-CimInstance -ClassName Win32_OperatingSystem).Version
$OSBuild = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion' UBR).UBR
return "$OSVersion Build $OSBuild"
}
function Build-OSInfoSection {
$osInfoNode = [HeaderNode]::new($(Get-OSName))
$osInfoNode.AddToolVersion("OS Version:", $(Get-OSVersion))
$osInfoNode.AddToolVersion("Image Version:", $env:IMAGE_VERSION)
return $osInfoNode
}
function Get-BashVersion {
bash --% -c 'echo ${BASH_VERSION}'
}
function Get-RustVersion {
rustc --version | Get-StringPart -Part 1
}
function Get-RustupVersion {
cmd /c "rustup --version 2>NUL" | Get-StringPart -Part 1
}
function Get-RustCargoVersion {
cargo --version | Get-StringPart -Part 1
}
function Get-RustdocVersion {
rustdoc --version | Get-StringPart -Part 1
}
function Get-RustfmtVersion {
rustfmt --version | Get-StringPart -Part 1 | Get-StringPart -Part 0 -Delimiter ('-')
}
function Get-RustClippyVersion {
cargo clippy --version | Get-StringPart -Part 1
}
function Get-BindgenVersion {
bindgen --version | Get-StringPart -Part 1
}
function Get-CbindgenVersion {
cbindgen --version | Get-StringPart -Part 1
}
function Get-CargoAuditVersion {
cargo-audit --version | Get-StringPart -Part 1
}
function Get-CargoOutdatedVersion {
cargo outdated --version | Get-StringPart -Part 1
}
function Get-PythonVersion {
python --version | Get-StringPart -Part 1
}
function Get-PowershellCoreVersion {
pwsh --version | Get-StringPart -Part 1
}
function Get-RubyVersion {
ruby --version | Get-StringPart -Part 1
}
function Get-GoVersion {
go version | Get-StringPart -Part 2 | Get-StringPart -Part 1 -Delimiter ('o')
}
function Get-KotlinVersion {
cmd /c "kotlinc -version 2>&1" | Get-StringPart -Part 2
}
function Get-PHPVersion {
php --version | Out-String | Get-StringPart -Part 1
}
function Get-JuliaVersion {
julia --version | Get-StringPart -Part 2
}
function Get-LLVMVersion {
(clang --version) -match "clang" | Get-StringPart -Part 2
}
function Get-PerlVersion {
($(perl --version) | Out-String) -match "\(v(?<version>\d+\.\d+\.\d+)\)" | Out-Null
$perlVersion = $Matches.Version
return $perlVersion
}
function Get-NodeVersion {
node --version | Get-StringPart -Part 0 -Delimiter ('v')
}
function Get-ChocoVersion {
choco --version
}
function Get-VcpkgVersion {
$commitId = git -C "C:\vcpkg" rev-parse --short HEAD
return "(build from commit $commitId)"
}
function Get-NPMVersion {
npm -version
}
function Get-YarnVersion {
yarn -version
}
function Get-RubyGemsVersion {
gem --version
}
function Get-HelmVersion {
($(helm version --short) | Out-String) -match "v(?<version>\d+\.\d+\.\d+)" | Out-Null
$helmVersion = $Matches.Version
return $helmVersion
}
function Get-PipVersion {
(pip --version) -match "pip" | Get-StringPart -Part 1, 4, 5
}
function Get-CondaVersion {
$condaVersion = ((& "$env:CONDA\Scripts\conda.exe" --version) -replace "^conda").Trim()
return "$condaVersion (pre-installed on the image but not added to PATH)"
}
function Get-ComposerVersion {
composer --version | Get-StringPart -Part 2
}
function Get-NugetVersion {
(nuget help) -match "Nuget Version" | Get-StringPart -Part 2
}
function Get-AntVersion {
ant -version | Get-StringPart -Part 3
}
function Get-MavenVersion {
(mvn -version) -match "Apache Maven" | Get-StringPart -Part 2
}
function Get-GradleVersion {
($(gradle -version) | Out-String) -match "Gradle (?<version>\d+\.\d+)" | Out-Null
$gradleVersion = $Matches.Version
return $gradleVersion
}
function Get-SbtVersion {
(sbt -version) -match "sbt script" | Get-StringPart -Part 3
}
function Get-DotnetSdks {
$sdksRawList = dotnet --list-sdks
$sdkVersions = $sdksRawList | Foreach-Object { $_.Split()[0] }
$sdkPath = $sdksRawList[0].Split(' ', 2)[1] -replace '\[|]'
[PSCustomObject]@{
Versions = $sdkVersions
Path = $sdkPath
}
}
function Get-DotnetTools {
$env:Path += ";C:\Users\Default\.dotnet\tools"
$dotnetTools = (Get-ToolsetContent).dotnet.tools
$toolsList = @()
foreach ($dotnetTool in $dotnetTools) {
$version = Invoke-Expression $dotnetTool.getversion
$toolsList += [ToolVersionNode]::new($dotnetTool.name, $version)
}
return $toolsList
}
function Get-DotnetRuntimes {
$runtimesRawList = dotnet --list-runtimes
$runtimesRawList | Group-Object { $_.Split()[0] } | ForEach-Object {
$runtimeName = $_.Name
$runtimeVersions = $_.Group | Foreach-Object { $_.split()[1] }
$runtimePath = $_.Group[0].Split(' ', 3)[2] -replace '\[|]'
[PSCustomObject]@{
"Runtime" = $runtimeName
"Versions" = $runtimeVersions
"Path" = $runtimePath
}
}
}
function Get-DotnetFrameworkVersions {
$path = "${env:ProgramFiles(x86)}\Microsoft SDKs\Windows\*\*\NETFX * Tools"
return Get-ChildItem -Path $path -Directory | ForEach-Object { $_.Name | Get-StringPart -Part 1 }
}
function Get-PowerShellAzureModules {
[Array] $result = @()
$defaultAzureModuleVersion = "2.1.0"
[Array] $azInstalledModules = Get-ChildItem -Path "C:\Modules\az_*" -Directory | ForEach-Object { $_.Name.Split("_")[1] }
if ($azInstalledModules.Count -gt 0) {
$result += [ToolVersionsListNode]::new("Az", $($azInstalledModules), '^\d+\.\d+', "Inline")
}
[Array] $azureInstalledModules = Get-ChildItem -Path "C:\Modules\azure_*" -Directory | ForEach-Object { $_.Name.Split("_")[1] } | ForEach-Object { if ($_ -eq $defaultAzureModuleVersion) { "$($_) (Default)" } else { $_ } }
if ($azureInstalledModules.Count -gt 0) {
$result += [ToolVersionsListNode]::new("Azure", $($azureInstalledModules), '^\d+\.\d+', "Inline")
}
[Array] $azurermInstalledModules = Get-ChildItem -Path "C:\Modules\azurerm_*" -Directory | ForEach-Object { $_.Name.Split("_")[1] } | ForEach-Object { if ($_ -eq $defaultAzureModuleVersion) { "$($_) (Default)" } else { $_ } }
if ($azurermInstalledModules.Count -gt 0) {
$result += [ToolVersionsListNode]::new("AzureRM", $($azurermInstalledModules), '^\d+\.\d+', "Inline")
}
[Array] $azCachedModules = Get-ChildItem -Path "C:\Modules\az_*.zip" -File | ForEach-Object { $_.Name.Split("_")[1] }
if ($azCachedModules.Count -gt 0) {
$result += [ToolVersionsListNode]::new("Az (Cached)", $($azCachedModules), '^\d+\.\d+', "Inline")
}
[Array] $azureCachedModules = Get-ChildItem -Path "C:\Modules\azure_*.zip" -File | ForEach-Object { $_.Name.Split("_")[1] }
if ($azureCachedModules.Count -gt 0) {
$result += [ToolVersionsListNode]::new("Azure (Cached)", $($azureCachedModules), '^\d+\.\d+', "Inline")
}
[Array] $azurermCachedModules = Get-ChildItem -Path "C:\Modules\azurerm_*.zip" -File | ForEach-Object { $_.Name.Split("_")[1] }
if ($azurermCachedModules.Count -gt 0) {
$result += [ToolVersionsListNode]::new("AzureRM (Cached)", $($azurermCachedModules), '^\d+\.\d+', "Inline")
}
return $result
}
function Get-PowerShellModules {
[Array] $result = @()
$result += Get-PowerShellAzureModules
$result += (Get-ToolsetContent).powershellModules.name | Sort-Object | ForEach-Object {
$moduleName = $_
$moduleVersions = Get-Module -Name $moduleName -ListAvailable | Select-Object -ExpandProperty Version | Sort-Object -Unique
return [ToolVersionsListNode]::new($moduleName, $moduleVersions, '^\d+', "Inline")
}
return $result
}
function Get-CachedDockerImages {
return (docker images --digests --format "* {{.Repository}}:{{.Tag}}").Split("*") | Where-Object { $_ }
}
function Get-CachedDockerImagesTableData {
$allImages = docker images --digests --format "*{{.Repository}}:{{.Tag}}|{{.Digest}} |{{.CreatedAt}}"
if (-not $allImages) {
return $null
}
$allImages.Split("*") | Where-Object { $_ } | ForEach-Object {
$parts = $_.Split("|")
[PSCustomObject] @{
"Repository:Tag" = $parts[0]
"Digest" = $parts[1]
"Created" = $parts[2].split(' ')[0]
}
} | Sort-Object -Property "Repository:Tag"
}
function Get-ShellTarget {
return Get-ChildItem C:\shells -File | Select-Object Name, @{n = "Target"; e = {
if ($_.Name -eq "msys2bash.cmd") {
"C:\msys64\usr\bin\bash.exe"
} else {
@($_.Target)[0]
}
}
} | Sort-Object Name
}
function Get-PacmanVersion {
$msys2BinDir = "C:\msys64\usr\bin"
$pacmanPath = Join-Path $msys2BinDir "pacman.exe"
$rawVersion = & $pacmanPath --version
$rawVersion.Split([System.Environment]::NewLine)[1] -match "\d+\.\d+(\.\d+)?" | Out-Null
$pacmanVersion = $matches[0]
return $pacmanVersion
}
function Get-YAMLLintVersion {
yamllint --version | Get-StringPart -Part 1
}
function Get-BizTalkVersion {
$bizTalkReg = Get-ItemProperty "HKLM:\SOFTWARE\WOW6432Node\Microsoft\BizTalk Server\3.0"
return [ToolVersionNode]::new($bizTalkReg.ProductName, $bizTalkReg.ProductVersion)
}
function Get-PipxVersion {
pipx --version
}
function Build-PackageManagementEnvironmentTable {
return @(
[PSCustomObject] @{
"Name" = "VCPKG_INSTALLATION_ROOT"
"Value" = $env:VCPKG_INSTALLATION_ROOT
},
[PSCustomObject] @{
"Name" = "CONDA"
"Value" = $env:CONDA
}
)
}
@@ -0,0 +1,37 @@
function Get-PostgreSQLTable
{
$pgService = Get-CimInstance Win32_Service -Filter "Name LIKE 'postgresql-%'"
$pgPath = $pgService.PathName
$pgRoot = $pgPath.split('"')[1].replace("\bin\pg_ctl.exe", "")
$env:Path += ";${env:PGBIN}"
$pgVersion = (postgres --version).split()[2].Trim()
return @(
[PSCustomObject]@{ Property = "ServiceName"; Value = $pgService.Name },
[PSCustomObject]@{ Property = "Version"; Value = $pgVersion },
[PSCustomObject]@{ Property = "ServiceStatus"; Value = $pgService.State },
[PSCustomObject]@{ Property = "ServiceStartType"; Value = $pgService.StartMode },
[PSCustomObject]@{ Property = "EnvironmentVariables"; Value = "`PGBIN=$env:PGBIN` <br> `PGDATA=$env:PGDATA` <br> `PGROOT=$env:PGROOT` " },
[PSCustomObject]@{ Property = "Path"; Value = $pgRoot },
[PSCustomObject]@{ Property = "UserName"; Value = $env:PGUSER },
[PSCustomObject]@{ Property = "Password"; Value = $env:PGPASSWORD }
)
}
function Get-MongoDBTable
{
$name = "MongoDB"
if (Test-IsWin25) {
$command = "mongod"
} else {
$command = "mongo"
}
$mongoService = Get-Service -Name $name
$mongoVersion = (Get-Command -Name $command).Version.ToString()
return [PSCustomObject]@{
Version = $mongoVersion
ServiceName = $name
ServiceStatus = $mongoService.Status
ServiceStartType = $mongoService.StartType
}
}
@@ -0,0 +1,30 @@
function Get-LinkTarget {
param (
[string] $inputPath
)
$link = Get-Item $inputPath | Select-Object -ExpandProperty Target
if ($link) {
return " -> $link"
}
return ""
}
function Get-PathWithLink {
param (
[string] $inputPath
)
$link = Get-LinkTarget($inputPath)
return "${inputPath}${link}"
}
function Get-StringPart {
param (
[Parameter(ValueFromPipeline)]
[string] $toolOutput,
[string] $Delimiter = " ",
[int[]] $Part
)
$parts = $toolOutput.Split($Delimiter, [System.StringSplitOptions]::RemoveEmptyEntries)
$selectedParts = $parts[$Part]
return [string]::Join($Delimiter, $selectedParts)
}
@@ -0,0 +1,22 @@
function Get-JavaVersions {
$defaultJavaPath = $env:JAVA_HOME
$javaVersions = Get-Item env:JAVA_HOME_*_X64
$sortRules = @{
Expression = { [Int32] $_.Name.Split("_")[2] }
Descending = $false
}
return $javaVersions | Sort-Object $sortRules | ForEach-Object {
$javaPath = $_.Value
# Take semver from the java path
# The path contains '-' sign in the version number instead of '+' due to the following issue, need to substitute it back https://github.com/actions/runner-images/issues/3014
$versionInPath = (Split-Path $javaPath) -replace "\w:\\.*\\"
$version = $versionInPath -replace '-', '+'
$defaultPostfix = ($javaPath -eq $defaultJavaPath) ? " (default)" : ""
[PSCustomObject] @{
"Version" = $version + $defaultPostfix
"Environment Variable" = $_.Name
}
}
}
@@ -0,0 +1,320 @@
function Get-Aria2Version {
(aria2c -v | Out-String) -match "(?<version>(\d+\.){1,}\d+)" | Out-Null
$aria2Version = $Matches.Version
return $aria2Version
}
function Get-AzCosmosDBEmulatorVersion {
$regKey = gci HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* | gp | ? { $_.DisplayName -eq 'Azure Cosmos DB Emulator' }
$installDir = $regKey.InstallLocation
$exeFilePath = Join-Path $installDir 'CosmosDB.Emulator.exe'
$version = (Get-Item $exeFilePath).VersionInfo.FileVersion
return $version
}
function Get-BazelVersion {
((cmd /c "bazel --version 2>&1") | Out-String) -match "bazel (?<version>\d+\.\d+\.\d+)" | Out-Null
$bazelVersion = $Matches.Version
return $bazelVersion
}
function Get-BazeliskVersion {
((cmd /c "bazelisk version 2>&1") | Out-String) -match "Bazelisk version: v(?<version>\d+\.\d+\.\d+)" | Out-Null
$bazeliskVersion = $Matches.Version
return $bazeliskVersion
}
function Get-BicepVersion {
(bicep --version | Out-String) -match "bicep cli version (?<version>\d+\.\d+\.\d+)" | Out-Null
$bicepVersion = $Matches.Version
return $bicepVersion
}
function Get-RVersion {
($(cmd /c "Rscript --version 2>&1") | Out-String) -match "Rscript .* version (?<version>\d+\.\d+\.\d+)" | Out-Null
$rVersion = $Matches.Version
return $rVersion
}
function Get-CMakeVersion {
($(cmake -version) | Out-String) -match "cmake version (?<version>\d+\.\d+\.\d+)" | Out-Null
$cmakeVersion = $Matches.Version
return $cmakeVersion
}
function Get-CodeQLBundleVersion {
$CodeQLVersionsWildcard = Join-Path $env:AGENT_TOOLSDIRECTORY -ChildPath "CodeQL" | Join-Path -ChildPath "*"
$CodeQLVersionPath = Get-ChildItem $CodeQLVersionsWildcard | Select-Object -First 1 -Expand FullName
$CodeQLPath = Join-Path $CodeQLVersionPath -ChildPath "x64" | Join-Path -ChildPath "codeql" | Join-Path -ChildPath "codeql.exe"
$CodeQLVersion = & $CodeQLPath version --quiet
return $CodeQLVersion
}
function Get-DockerVersion {
$dockerVersion = $(docker version --format "{{.Server.Version}}")
return $dockerVersion
}
function Get-DockerComposeVersionV2 {
$dockerComposeVersion = docker compose version --short
return $dockerComposeVersion
}
function Get-DockerWincredVersion {
$dockerCredVersion = docker-credential-wincred version | Get-StringPart -Part 2 | Get-StringPart -Part 0 -Delimiter "v"
return $dockerCredVersion
}
function Get-GitVersion {
$gitVersion = git --version | Get-StringPart -Part -1
return $gitVersion
}
function Get-GitLFSVersion {
$(git-lfs version) -match "git-lfs\/(?<version>\d+\.\d+\.\d+)" | Out-Null
$gitLfsVersion = $Matches.Version
return $gitLfsVersion
}
function Get-InnoSetupVersion {
$innoSetupVersion = $(choco list innosetup) | Select-String -Pattern "InnoSetup"
return ($innoSetupVersion -replace "^InnoSetup").Trim()
}
function Get-JQVersion {
$jqVersion = ($(jq --version) -Split "jq-")[1]
return $jqVersion
}
function Get-KubectlVersion {
$kubectlVersion = (kubectl version --client --output=json | ConvertFrom-Json).clientVersion.gitVersion.Replace('v', '')
return $kubectlVersion
}
function Get-KindVersion {
$(kind version) -match "kind v(?<version>\d+\.\d+\.\d+)" | Out-Null
$kindVersion = $Matches.Version
return $kindVersion
}
function Get-GCCVersion {
(gcc --version | Select-String -Pattern "gcc.exe") -match "(?<version>\d+\.\d+\.\d+)" | Out-Null
$mingwVersion = $Matches.Version
return $mingwVersion
}
function Get-GDBVersion {
(gdb --version | Select-String -Pattern "GNU gdb") -match "(?<version>\d+\.\d+)" | Out-Null
$mingwVersion = $Matches.Version
return $mingwVersion
}
function Get-GNUBinutilsVersion {
(ld --version | Select-String -Pattern "GNU Binutils") -match "(?<version>\d+\.\d+)" | Out-Null
$mingwVersion = $Matches.Version
return $mingwVersion
}
function Get-MySQLVersion {
$mysqlCommand = Get-Command -Name "mysql"
$mysqlVersion = $mysqlCommand.Version.ToString()
return $mysqlVersion
}
function Get-SQLOLEDBDriverVersion {
$SQLOLEDBDriverVersion = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSOLEDBSQL' InstalledVersion).InstalledVersion
return $SQLOLEDBDriverVersion
}
function Get-MercurialVersion {
($(hg --version) | Out-String) -match "version (?<version>\d+\.\d+\.?\d*)" | Out-Null
$mercurialVersion = $Matches.Version
return $mercurialVersion
}
function Get-NSISVersion {
$nsisVersion = & "c:\Program Files (x86)\NSIS\makensis.exe" "/Version"
return $nsisVersion.TrimStart("v")
}
function Get-OpenSSLVersion {
$(openssl version) -match "OpenSSL (?<version>\d+\.\d+\.\d+\w?) " | Out-Null
$opensslVersion = $Matches.Version
return $opensslVersion
}
function Get-PackerVersion {
$packerVersion = (packer --version | Select-String "^Packer").Line.Replace('v','') | Get-StringPart -Part 1
return $packerVersion
}
function Get-ParcelVersion {
$parcelVersion = parcel --version
return "$parcelVersion"
}
function Get-PulumiVersion {
return (pulumi version).TrimStart("v")
}
function Get-SQLPSVersion {
$module = Get-Module -Name SQLPS -ListAvailable
$version = $module.Version
return $version
}
function Get-SVNVersion {
$svnVersion = $(svn --version --quiet)
return $svnVersion
}
function Get-VSWhereVersion {
($(Get-Command -Name vswhere).FileVersionInfo.ProductVersion) -match "(?<version>\d+\.\d+\.\d+)" | Out-Null
$vswhereVersion = $Matches.Version
return $vswhereVersion
}
function Get-WinAppDriver {
$winAppDriverVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe").FileVersion
return $winAppDriverVersion
}
function Get-WixVersion {
$regKey = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
$installedApplications = Get-ItemProperty -Path $regKey
$wixToolsetVersion = ($installedApplications | Where-Object { $_.BundleCachePath -imatch ".*\\WiX\d*\.exe$" } | Select-Object -First 1).DisplayName
return ($wixToolsetVersion -replace "^WiX Toolset v").Trim()
}
function Get-ZstdVersion {
$(zstd --version) -match "v(?<version>\d+\.\d+\.\d+)" | Out-Null
$zstdVersion = $Matches.Version
return $zstdVersion
}
function Get-AzureCLIVersion {
$azureCLIVersion = $(az version) | ConvertFrom-Json | Foreach{ $_."azure-cli" }
return $azureCLIVersion
}
function Get-AzCopyVersion {
return ($(azcopy --version) -replace "^azcopy version").Trim()
}
function Get-AzureDevopsExtVersion {
$azureDevExtVersion = (az version | ConvertFrom-Json | ForEach-Object { $_."extensions" })."azure-devops"
return $azureDevExtVersion
}
function Get-AWSCLIVersion {
$(aws --version) -match "aws-cli\/(?<version>\d+\.\d+\.\d+)" | Out-Null
$awscliVersion = $Matches.Version
return $awscliVersion
}
function Get-AWSSAMVersion {
$(sam --version) -match "version (?<version>\d+\.\d+\.\d+)" | Out-Null
$awssamVersion = $Matches.Version
return $awssamVersion
}
function Get-AWSSessionManagerVersion {
$awsSessionManagerVersion = $(session-manager-plugin --version)
return $awsSessionManagerVersion
}
function Get-AlibabaCLIVersion {
$alicliVersion = $(aliyun version)
return $alicliVersion
}
function Get-CloudFoundryVersion {
$(cf version) -match "(?<version>\d+\.\d+\.\d+)" | Out-Null
$cfVersion = $Matches.Version
return $cfVersion
}
function Get-7zipVersion {
(7z | Out-String) -match "7-Zip (?<version>\d+\.\d+\.?\d*)" | Out-Null
$version = $Matches.Version
return $version
}
function Get-GHCVersion {
((ghc --version) | Out-String) -match "version (?<version>\d+\.\d+\.\d+)" | Out-Null
$ghcVersion = $Matches.Version
return $ghcVersion
}
function Get-CabalVersion {
((cabal --version) | Out-String) -match "version (?<version>\d+\.\d+\.\d+\.\d+)" | Out-Null
$cabalVersion = $Matches.Version
return $cabalVersion
}
function Get-StackVersion {
((stack --version --quiet) | Out-String) -match "Version (?<version>\d+\.\d+\.\d+)," | Out-Null
$stackVersion = $Matches.Version
return $stackVersion
}
function Get-GoogleCloudCLIVersion {
return (((cmd /c "gcloud --version") -match "Google Cloud SDK") -replace "Google Cloud SDK").Trim()
}
function Get-ServiceFabricSDKVersion {
$serviceFabricSDKVersion = Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Service Fabric\' -Name FabricVersion
return $serviceFabricSDKVersion
}
function Get-NewmanVersion {
return $(newman --version)
}
function Get-GHVersion {
($(gh --version) | Select-String -Pattern "gh version") -match "gh version (?<version>\d+\.\d+\.\d+)" | Out-Null
$ghVersion = $Matches.Version
return $ghVersion
}
function Get-VisualCPPComponents {
$regKeys = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
)
$vcpp = Get-ItemProperty -Path $regKeys | Where-Object DisplayName -like "Microsoft Visual C++*"
$vcpp | Sort-Object DisplayName, DisplayVersion | ForEach-Object {
$isMatch = $_.DisplayName -match "^(?<Name>Microsoft Visual C\+\+ \d{4})\s+(?<Arch>\w{3})\s+(?<Ext>.+)\s+-"
if ($isMatch) {
$name = '{0} {1}' -f $matches["Name"], $matches["Ext"]
$arch = $matches["Arch"].ToLower()
$version = $_.DisplayVersion
[PSCustomObject]@{
Name = $name
Architecture = $arch
Version = $version
}
}
}
}
function Get-DacFxVersion {
$dacfxversion = & "$env:ProgramFiles\Microsoft SQL Server\160\DAC\bin\sqlpackage.exe" /version
return $dacfxversion
}
function Get-SwigVersion {
(swig -version | Out-String) -match "version (?<version>\d+\.\d+\.\d+)" | Out-Null
$swigVersion = $Matches.Version
return $swigVersion
}
function Get-ImageMagickVersion {
(magick -version | Select-String -Pattern "Version") -match "(?<version>\d+\.\d+\.\d+-\d+)" | Out-Null
$magickVersion = $Matches.Version
return $magickVersion
}
function Get-MongoshVersion {
return $(mongosh --version)
}
@@ -0,0 +1,71 @@
function Get-VisualStudioVersion {
$vsInstance = Get-VisualStudioInstance
[PSCustomObject]@{
Name = $vsInstance.DisplayName
Version = $vsInstance.InstallationVersion
Path = $vsInstance.InstallationPath
}
}
function Get-SDKVersion {
$regKey = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
$installedApplications = Get-ItemProperty -Path $regKey
($installedApplications | Where-Object { $_.DisplayName -eq 'Windows SDK' } | Select-Object -First 1).DisplayVersion
}
function Get-WDKVersion {
$regKey = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
$installedApplications = Get-ItemProperty -Path $regKey
($installedApplications | Where-Object { $_.DisplayName -eq 'Windows Driver Kit' } | Select-Object -First 1).DisplayVersion
}
function Get-VisualStudioExtensions {
$vsPackages = (Get-VisualStudioInstance).Packages
# Additional vsixs
$toolset = Get-ToolsetContent
$vsixPackagesList = $toolset.visualStudio.vsix
if ($vsixPackagesList) {
$vsixs = $vsixPackagesList | ForEach-Object {
$vsixPackage = Get-VsixInfoFromMarketplace $_
$vsixVersion = ($vsPackages | Where-Object { $_.Id -match $vsixPackage.VsixId -and $_.type -eq 'vsix' }).Version
@{
Package = $vsixPackage.ExtensionName
Version = $vsixVersion
}
}
}
# SDK
$sdkVersion = Get-SDKVersion
$sdkPackages = @(
@{Package = 'Windows Software Development Kit'; Version = $sdkVersion }
)
# WDK
$wdkVersion = Get-WDKVersion
$wdkExtensionVersion = Get-VSExtensionVersion -packageName 'Microsoft.Windows.DriverKit'
$wdkPackages = @(
@{Package = 'Windows Driver Kit'; Version = $wdkVersion }
@{Package = 'Windows Driver Kit Visual Studio Extension'; Version = $wdkExtensionVersion }
)
$extensions = @(
$vsixs
$ssdtPackages
$sdkPackages
$wdkPackages
)
$extensions | Foreach-Object {
[PSCustomObject] $_
} | Select-Object Package, Version | Sort-Object Package
}
function Get-WindowsSDKs {
$path = "${env:ProgramFiles(x86)}\Windows Kits\10\Extension SDKs\WindowsDesktop"
return [PSCustomObject]@{
Path = $path
Versions = $(Get-ChildItem $path).Name
}
}

Some files were not shown because too many files have changed in this diff Show More