2022-12-07 09:09:27 -08:00

514 lines
16 KiB
PowerShell

##
## Azure DevOps CI build tools
## [Add appropriate copyright]
##
$ErrorActionPreference = 'Stop'
$repoRoot = Get-RepositoryRoot
$script:messageFile = join-path $repoRoot.FullName "BuildMessage.log"
function Write-BuildMessage
{
param (
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Message,
[ValidateNotNullOrEmpty()]
[string] $Category = "Information"
)
# Write message to verbose stream.
Write-Verbose -Verbose -Message "$Category--$Message"
# Write it to the log file, if present.
if (-not ([string]::IsNullOrEmpty($script:messageFile)))
{
Add-Content -Path $script:messageFile -Value "$Category--$Message"
}
}
<#
.Synopsis
Implements the AzDO build package step
#>
function Invoke-AzDOBuild
{
Start-OpenSSHBuild -Configuration Release -NativeHostArch x64 -Verbose
Start-OpenSSHBuild -Configuration Release -NativeHostArch x86 -Verbose
Write-BuildMessage -Message "OpenSSH binaries build success!" -Category Information
}
<#
.Synopsis
Deploy all required files to a location and install the binaries
#>
function Install-OpenSSH
{
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$SourceDir,
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
UnInstall-OpenSSH -OpenSSHDir $OpenSSHDir
if (! (Test-Path -Path $OpenSSHDir)) {
$null = New-Item -Path $OpenSSHDir -ItemType Directory -Force
}
Copy-Item -Path "$SourceDir/*" -Destination $OpenSSHDir -Recurse -Force -Verbose
Push-Location $OpenSSHDir
try
{
& "$OpenSSHDir\install-sshd.ps1"
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
$newMachineEnvironmentPath = $machinePath
if (-not ($machinePath.ToLower().Contains($OpenSSHDir.ToLower())))
{
$newMachineEnvironmentPath = "$OpenSSHDir;$newMachineEnvironmentPath"
$env:Path = "$OpenSSHDir;$env:Path"
}
# Update machine environment path
if ($newMachineEnvironmentPath -ne $machinePath)
{
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
}
Start-Service -Name sshd
Start-Service -Name ssh-agent
}
finally
{
Pop-Location
}
Write-BuildMessage -Message "OpenSSH installed!" -Category Information
}
<#
.Synopsis
Uninstalled sshd
#>
function UnInstall-OpenSSH
{
[CmdletBinding()]
param (
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
if (-not (Test-Path $OpenSSHDir -PathType Container))
{
return
}
Push-Location $OpenSSHDir
try
{
if ((Get-Service ssh-agent -ErrorAction SilentlyContinue) -ne $null) {
Stop-Service ssh-agent -Force
}
& "$OpenSSHDir\uninstall-sshd.ps1"
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
$newMachineEnvironmentPath = $machinePath
if ($machinePath.ToLower().Contains($OpenSSHDir.ToLower()))
{
$newMachineEnvironmentPath = $newMachineEnvironmentPath.Replace("$OpenSSHDir;", '')
$env:Path = $env:Path.Replace("$OpenSSHDir;", '')
}
if ($newMachineEnvironmentPath -ne $machinePath)
{
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
}
}
finally
{
Pop-Location
}
Remove-Item -Path $OpenSSHDir -Recurse -Force -ErrorAction SilentlyContinue
}
#
# Install CygWin from Chocolatey and fix up install directory if needed.
#
function Install-CygWin
{
param (
[string] $InstallLocation
)
Write-Verbose -Verbose -Message "Installing CygWin from Chocolately to location: ${InstallLocation} ..."
choco install cygwin -y --force --params "/InstallDir:${InstallLocation} /NoStartMenu"
}
<#
.Synopsis
Runs the tests for this repo
#>
function Invoke-OpenSSHTests
{
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string] $OpenSSHBinPath
)
Set-BasicTestInfo -OpenSSHBinPath $OpenSSHBinPath -Confirm:$false
Write-Verbose -Verbose -Message "Running OpenSSH Set up Tests..."
$AllTestsPassed = $true
Invoke-OpenSSHSetupTest
if (($OpenSSHTestInfo -eq $null) -or (-not (Test-Path $OpenSSHTestInfo["SetupTestResultsFile"])))
{
Write-BuildMessage -Message "Test result file $OpenSSHTestInfo["SetupTestResultsFile"] not found after tests." -Category Error
$AllTestsPassed = $false
Write-Warning "Stop running further tests!"
return
}
$xml = [xml](Get-Content $OpenSSHTestInfo["SetupTestResultsFile"] | out-string)
if ([int]$xml.'test-results'.failures -gt 0)
{
$errorMessage = "$($xml.'test-results'.failures) Setup Tests in regress\pesterTests failed. Detail test log is at $($OpenSSHTestInfo["SetupTestResultsFile"])."
Write-BuildMessage -Message $errorMessage -Category Error
$AllTestsPassed = $False
Write-Warning "Stop running further tests!"
return
}
Write-BuildMessage -Message "All Setup tests passed!" -Category Information
$AllTestsPassed = $true
# Unit test directories are installed in the same directory as Open SSH binaries.
# OpenSSH Directory
# unittest-bitmap
# unittest-hostkeys
# ...
# FixHostFilePermissions.ps1
# ...
Write-Verbose -Verbose -Message "Running Unit Tests..."
Write-Verbose -Verbose -Message "Unit test directory is: ${OpenSSHBinPath}"
$unitTestFailed = Invoke-OpenSSHUnitTest -UnitTestDirectory $OpenSSHBinPath
if($unitTestFailed)
{
Write-BuildMessage "At least one of the unit tests failed!" -Category Error
$AllTestsPassed = $false
}
else
{
Write-BuildMessage -Message "All Unit tests passed!" -Category Information
}
# Run all E2E tests.
Write-Verbose -Verbose -Message "Running E2E Tests..."
Set-OpenSSHTestEnvironment -Confirm:$false
Invoke-OpenSSHE2ETest
if (($OpenSSHTestInfo -eq $null) -or (-not (Test-Path $OpenSSHTestInfo["E2ETestResultsFile"])))
{
Write-BuildMessage -Message "Test result file $OpenSSHTestInfo["E2ETestResultsFile"] not found after tests." -Category Error
$AllTestsPassed = $false
}
else
{
$xml = [xml](Get-Content $OpenSSHTestInfo["E2ETestResultsFile"] | out-string)
if ([int]$xml.'test-results'.failures -gt 0)
{
$errorMessage = "$($xml.'test-results'.failures) E2E tests in regress\pesterTests failed. Detail test log is at $($OpenSSHTestInfo["E2ETestResultsFile"])."
Write-BuildMessage -Message $errorMessage -Category Error
$AllTestsPassed = $false
}
else
{
Write-BuildMessage -Message "All E2E tests passed!" -Category Information
}
}
# Bash tests.
Write-Verbose -Verbose -Message "Running Bash Tests..."
# Ensure CygWin is installed, and install from Chocolatey if needed.
$cygwinInstalled = $true
$cygwinInstallLocation = "$env:SystemDrive/cygwin"
if (! (Test-Path -Path "$cygwinInstallLocation/bin/sh.exe"))
{
Write-Verbose -Verbose -Message "CygWin not found"
Install-CygWin -InstallLocation $cygwinInstallLocation
# Hack to fix up mangled CygWin directory, if needed.
$expectedCygWinPath = "$env:SystemDrive/cygwin/bin/sh.exe"
if (! (Test-Path -Path $expectedCygWinPath))
{
Write-Verbose -Verbose -Message "CygWin did not install correctly, missing expected path: ${expectedCygWinPath}"
$cygWinDirs = Get-Item -Path "$env:SystemDrive/cygwin*"
if ($cygWinDirs.Count -gt 1)
{
Write-Verbose -Verbose -Message "CygWin install failed with mangled folder locations: ${cygWinDirs}"
Write-Verbose -Verbose -Message 'TODO: Add hack to fix up CygWin folder.'
}
Write-BuildMessage -Message "All bash tests failed because CygWin install failed" -Category Error
$AllTestsPassed = $false
$cygwinInstalled = $false
}
}
# Run UNIX bash tests.
if ($cygwinInstalled)
{
Write-Verbose -Verbose -Message "Starting Bash Tests..."
Invoke-OpenSSHBashTests
if (-not $Global:bash_tests_summary)
{
$errorMessage = "Failed to start OpenSSH bash tests"
Write-BuildMessage -Message $errorMessage -Category Error
$AllTestsPassed = $false
}
else
{
if ($Global:bash_tests_summary["TotalBashTestsFailed"] -ne 0)
{
$total_bash_failed_tests = $Global:bash_tests_summary["TotalBashTestsFailed"]
$total_bash_tests = $Global:bash_tests_summary["TotalBashTests"]
$errorMessage = "At least one of the bash tests failed. [$total_bash_failed_tests of $total_bash_tests]"
Write-BuildMessage -Message $errorMessage -Category Error
$AllTestsPassed = $false
}
$OpenSSHTestInfo["BashTestSummaryFile"] = $Global:bash_tests_summary["BashTestSummaryFile"]
$OpenSSHTestInfo["BashTestLogFile"] = $Global:bash_tests_summary["BashTestLogFile"]
}
}
# OpenSSH Uninstall Tests
Invoke-OpenSSHUninstallTest
if (($OpenSSHTestInfo -eq $null) -or (-not (Test-Path $OpenSSHTestInfo["UninstallTestResultsFile"])))
{
Write-BuildMessage -Message "Test result file $OpenSSHTestInfo["UninstallTestResultsFile"] not found after tests." -Category Error
$AllTestsPassed = $false
}
else
{
$xml = [xml](Get-Content $OpenSSHTestInfo["UninstallTestResultsFile"] | out-string)
if ([int]$xml.'test-results'.failures -gt 0)
{
$errorMessage = "$($xml.'test-results'.failures) uninstall tests in regress\pesterTests failed. Detail test log is at $($OpenSSHTestInfo["UninstallTestResultsFile"])."
Write-BuildMessage -Message $errorMessage -Category Error
$AllTestsPassed = $false
}
}
# Save OpenSSHTestInfo for later test results uploading.
$OpenSSHTestInfo | Export-Clixml -Path "$repoRoot/OpenSSHTestInfo.xml" -Depth 10
# Writing out warning when the $Error.Count is non-zero. Tests Should clean $Error after success.
if ($Error.Count -gt 0)
{
Write-BuildMessage -Message "Tests Should always clean $Error variable after success." -Category Warning
}
if ($AllTestsPassed)
{
Write-BuildMessage -Message "All OpenSSH validation tests have passed!" -Category Information
}
else
{
Write-BuildMessage -Message "Some OpenSSH validation tests have failed." -Category Error
throw "OpenSSH validation tests failed!"
}
}
<#
.Synopsis
Collect OpenSSH pester test results into one directory
#>
function Copy-OpenSSHTestResults
{
param (
[Parameter(Mandatory=$true)]
[string] $ResultsPath
)
if (Test-Path -Path $ResultsPath)
{
Remove-Item -Path $ResultsPath -Force -Recurse -ErrorAction Ignore
}
Write-Verbose -Verbose "Creating test results directory for artifacts upload: $ResultsPath"
$null = New-Item -Path $ResultsPath -ItemType Directory -Force
if (! (Test-Path -Path $ResultsPath))
{
Write-BuildMessage -Message "Unable to write to test results path for test artifacts upload: $ResultsPath" -Category Error
return
}
$OpenSSHTestInfo = $null
$openSSHTestInfoFilePath = "$repoRoot/OpenSSHTestInfo.xml"
if (Test-Path -Path $openSSHTestInfoFilePath)
{
$OpenSSHTestInfo = Import-Clixml -Path $openSSHTestInfoFilePath
}
if (! $OpenSSHTestInfo)
{
Write-BuildMessage -Message "Unable to get OpenSSHTestInfo object from: ${openSSHTestInfoFilePath}"
return
}
try { $setupresultFile = Resolve-Path -Path $OpenSSHTestInfo["SetupTestResultsFile"] -ErrorAction Ignore } catch { }
if ($setupresultFile)
{
Write-Verbose -Verbose -Message "Copying set-up test results file, $setupresultFile, to results directory"
Copy-Item -Path $setupresultFile -Destination $ResultsPath
}
try { $E2EresultFile = Resolve-Path -Path $OpenSSHTestInfo["E2ETestResultsFile"] -ErrorAction Ignore } catch { }
if ($E2EresultFile)
{
Write-Verbose -Verbose -Message "Copying end-to-end test results file, $E2EresultFile, to results directory"
Copy-Item -Path $E2EresultFile -Destination $ResultsPath
}
try { $uninstallResultFile = Resolve-Path $OpenSSHTestInfo["UninstallTestResultsFile"] -ErrorAction Ignore } catch { }
if ($uninstallResultFile)
{
Write-Verbose -Verbose -Message "Copying uninstall test results file, $uninstallResultFile, to results directory"
Copy-Item -Path $uninstallResultFile -Destination $ResultsPath
}
try { $bashTestsSummaryFile = Resolve-Path -Path $OpenSSHTestInfo["BashTestSummaryFile"] -ErrorAction Ignore } catch { }
if ($bashTestsSummaryFile)
{
Write-Verbose -Verbose -Message "Copying bash tests summary file, $bashTestsSummaryFile, to results directory"
Copy-Item -Path $bashTestsSummaryFile -Destination $ResultsPath
}
try { $bashTestsLogFile = Resolve-Path -Path $OpenSSHTestInfo["BashTestLogFile"] -ErrorAction Ignore } catch { }
if ($bashTestsLogFile)
{
Write-Verbose -Verbose -Message "Copying bash tests log file, $bashTestsLogFile, to results directory"
Copy-Item -Path $bashTestsLogFile -Destination $ResultsPath
}
}
function Clear-TestEnvironmentSetup
{
Write-Verbose -Verbose -Message "Running OpenSSH test environment cleanup..."
try
{
$null = Clear-OpenSSHTestEnvironment -ErrorAction Ignore
$null = UnInstall-OpenSSH -ErrorAction Ignore
}
catch
{ }
Write-Verbose -Verbose -Message "OpenSSH test environment cleanup complete."
}
<#
.SYNOPSIS
Copy build results package to provided destination path.
#>
function Copy-BuildResults
{
param (
[Parameter(Mandatory=$true)]
[string] $BuildResultsPath,
[ValidateSet('x86', 'x64', 'arm64', 'arm')]
[string]$NativeHostArch = "x64",
[ValidateSet('Debug', 'Release')]
[string]$Configuration = "Release"
)
# Copy OpenSSH package to results directory
Start-OpenSSHPackage -DestinationPath $BuildResultsPath -NativeHostArch $NativeHostArch -Configuration $Configuration
}
<#
.SYNOPSIS
Copy build unit tests to provided destination path.
#>
function Copy-UnitTests
{
param (
[Parameter(Mandatory=$true)]
[string] $UnitTestsSrcDir,
[Parameter(Mandatory=$true)]
[string] $UnitTestsDestDir,
[ValidateSet('x86', 'x64', 'arm64', 'arm')]
[string]$NativeHostArch = "x64",
[ValidateSet('Debug', 'Release')]
[string]$Configuration = "Release"
)
if (! (Test-Path -Path $UnitTestsDestDir))
{
Write-Verbose -Verbose -Message "Creating Unit Test directory: $UnitTestsDestDir"
$null = New-Item -Path $UnitTestsDestDir -ItemType Directory -Force
}
if ($NativeHostArch -eq 'x86')
{
$unitTestsSrcPath = Join-Path -Path $UnitTestsSrcDir -ChildPath "Win32/${Configuration}"
}
else
{
$unitTestsSrcPath = Join-Path -Path $UnitTestsSrcDir -ChildPath "${NativeHostArch}/${Configuration}"
}
$unitTestsDestPath = Join-Path -Path $UnitTestsDestDir -ChildPath "${NativeHostArch}/${Configuration}"
if (! (Test-Path -Path $unitTestsDestPath))
{
Write-Verbose -Verbose -Message "Creating Unit Test directory: $unitTestsDestPath"
$null = New-Item -Path $unitTestsDestPath -ItemType Directory -Force
}
Write-Verbose -Verbose -Message "Copying unit tests from: ${unitTestsSrcPath} to: ${unitTestsDestPath}"
Copy-Item -Path "$unitTestsSrcPath/unittest-*" -Destination $unitTestsDestPath -Recurse -Force
}
<#
.SYNOPSIS
Install unit tests to provided destination.
#>
function Install-UnitTests
{
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$SourceDir,
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
if (! (Test-Path -Path $OpenSSHDir)) {
$null = New-Item -Path $OpenSSHDir -ItemType Directory -Force
}
Copy-Item -Path "$SourceDir/*" -Destination $OpenSSHDir -Recurse -Force
}