diff --git a/utils/build.ps1 b/utils/build.ps1 index 49ba6b6a0a462..ea640a78a10db 100644 --- a/utils/build.ps1 +++ b/utils/build.ps1 @@ -118,6 +118,10 @@ steps. .PARAMETER SkipPackaging Skip building the MSI installers and packaging. Useful for development builds. +.PARAMETER SmokeTest +Smoke test the installer. Mutually exclusive with `-SkipPackaging`. +Requires Docker installation with Windows container support and Hyper-V isolation. + .PARAMETER Test An array of names of projects to run tests for. Use '*' to run all tests. Available tests: lld, lldb, swift, dispatch, foundation, xctest, swift-format, sourcekit-lsp @@ -210,6 +214,9 @@ param [switch] $SkipPackaging = $false, [string[]] $Test = @(), + # XXX: True temporarily for testing. Do not merge. + [switch] $SmokeTest = $true, + [switch] $IncludeDS2 = $false, [ValidateSet("none", "full", "thin")] [string] $LTO = "none", @@ -247,6 +254,10 @@ if (($PinnedBuild -or $PinnedSHA256 -or $PinnedVersion) -and -not ($PinnedBuild throw "If any of PinnedBuild, PinnedSHA256, or PinnedVersion is set, all three must be set." } +if ($SmokeTest -and $SkipPackaging) { + throw "Cannot use -SmokeTest with -SkipPackaging." +} + # Work around limitations of cmd passing in array arguments via powershell.exe -File if ($AndroidSDKVersions.Length -eq 1) { $AndroidSDKVersions = $AndroidSDKVersions[0].Split(",") } if ($AndroidSDKArchitectures.Length -eq 1) { $AndroidSDKArchitectures = $AndroidSDKArchitectures[0].Split(",") } @@ -3972,6 +3983,73 @@ function Copy-BuildArtifactsToStage([Hashtable] $Platform) { Invoke-Program "$($WiX.Path)\wix.exe" -- burn detach "$BinaryCache\$($Platform.Triple)\installer\Release\$($Platform.Architecture.VSName)\installer.exe" -engine "$Stage\installer-engine.exe" -intermediateFolder "$BinaryCache\$($Platform.Triple)\installer\$($Platform.Architecture.VSName)\" } +# Ensure: +# - Docker is installed +# - Docker is configured for Windows containers +# - Docker supports Hyper-V isolation +# If all conditions are not met, exit with an error. +function Check-DockerRequirements() { + try { + $dockerVersion = docker version 2>$null + if ($LASTEXITCODE -ne 0) { + throw "Docker is not installed or not running" + } + + $dockerInfo = docker info 2>$null + if ($dockerInfo -notmatch "OSType:\s*windows") { + throw "Docker is not configured for Windows containers." + } + + if ($dockerInfo -notmatch "Isolation:\s*hyperv") { + $hyperVSupport = $dockerInfo -match "hyperv" + if (-not $hyperVSupport) { + throw "Docker does not support Hyper-V isolation." + } + } + } catch { + Write-Host -ForegroundColor Red "Docker requirements check failed: $_" + exit 1 + } +} + +function Run-SmokeTests([Hashtable] $Platform) { + Check-DockerRequirements + + $InstallerPath = "$BinaryCache\$($Platform.Triple)\installer\Release\$($Platform.Architecture.VSName)\installer.exe" + if (-not (Test-Path $InstallerPath)) { + throw "Installer not found at: $InstallerPath" + } + + $SmokeTestDir = Join-Path $PSScriptRoot "windows-smoke-tests" + $InstallerFileName = Split-Path $InstallerPath -Leaf + + Copy-Item $InstallerPath (Join-Path $SmokeTestDir $InstallerFileName) -Force + + Push-Location $SmokeTestDir + try { + Record-OperationTiming $Platform "SmokeTests-DockerBuild" { + Write-Host "Building Docker image with installer" + docker build --build-arg SWIFT_INSTALLER_PATH=$InstallerFileName --isolation=hyperv -t swift-smoke-test . + if ($LASTEXITCODE -ne 0) { + throw "Docker build failed" + } + } + + Record-OperationTiming $Platform "SmokeTest-DockerRun" { + Write-Host "Running smoke test container" + docker run --rm --isolation=hyperv swift-smoke-test + if ($LASTEXITCODE -ne 0) { + throw "Smoke test failed" + } + } + + Write-Host -ForegroundColor Green "Smoke test completed successfully!" + } finally { + Pop-Location + Remove-Item (Join-Path $SmokeTestDir $InstallerFileName) -ErrorAction SilentlyContinue + } +} + function Build-NoAssertsToolchain() { if ($ToBatch) { Write-Output "" @@ -4322,6 +4400,12 @@ if (-not $IsCrossCompiling) { } } +if ($SmokeTest) { + Record-OperationTiming $HostPlatform "Run-SmokeTests" { + Run-SmokeTests $HostPlatform + } +} + if ($IncludeSBoM) { Invoke-IsolatingEnvVars { $env:SYFT_FILE_METADATA_SELECTION = "all" diff --git a/utils/windows-smoke-tests/Dockerfile b/utils/windows-smoke-tests/Dockerfile new file mode 100644 index 0000000000000..b1fc224cf3038 --- /dev/null +++ b/utils/windows-smoke-tests/Dockerfile @@ -0,0 +1,106 @@ +# Based on https://github.com/swiftlang/swift-docker/blob/main/nightly-main/windows/LTSC2022/Dockerfile +FROM mcr.microsoft.com/windows/servercore:ltsc2022 + +SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] + +# Install Git. +ARG GIT=https://github.com/git-for-windows/git/releases/download/v2.42.0.windows.2/Git-2.42.0.2-64-bit.exe +ARG GIT_SHA256=BD9B41641A258FD16D99BEECEC66132160331D685DFB4C714CEA2BCC78D63BDB +RUN Write-Host -NoNewLine ('Downloading {0} ... ' -f ${env:GIT}); \ + Invoke-WebRequest -Uri ${env:GIT} -OutFile git.exe; \ + Write-Host '✓'; \ + Write-Host -NoNewLine ('Verifying SHA256 ({0}) ... ' -f ${env:GIT_SHA256}); \ + $Hash = Get-FileHash git.exe -Algorithm sha256; \ + if ($Hash.Hash -eq ${env:GIT_SHA256}) { \ + Write-Host '✓'; \ + } else { \ + Write-Host ('✘ ({0})' -f $Hash.Hash); \ + exit 1; \ + } \ + Write-Host -NoNewLine 'Installing git ... '; \ + $Process = \ + Start-Process git.exe -Wait -PassThru -NoNewWindow -ArgumentList @( \ + '/SP-', \ + '/VERYSILENT', \ + '/SUPPRESSMSGBOXES', \ + '/NOCANCEL', \ + '/NORESTART', \ + '/CLOSEAPPLICATIONS', \ + '/FORCECLOSEAPPLICATIONS', \ + '/NOICONS', \ + '/COMPONENTS="gitlfs"', \ + '/EditorOption=VIM', \ + '/PathOption=Cmd', \ + '/SSHOption=OpenSSH', \ + '/CURLOption=WinSSL', \ + '/UseCredentialManager=Enabled', \ + '/EnableSymlinks=Enabled', \ + '/EnableFSMonitor=Enabled' \ + ); \ + if ($Process.ExitCode -eq 0) { \ + Write-Host '✓'; \ + } else { \ + Write-Host ('✘ ({0})' -f $Process.ExitCode); \ + exit 1; \ + } \ + Remove-Item -Force git.exe; \ + Remove-Item -ErrorAction SilentlyContinue -Force -Recurse ${env:TEMP}\* + +# Install Visual Studio Build Tools +ARG VSB=https://download.visualstudio.microsoft.com/download/pr/5536698c-711c-4834-876f-2817d31a2ef2/c792bdb0fd46155de19955269cac85d52c4c63c23db2cf43d96b9390146f9390/vs_BuildTools.exe +ARG VSB_SHA256=C792BDB0FD46155DE19955269CAC85D52C4C63C23DB2CF43D96B9390146F9390 +RUN Write-Host -NoNewLine ('Downloading {0} ... ' -f ${env:VSB}); \ + Invoke-WebRequest -Uri ${env:VSB} -OutFile vs_buildtools.exe; \ + Write-Host '✓'; \ + Write-Host -NoNewLine ('Verifying SHA256 ({0}) ... ' -f ${env:VSB_SHA256}); \ + $Hash = Get-FileHash vs_buildtools.exe -Algorithm sha256; \ + if ($Hash.Hash -eq ${env:VSB_SHA256}) { \ + Write-Host '✓'; \ + } else { \ + Write-Host ('✘ ({0})' -f $Hash.Hash); \ + exit 1; \ + } \ + Write-Host -NoNewLine 'Installing Visual Studio Build Tools ... '; \ + $Process = \ + Start-Process vs_buildtools.exe -Wait -PassThru -NoNewWindow -ArgumentList @( \ + '--quiet', \ + '--wait', \ + '--norestart', \ + '--nocache', \ + '--add', 'Microsoft.VisualStudio.Component.Windows11SDK.22000', \ + '--add', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64' \ + ); \ + if ($Process.ExitCode -eq 0 -or $Process.ExitCode -eq 3010) { \ + Write-Host '✓'; \ + } else { \ + Write-Host ('✘ ({0})' -f $Process.ExitCode); \ + exit 1; \ + } \ + Remove-Item -Force vs_buildtools.exe; \ + Remove-Item -ErrorAction SilentlyContinue -Force -Recurse ${env:TEMP}\* + +# Build argument for the Swift installer path +ARG SWIFT_INSTALLER_PATH + +# Copy the Swift installer from the build context +COPY ${SWIFT_INSTALLER_PATH} installer.exe + +# Install Swift toolchain +RUN Write-Host -NoNewLine 'Installing Swift ... '; \ + $Process = \ + Start-Process installer.exe -Wait -PassThru -NoNewWindow -ArgumentList @( \ + '/quiet', \ + '/norestart' \ + ); \ + if ($Process.ExitCode -eq 0) { \ + Write-Host '✓'; \ + } else { \ + Write-Host ('✘ ({0})' -f $Process.ExitCode); \ + exit 1; \ + } \ + Remove-Item -Force installer.exe; \ + Remove-Item -ErrorAction SilentlyContinue -Force -Recurse ${env:TEMP}\* + +COPY smoke_test.ps1 smoke_test.ps1 + +ENTRYPOINT ["powershell", "-File", "./smoke_test.ps1"] \ No newline at end of file diff --git a/utils/windows-smoke-tests/smoke_test.ps1 b/utils/windows-smoke-tests/smoke_test.ps1 new file mode 100644 index 0000000000000..6b94611db4bbb --- /dev/null +++ b/utils/windows-smoke-tests/smoke_test.ps1 @@ -0,0 +1,30 @@ +# Attempts to build and test `swift-win32`. +$ErrorActionPreference = 'Stop' + +Write-Host "Starting smoke test" +Write-Host "" + +swift --version +Write-Host "" + +$RepoUrl = "https://github.com/compnerd/swift-win32" +$CloneDir = "C:\swift-win32" + +Write-Host "Cloning $RepoUrl" +git clone $RepoUrl $CloneDir +if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } +Write-Host "" + +Set-Location $CloneDir + +Write-Host "Building swift-win32" +swift build +if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } +Write-Host "" + +Write-Host "Testing swift-win32" +swift test -Xswiftc -DENABLE_TESTING +if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } +Write-Host "" + +Write-Host "Smoke test completed successfully!" -ForegroundColor Green