From 076cec130ab2799eebe98e083c816dbdfeebe355 Mon Sep 17 00:00:00 2001 From: James Ruskin Date: Thu, 6 Apr 2023 19:57:28 +0100 Subject: [PATCH] (#4) Adds Windows Sandbox to Test-Package This adds a really messy addition to the Test-Package function, which allows users to test package install/uninstall with Windows Sandbox rather than Vagrant or Local testing. It is not in my regular style but attempts to match the existing function. I'm not fully successful in this. --- AU/Public/Test-Package.ps1 | 121 +++++++++++++++++++++++++++++++++++-- 1 file changed, 116 insertions(+), 5 deletions(-) diff --git a/AU/Public/Test-Package.ps1 b/AU/Public/Test-Package.ps1 index 91019b4..79e97e8 100644 --- a/AU/Public/Test-Package.ps1 +++ b/AU/Public/Test-Package.ps1 @@ -21,10 +21,12 @@ https://github.com/chocolatey/choco/wiki/CreatePackages#testing-your-package #> function Test-Package { + [CmdletBinding(DefaultParameterSetName="Local")] param( # If file, path to the .nupkg or .nuspec file for the package. # If directory, latest .nupkg or .nuspec file wil be looked in it. # If ommited current directory will be used. + [Parameter(Position=0)] $Nu, # Test chocolateyInstall.ps1 only. @@ -37,13 +39,28 @@ function Test-Package { [string] $Parameters, # Path to chocolatey-test-environment: https://github.com/majkinetor/chocolatey-test-environment - [string] $Vagrant = $Env:au_Vagrant, + [Parameter(ParameterSetName="Vagrant")] + [string] $Vagrant = $env:au_Vagrant, + [Parameter(ParameterSetName="Vagrant")] # Open new shell window [switch] $VagrantOpen, # Do not remove existing packages from vagrant package directory - [switch] $VagrantNoClear + [Parameter(ParameterSetName="Vagrant")] + [switch] $VagrantNoClear, + + # Invokes the package test within Windows Sandbox, if available + [Parameter(ParameterSetName="Sandbox")] + [switch] $Sandbox, + + # If set, does not destroy the Windows Sandbox instance or files. + [Parameter(ParameterSetName="Sandbox")] + [switch] $NoDestroy, + + # Timeout for attempt to install and uninstall to Windows Sandbox, in minutes. + [Parameter(ParameterSetName="Sandbox")] + [uint16] $Timeout = 5 ) if (!$Install -and !$Uninstall) { $Install = $true } @@ -68,7 +85,7 @@ function Test-Package { $Nu = Get-Item ([System.IO.Path]::Combine($Nu.DirectoryName, '*.nupkg')) | Sort-Object -Property CreationTime -Descending | Select-Object -First 1 } elseif ($Nu.Extension -ne '.nupkg') { throw "File is not nupkg or nuspec file" } - #At this point Nu is nupkg file + # At this point Nu is nupkg file $package_name = $Nu.Name -replace '(\.\d+)+(-[^-]+)?\.nupkg$' $package_version = ($Nu.BaseName -replace $package_name).Substring(1) @@ -78,9 +95,103 @@ function Test-Package { Write-Host " Name:".PadRight(15) $package_name Write-Host " Version:".PadRight(15) $package_version if ($Parameters) { Write-Host " Parameters:".PadRight(15) $Parameters } - if ($Vagrant) { Write-Host " Vagrant: ".PadRight(15) $Vagrant } + + if ($Sandbox) { + if (-not (Get-Command WindowsSandbox -ErrorAction SilentlyContinue)) { + Write-Error "Windows Sandbox is not available. Please try Local or Vagrant methods." -ErrorAction Stop + } + Write-Host "`nTesting package using Windows Sandbox" + + $SandboxTempFolder = Join-Path $env:TEMP "$(New-Guid)" + $null = New-Item -Path $SandboxTempFolder\ChocoTestingSandbox.wsb -Force -Value @" + + Enable + + + $($SandboxTempFolder) + C:\packages\ + false + + + + C:\packages\Test-Package.cmd + + +"@ + + $TestCommand = @( + 'Start-Transcript -Path c:\packages\log.txt' + '$Results = @{}' + if ($Install) { + "choco install -y $package_name --version $package_version --no-progress --source `"'C:\packages\;https://community.chocolatey.org/api/v2/'`"$(if ($Parameters) {[string]::format(' --packageParameters="''{0}''"', $Parameters)}) | Write-Host" + '$Results.InstallExitCode = $LASTEXITCODE' + } + if ($Uninstall) { + "choco uninstall -y $package_name | Write-Host" + '$Results.UninstallExitCode = $LASTEXITCODE' + } + 'Stop-Transcript' + 'Copy-Item C:\ProgramData\chocolatey\logs\* -Destination C:\packages\' + '$Results | Export-Clixml -Path C:\packages\results.clixml' + ) -join '; ' + $null = New-Item -Path $SandboxTempFolder\Test-Package.cmd -Value @" + @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" + @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$($TestCommand)" +"@ + Copy-Item -Path $Nu -Destination $SandboxTempFolder + + try { + & WindowsSandbox "$SandboxTempFolder\ChocoTestingSandbox.wsb" + + $Timer = [System.Diagnostics.Stopwatch]::StartNew() + $BytesShown = 0 # Nothing shown yet + while ($Timer.IsRunning -and $Timer.Elapsed.TotalMinutes -lt $Timeout) { + if (Test-Path $SandboxTempFolder\log.txt) { + $Log = Get-Content $SandboxTempFolder\log.txt -Raw + -join $Log[$BytesShown..$Log.Length] | Write-Host -NoNewLine + $BytesShown = $Log.Length + } + + if (Test-Path $SandboxTempFolder\results.clixml) { + $Timer.Stop() + } + + Start-Sleep -Milliseconds 500 + } + } finally { + if (Test-Path $SandboxTempFolder\results.clixml) { + $Results = Import-Clixml $SandboxTempFolder\results.clixml + + if ($Install) { + if ($Results.InstallExitCode -ne 0) { throw "choco install failed with $($Results.InstallExitCode)"} + } + if ($Uninstall) { + if ($Results.UninstallExitCode -ne 0) { throw "choco install failed with $($Results.UninstallExitCode)"} + } + } else { + Write-Error "Test failed after $($Timeout) minutes without a results file." + } + + if (-not $NoDestroy) { + Get-Process WindowsSandboxClient | Stop-Process + + $Tries = 0 + while ($Tries++ -lt 4 -and (Test-Path $SandboxTempFolder)) { + try { + Remove-Item $SandboxTempFolder -Recurse -Force -ErrorAction Stop + } catch { + Start-Sleep -Seconds 1 + } + } + } else { + Write-Host "Logs and Results can be found in '$($SandboxTempFolder)'" + } + } + return + } if ($Vagrant) { + Write-Host " Vagrant: ".PadRight(15) $Vagrant Write-Host "`nTesting package using vagrant" if (!$VagrantNoClear) { @@ -102,7 +213,7 @@ function Test-Package { if ($Install) { Write-Host "`nTesting package install" - choco install -y -r $package_name --version $package_version --source "'$($Nu.DirectoryName);https://chocolatey.org/api/v2/'" --force --packageParameters "'$Parameters'" | Write-Host + choco install -y -r $package_name --version $package_version --source "'$($Nu.DirectoryName);https://community.chocolatey.org/api/v2/'" --force --packageParameters "'$Parameters'" | Write-Host if ($LASTEXITCODE -ne 0) { throw "choco install failed with $LastExitCode"} }