Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(#4) Adds Windows Sandbox to Test-Package #26

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 116 additions & 5 deletions AU/Public/Test-Package.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 }
Expand All @@ -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)
Expand All @@ -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 @"
<Configuration>
<Networking>Enable</Networking>
<MappedFolders>
<MappedFolder>
<HostFolder>$($SandboxTempFolder)</HostFolder>
<SandboxFolder>C:\packages\</SandboxFolder>
<ReadOnly>false</ReadOnly>
</MappedFolder>
</MappedFolders>
<LogonCommand>
<Command>C:\packages\Test-Package.cmd</Command>
</LogonCommand>
</Configuration>
"@

$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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check for an existing windowssandbox process. If there is already one, then this will fail and we'll be waiting for the timeout to hit needlessly.

image

I would recommend the check happen early before we've done a bunch of setup.


$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)"}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be choco uninstall failed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very true! I'll get that sorted

}
} 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) {
Expand All @@ -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"}
}

Expand Down