PowerShell/tools/ci.psm1

767 lines
28 KiB
PowerShell
Raw Normal View History

# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
Set-StrictMode -Version 3.0
$ErrorActionPreference = 'continue'
$repoRoot = Join-Path $PSScriptRoot '..'
$script:administratorsGroupSID = "S-1-5-32-544"
$script:usersGroupSID = "S-1-5-32-545"
# set .NET path
$dotNetPath = "$env:USERPROFILE\Appdata\Local\Microsoft\dotnet"
if(Test-Path $dotNetPath)
{
$env:PATH = $dotNetPath + ';' + $env:PATH
}
# import build into the global scope so it can be used by packaging
Import-Module (Join-Path $repoRoot 'build.psm1') -Verbose -Scope Global
Import-Module (Join-Path $repoRoot 'tools\packaging') -Verbose -Scope Global
# import the windows specific functcion only in Windows PowerShell or on Windows
if($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows)
{
Import-Module (Join-Path $PSScriptRoot 'WindowsCI.psm1') -Scope Global
}
# tests if we should run a daily build
2017-01-16 22:31:14 +01:00
# returns true if the build is scheduled
# or is a pushed tag
Function Test-DailyBuild
{
2017-07-23 00:34:03 +02:00
$trueString = 'True'
if(($env:PS_DAILY_BUILD -eq $trueString) -or $env:BUILD_REASON -eq 'Schedule')
{
return $true
}
return $false
}
# Sets a build variable
Function Set-BuildVariable
{
param(
[Parameter(Mandatory=$true)]
[string]
$Name,
[Parameter(Mandatory=$true)]
[string]
$Value
)
if($env:TF_BUILD)
{
# In VSTS
Write-Host "##vso[task.setvariable variable=$Name;]$Value"
# The variable will not show up until the next task.
# Setting in the current session for the same behavior as the CI
Set-Item env:/$name -Value $Value
}
2017-01-16 22:31:14 +01:00
else
{
Set-Item env:/$name -Value $Value
}
}
# Emulates running all of CI but locally
function Invoke-CIFull
{
param(
[switch] $CleanRepo
)
if($CleanRepo)
{
Clear-PSRepo
}
Invoke-CIInstall
Invoke-CIBuild
Invoke-CITest -ErrorAction Continue
Invoke-CIFinish
}
# Implements the CI 'build_script' step
function Invoke-CIBuild
{
$releaseTag = Get-ReleaseTag
# check to be sure our test tags are correct
$result = Get-PesterTag
if ( $result.Result -ne "Pass" )
{
$result.Warnings
throw "Tags must be CI, Feature, Scenario, or Slow"
}
Add OpenCover PS Module to collect code coverage (#2585) * Add OpenCover PS Module to collect code coverage OpenCover PS Module helps is collecting Code Coverage using the OpenCover toolset. The module helps in comparing two code coverage runs as well. * Change OpenCover.psd1 to ASCII * Fix an error in path for OpenCover Fixed an error on path for OpenCover. Also used ZipFile class instead of cmdlet as it might not be available on CI system. * Convert module to be Powershell v4 compliant Changed implementation from classes to PSObjects and implemented Expand-ZipArchive. * Added CodeCoverage as a configuration to project.json files Added CodeCoverage as the new configuration for all the project.json files. When Start-PSBuild is executed with configuration as CodeCoverage, we change the degubType to 'full' as required by OpenCover toolset. Also made changes to appveyor.psm1 to build a CodeCoverage package on daily builds and publish it as a zip. * Addressed code review comments Changed from Add-Member to use pscustomobject type accelator. Removed [gc]::collect. * Added explicit garbage collection * Addressed code review comments - Make sure that the build Start-PSPackage gets is not a code coverage build - Add debugType = full for FullCLR - Remove configurations from PackageManagement files as it is not needed. - Build CodeCoverage build first in AppVeyor. * Resolve merge conflict * Fix indentation * Fix newline at end of file * Added command discovery for locating OpenCover.console.exe
2016-11-11 20:12:07 +01:00
if(Test-DailyBuild)
{
Start-PSBuild -Configuration 'CodeCoverage' -PSModuleRestore -CI -ReleaseTag $releaseTag
}
Add OpenCover PS Module to collect code coverage (#2585) * Add OpenCover PS Module to collect code coverage OpenCover PS Module helps is collecting Code Coverage using the OpenCover toolset. The module helps in comparing two code coverage runs as well. * Change OpenCover.psd1 to ASCII * Fix an error in path for OpenCover Fixed an error on path for OpenCover. Also used ZipFile class instead of cmdlet as it might not be available on CI system. * Convert module to be Powershell v4 compliant Changed implementation from classes to PSObjects and implemented Expand-ZipArchive. * Added CodeCoverage as a configuration to project.json files Added CodeCoverage as the new configuration for all the project.json files. When Start-PSBuild is executed with configuration as CodeCoverage, we change the degubType to 'full' as required by OpenCover toolset. Also made changes to appveyor.psm1 to build a CodeCoverage package on daily builds and publish it as a zip. * Addressed code review comments Changed from Add-Member to use pscustomobject type accelator. Removed [gc]::collect. * Added explicit garbage collection * Addressed code review comments - Make sure that the build Start-PSPackage gets is not a code coverage build - Add debugType = full for FullCLR - Remove configurations from PackageManagement files as it is not needed. - Build CodeCoverage build first in AppVeyor. * Resolve merge conflict * Fix indentation * Fix newline at end of file * Added command discovery for locating OpenCover.console.exe
2016-11-11 20:12:07 +01:00
Start-PSBuild -PSModuleRestore -Configuration 'Release' -CI -ReleaseTag $releaseTag
Save-PSOptions
$options = (Get-PSOptions)
$path = Split-Path -Path $options.Output
$psOptionsPath = (Join-Path -Path $PSScriptRoot -ChildPath '../psoptions.json')
$buildZipPath = (Join-Path -Path $PSScriptRoot -ChildPath '../build.zip')
Compress-Archive -Path $path -DestinationPath $buildZipPath
Push-Artifact -Path $psOptionsPath -Name 'build'
Push-Artifact -Path $buildZipPath -Name 'build'
}
# Implements the CI 'install' step
function Invoke-CIInstall
{
param(
[switch]
$SkipUser
)
# Make sure we have all the tags
Sync-PSTags -AddRemoteIfMissing
if(Test-DailyBuild)
{
if ($env:BUILD_REASON -eq 'Schedule')
{
Write-Host "##vso[build.updatebuildnumber]Daily-$env:BUILD_SOURCEBRANCHNAME-$env:BUILD_SOURCEVERSION-$((Get-Date).ToString("yyyyMMddhhss"))"
}
}
if ($env:TF_BUILD -and !$SkipUser.IsPresent)
{
# Generate new credential for CI (only) remoting tests.
Write-Verbose "Creating account for remoting tests in CI." -Verbose
# Password
$randomObj = [System.Random]::new()
$password = ""
1..(Get-Random -Minimum 15 -Maximum 126) | ForEach-Object { $password = $password + [char]$randomObj.next(45,126) }
# Account
$userName = 'ciRemote'
New-LocalUser -username $userName -Password $password
Add-UserToGroup -username $userName -groupSid $script:administratorsGroupSID
# Provide credentials globally for remote tests.
$ss = ConvertTo-SecureString -String $password -AsPlainText -Force
$ciRemoteCredential = [PSCredential]::new("$env:COMPUTERNAME\$userName", $ss)
$ciRemoteCredential | Export-Clixml -Path "$env:TEMP\CIRemoteCred.xml" -Force
# Check that LocalAccountTokenFilterPolicy policy is set, since it is needed for remoting
# using above local admin account.
Write-Log -Message "Checking for LocalAccountTokenFilterPolicy in the CI."
$haveLocalAccountTokenFilterPolicy = $false
try
{
$haveLocalAccountTokenFilterPolicy = ((Get-ItemPropertyValue -Path HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name LocalAccountTokenFilterPolicy) -eq 1)
}
# ignore if anything is caught:
catch {}
if (!$haveLocalAccountTokenFilterPolicy)
{
Write-Verbose "Setting the LocalAccountTokenFilterPolicy for remoting tests"
Set-ItemProperty -Path HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name LocalAccountTokenFilterPolicy -Value 1
}
}
Set-BuildVariable -Name TestPassed -Value False
Start-PSBootstrap
}
function Invoke-CIxUnit
{
param(
[switch]
$SkipFailing
)
$env:CoreOutput = Split-Path -Parent (Get-PSOutput -Options (Get-PSOptions))
$path = "$env:CoreOutput\pwsh.exe"
if($IsMacOS -or $IsLinux)
{
$path = "$env:CoreOutput\pwsh"
}
if(!(Test-Path $path))
{
throw "CoreCLR pwsh.exe was not built"
}
$xUnitTestResultsFile = Join-Path -Path $PWD -ChildPath "xUnitTestResults.xml"
Start-PSxUnit -xUnitTestResultsFile $xUnitTestResultsFile
Push-Artifact -Path $xUnitTestResultsFile -name xunit
if(!$SkipFailing.IsPresent)
{
# Fail the build, if tests failed
Test-XUnitTestResults -TestResultsFile $xUnitTestResultsFile
}
}
# Implement CI 'Test_script'
function Invoke-CITest
{
[CmdletBinding()]
param(
[ValidateSet('UnelevatedPesterTests', 'ElevatedPesterTests')]
[string] $Purpose,
[ValidateSet('CI', 'Others')]
[string] $TagSet
)
2017-01-16 22:31:14 +01:00
# Set locale correctly for Linux CIs
Set-CorrectLocale
# Pester doesn't allow Invoke-Pester -TagAll@('CI', 'RequireAdminOnWindows') currently
# https://github.com/pester/Pester/issues/608
# To work-around it, we exlude all categories, but 'CI' from the list
switch ($TagSet) {
'CI' {
Write-Host -Foreground Green 'Running "CI" CoreCLR tests..'
$ExcludeTag = @('Slow', 'Feature', 'Scenario')
}
'Others' {
Write-Host -Foreground Green 'Running non-CI CoreCLR tests..'
$ExcludeTag = @('CI')
}
Default {
throw "Unknown TagSet: '$TagSet'"
}
}
2017-01-16 22:31:14 +01:00
if($IsLinux -or $IsMacOS)
{
return Invoke-LinuxTestsCore -Purpose $Purpose -ExcludeTag $ExcludeTag -TagSet $TagSet
}
# CoreCLR
$env:CoreOutput = Split-Path -Parent (Get-PSOutput -Options (Get-PSOptions))
Write-Host -Foreground Green 'Run CoreCLR tests'
2020-01-13 20:24:10 +01:00
$testResultsNonAdminFile = "$PWD\TestsResultsNonAdmin-$TagSet.xml"
$testResultsAdminFile = "$PWD\TestsResultsAdmin-$TagSet.xml"
if(!(Test-Path "$env:CoreOutput\pwsh.exe"))
{
throw "CoreCLR pwsh.exe was not built"
}
# Get the experimental feature names and the tests associated with them
$ExperimentalFeatureTests = Get-ExperimentalFeatureTests
if ($Purpose -eq 'UnelevatedPesterTests') {
$arguments = @{
Bindir = $env:CoreOutput
OutputFile = $testResultsNonAdminFile
Unelevate = $true
Terse = $true
Tag = @()
ExcludeTag = $ExcludeTag + 'RequireAdminOnWindows'
}
Start-PSPester @arguments -Title "Pester Unelevated - $TagSet"
# Fail the build, if tests failed
Test-PSPesterResults -TestResultsFile $testResultsNonAdminFile
# Run tests with specified experimental features enabled
foreach ($entry in $ExperimentalFeatureTests.GetEnumerator())
{
$featureName = $entry.Key
$testFiles = $entry.Value
2020-01-13 20:24:10 +01:00
$expFeatureTestResultFile = "$PWD\TestsResultsNonAdmin.$featureName.xml"
$arguments['OutputFile'] = $expFeatureTestResultFile
$arguments['ExperimentalFeatureName'] = $featureName
if ($testFiles.Count -eq 0) {
# If an empty array is specified for the feature name, we run all tests with the feature enabled.
# This allows us to prevent regressions to a critical engine experimental feature.
$arguments.Remove('Path')
} else {
# If a non-empty string or array is specified for the feature name, we only run those test files.
$arguments['Path'] = $testFiles
}
Start-PSPester @arguments -Title "Pester Experimental Unelevated - $featureName"
# Fail the build, if tests failed
Test-PSPesterResults -TestResultsFile $expFeatureTestResultFile
}
}
if ($Purpose -eq 'ElevatedPesterTests') {
$arguments = @{
Terse = $true
Bindir = $env:CoreOutput
OutputFile = $testResultsAdminFile
Tag = @('RequireAdminOnWindows')
ExcludeTag = $ExcludeTag
}
Start-PSPester @arguments -Title "Pester Elevated - $TagSet"
# Fail the build, if tests failed
Test-PSPesterResults -TestResultsFile $testResultsAdminFile
# Run tests with specified experimental features enabled
foreach ($entry in $ExperimentalFeatureTests.GetEnumerator())
{
$featureName = $entry.Key
$testFiles = $entry.Value
2020-01-13 20:24:10 +01:00
$expFeatureTestResultFile = "$PWD\TestsResultsAdmin.$featureName.xml"
$arguments['OutputFile'] = $expFeatureTestResultFile
$arguments['ExperimentalFeatureName'] = $featureName
if ($testFiles.Count -eq 0)
{
# If an empty array is specified for the feature name, we run all tests with the feature enabled.
# This allows us to prevent regressions to a critical engine experimental feature.
$arguments.Remove('Path')
}
else
{
# If a non-empty string or array is specified for the feature name, we only run those test files.
$arguments['Path'] = $testFiles
}
Start-PSPester @arguments -Title "Pester Experimental Elevated - $featureName"
# Fail the build, if tests failed
Test-PSPesterResults -TestResultsFile $expFeatureTestResultFile
}
}
Set-BuildVariable -Name TestPassed -Value True
}
function New-CodeCoverageAndTestPackage
{
[CmdletBinding()]
param()
if (Test-DailyBuild)
{
Start-PSBootstrap -Verbose
Start-PSBuild -Configuration 'CodeCoverage' -Clean
$codeCoverageOutput = Split-Path -Parent (Get-PSOutput)
$codeCoverageArtifacts = Compress-CoverageArtifacts -CodeCoverageOutput $codeCoverageOutput
$destBasePath = if ($env:TF_BUILD) {
$env:BUILD_ARTIFACTSTAGINGDIRECTORY
} else {
Join-Path (Get-Location).Path "out"
}
if (-not (Test-Path $destBasePath))
{
$null = New-Item -ItemType Directory -Path $destBasePath
}
Write-Host -ForegroundColor Green 'Upload CodeCoverage artifacts'
$codeCoverageArtifacts | ForEach-Object {
Copy-Item -Path $_ -Destination $destBasePath
$newPath = Join-Path $destBasePath (Split-Path $_ -Leaf)
Push-Artifact -Path $newPath -Name 'CodeCoverage'
}
New-TestPackage -Destination $destBasePath
$testPackageFullName = Join-Path $destBasePath 'TestPackage.zip'
Write-Verbose "Created TestPackage.zip" -Verbose
Write-Host -ForegroundColor Green 'Upload test package'
Push-Artifact $testPackageFullName -Name 'CodeCoverage'
}
}
# Wrapper to push artifact
function Push-Artifact
{
param(
[Parameter(Mandatory)]
[ValidateScript({Test-Path -Path $_})]
$Path,
[string]
$Name
)
if(!$Name)
{
$artifactName = [system.io.path]::GetFileName($Path)
}
else
{
$artifactName = $Name
}
if ($env:TF_BUILD) {
# In Azure DevOps
Write-Host "##vso[artifact.upload containerfolder=$artifactName;artifactname=$artifactName;]$Path"
}
}
function Compress-CoverageArtifacts
{
param([string] $CodeCoverageOutput)
# Create archive for test content, OpenCover module and CodeCoverage build
$artifacts = New-Object System.Collections.ArrayList
Add-Type -AssemblyName System.IO.Compression.FileSystem
$resolvedPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath((Join-Path $PSScriptRoot '..\test\tools\OpenCover'))
2020-01-13 20:24:10 +01:00
$zipOpenCoverPath = Join-Path $PWD 'OpenCover.zip'
2017-01-16 22:31:14 +01:00
[System.IO.Compression.ZipFile]::CreateFromDirectory($resolvedPath, $zipOpenCoverPath)
$null = $artifacts.Add($zipOpenCoverPath)
2020-01-13 20:24:10 +01:00
$zipCodeCoveragePath = Join-Path $PWD "CodeCoverage.zip"
Write-Verbose "Zipping ${CodeCoverageOutput} into $zipCodeCoveragePath" -Verbose
[System.IO.Compression.ZipFile]::CreateFromDirectory($CodeCoverageOutput, $zipCodeCoveragePath)
$null = $artifacts.Add($zipCodeCoveragePath)
return $artifacts
}
function Get-ReleaseTag
{
$metaDataPath = Join-Path -Path $PSScriptRoot -ChildPath 'metadata.json'
$metaData = Get-Content $metaDataPath | ConvertFrom-Json
$releaseTag = $metadata.NextReleaseTag
if($env:BUILD_BUILID)
{
$releaseTag = $releaseTag.split('.')[0..2] -join '.'
$releaseTag = $releaseTag + '.' + $env:BUILD_BUILID
}
return $releaseTag
}
# Implements CI 'on_finish' step
function Invoke-CIFinish
{
param(
[string] $Runtime = 'win7-x64',
[string] $Channel = 'preview',
[Validateset('Build','Package')]
[string[]] $Stage = ('Build','Package')
)
if ($PSEdition -eq 'Core' -and ($IsLinux -or $IsMacOS) -and $Stage -contains 'Build') {
return New-LinuxPackage
}
$artifacts = New-Object System.Collections.ArrayList
try {
$buildFolder = "${env:SYSTEM_ARTIFACTSDIRECTORY}/mainBuild"
if ($Stage -contains "Build") {
if ($Channel -eq 'preview') {
$releaseTag = Get-ReleaseTag
$previewVersion = $releaseTag.Split('-')
$previewPrefix = $previewVersion[0]
$previewLabel = $previewVersion[1].replace('.','')
if (Test-DailyBuild) {
$previewLabel = "daily{0}" -f $previewLabel
}
$prereleaseIteration = (get-date).Day
$preReleaseVersion = "$previewPrefix-$previewLabel.$prereleaseIteration"
# Build clean before backing to remove files from testing
Start-PSBuild -PSModuleRestore -Configuration 'Release' -ReleaseTag $preReleaseVersion -Clean -Runtime $Runtime -output $buildFolder -PSOptionsPath "${buildFolder}/psoptions.json"
$options = Get-PSOptions
# Remove symbol files.
$filter = Join-Path -Path (Split-Path $options.Output) -ChildPath '*.pdb'
Write-Verbose "Removing symbol files from $filter" -Verbose
Remove-Item $filter -Force -Recurse
} else {
$releaseTag = Get-ReleaseTag
$releaseTagParts = $releaseTag.split('.')
$preReleaseVersion = $releaseTagParts[0]+ ".9.9"
Write-Verbose "newPSReleaseTag: $preReleaseVersion" -Verbose
Start-PSBuild -PSModuleRestore -Configuration 'Release' -ReleaseTag $preReleaseVersion -Clean -Runtime $Runtime -output $buildFolder -PSOptionsPath "${buildFolder}/psoptions.json"
$options = Get-PSOptions
# Remove symbol files.
$filter = Join-Path -Path (Split-Path $options.Output) -ChildPath '*.pdb'
Write-Verbose "Removing symbol files from $filter" -Verbose
Remove-Item $filter -Force -Recurse
}
# Set a variable, both in the current process and in AzDevOps for the packaging stage to get the release tag
$env:CI_FINISH_RELASETAG=$preReleaseVersion
$vstsCommandString = "vso[task.setvariable variable=CI_FINISH_RELASETAG]$preReleaseVersion"
Write-Verbose -Message "$vstsCommandString" -Verbose
Write-Host -Object "##$vstsCommandString"
}
if ($Stage -contains "Package") {
Restore-PSOptions -PSOptionsPath "${buildFolder}/psoptions.json"
$preReleaseVersion = $env:CI_FINISH_RELASETAG
# Build packages $preReleaseVersion = "$previewPrefix-$previewLabel.$prereleaseIteration"
switch -regex ($Runtime){
default {
$runPackageTest = $true
$packageTypes = 'msi', 'nupkg', 'zip', 'zip-pdb', 'msix'
}
'win-arm.*' {
$runPackageTest = $false
$packageTypes = 'zip', 'zip-pdb', 'msix'
}
}
$packages = Start-PSPackage -Type $packageTypes -ReleaseTag $preReleaseVersion -SkipReleaseChecks -WindowsRuntime $Runtime
foreach ($package in $packages) {
if (Test-Path $package -ErrorAction Ignore) {
Write-Log "Package found: $package"
} else {
Write-Warning -Message "Package NOT found: $package"
}
if ($package -is [string]) {
$null = $artifacts.Add($package)
} elseif ($package -is [pscustomobject] -and $package.psobject.Properties['msi']) {
$null = $artifacts.Add($package.msi)
$null = $artifacts.Add($package.wixpdb)
}
}
if ($runPackageTest) {
# the packaging tests find the MSI package using env:PSMsiX64Path
$env:PSMsiX64Path = $artifacts | Where-Object { $_.EndsWith(".msi")}
$architechture = $Runtime.Split('-')[1]
$exePath = New-ExePackage -ProductVersion ($preReleaseVersion -replace '^v') -ProductTargetArchitecture $architechture -MsiLocationPath $env:PSMsiX64Path
Write-Verbose "exe Path: $exePath" -Verbose
$artifacts.Add($exePath)
$env:PSExePath = $exePath
$env:PSMsiChannel = $Channel
$env:PSMsiRuntime = $Runtime
# Install the latest Pester and import it
$maximumPesterVersion = '4.99'
Install-Module Pester -Force -SkipPublisherCheck -MaximumVersion $maximumPesterVersion
Import-Module Pester -Force -MaximumVersion $maximumPesterVersion
$testResultPath = Join-Path -Path $env:TEMP -ChildPath "win-package-$channel-$runtime.xml"
# start the packaging tests and get the results
$packagingTestResult = Invoke-Pester -Script (Join-Path $repoRoot '.\test\packaging\windows\') -PassThru -OutputFormat NUnitXml -OutputFile $testResultPath
Publish-TestResults -Title "win-package-$channel-$runtime" -Path $testResultPath
# fail the CI job if the tests failed, or nothing passed
if (-not $packagingTestResult -is [pscustomobject] -or $packagingTestResult.FailedCount -ne 0 -or $packagingTestResult.PassedCount -eq 0) {
throw "Packaging tests failed ($($packagingTestResult.FailedCount) failed/$($packagingTestResult.PassedCount) passed)"
}
}
# only publish assembly nuget packages if it is a daily build and tests passed
if (Test-DailyBuild) {
$nugetArtifacts = Get-ChildItem $PSScriptRoot\packaging\nugetOutput -ErrorAction SilentlyContinue -Filter *.nupkg | Select-Object -ExpandProperty FullName
if ($nugetArtifacts) {
$artifacts.AddRange(@($nugetArtifacts))
}
}
}
} catch {
Get-Error -InputObject $_
throw
} finally {
$pushedAllArtifacts = $true
2017-01-16 22:31:14 +01:00
$artifacts | ForEach-Object {
Write-Log -Message "Pushing $_ as CI artifact"
if (Test-Path $_) {
Push-Artifact -Path $_ -Name 'artifacts'
} else {
$pushedAllArtifacts = $false
Write-Warning "Artifact $_ does not exist."
}
}
if (!$pushedAllArtifacts) {
throw "Some artifacts did not exist!"
}
2017-01-16 22:31:14 +01:00
}
}
# Bootstrap script for Linux and macOS
function Invoke-BootstrapStage
{
$createPackages = Test-DailyBuild
Write-Log -Message "Executing ci.psm1 Bootstrap Stage"
# Make sure we have all the tags
Sync-PSTags -AddRemoteIfMissing
Start-PSBootstrap -Package:$createPackages
}
# Run pester tests for Linux and macOS
function Invoke-LinuxTestsCore
{
[CmdletBinding()]
param(
[ValidateSet('UnelevatedPesterTests', 'ElevatedPesterTests', 'All')]
[string] $Purpose = 'All',
[string[]] $ExcludeTag = @('Slow', 'Feature', 'Scenario'),
[string] $TagSet = 'CI'
)
$output = Split-Path -Parent (Get-PSOutput -Options (Get-PSOptions))
2020-01-13 20:24:10 +01:00
$testResultsNoSudo = "$PWD/TestResultsNoSudo.xml"
$testResultsSudo = "$PWD/TestResultsSudo.xml"
$testExcludeTag = $ExcludeTag + 'RequireSudoOnUnix'
$pesterPassThruNoSudoObject = $null
$pesterPassThruSudoObject = $null
$noSudoResultsWithExpFeatures = $null
$sudoResultsWithExpFeatures = $null
$noSudoPesterParam = @{
'BinDir' = $output
'PassThru' = $true
'Terse' = $true
'Tag' = @()
'ExcludeTag' = $testExcludeTag
'OutputFile' = $testResultsNoSudo
}
# Get the experimental feature names and the tests associated with them
$ExperimentalFeatureTests = Get-ExperimentalFeatureTests
# Running tests which do not require sudo.
if($Purpose -eq 'UnelevatedPesterTests' -or $Purpose -eq 'All')
{
$pesterPassThruNoSudoObject = Start-PSPester @noSudoPesterParam -Title "Pester No Sudo - $TagSet"
# Running tests that do not require sudo, with specified experimental features enabled
$noSudoResultsWithExpFeatures = @()
foreach ($entry in $ExperimentalFeatureTests.GetEnumerator()) {
$featureName = $entry.Key
$testFiles = $entry.Value
2020-01-13 20:24:10 +01:00
$expFeatureTestResultFile = "$PWD\TestResultsNoSudo.$featureName.xml"
$noSudoPesterParam['OutputFile'] = $expFeatureTestResultFile
$noSudoPesterParam['ExperimentalFeatureName'] = $featureName
if ($testFiles.Count -eq 0) {
# If an empty array is specified for the feature name, we run all tests with the feature enabled.
# This allows us to prevent regressions to a critical engine experimental feature.
$noSudoPesterParam.Remove('Path')
}
else
{
# If a non-empty string or array is specified for the feature name, we only run those test files.
$noSudoPesterParam['Path'] = $testFiles
}
$passThruResult = Start-PSPester @noSudoPesterParam -Title "Pester Experimental No Sudo - $featureName - $TagSet"
$noSudoResultsWithExpFeatures += $passThruResult
}
}
# Running tests, which require sudo.
if($Purpose -eq 'ElevatedPesterTests' -or $Purpose -eq 'All')
{
$sudoPesterParam = $noSudoPesterParam.Clone()
$sudoPesterParam.Remove('Path')
$sudoPesterParam['Tag'] = @('RequireSudoOnUnix')
$sudoPesterParam['ExcludeTag'] = $ExcludeTag
$sudoPesterParam['Sudo'] = $true
$sudoPesterParam['OutputFile'] = $testResultsSudo
$pesterPassThruSudoObject = Start-PSPester @sudoPesterParam -Title "Pester Sudo - $TagSet"
# Running tests that require sudo, with specified experimental features enabled
$sudoResultsWithExpFeatures = @()
foreach ($entry in $ExperimentalFeatureTests.GetEnumerator()) {
$featureName = $entry.Key
$testFiles = $entry.Value
2020-01-13 20:24:10 +01:00
$expFeatureTestResultFile = "$PWD\TestResultsSudo.$featureName.xml"
$sudoPesterParam['OutputFile'] = $expFeatureTestResultFile
$sudoPesterParam['ExperimentalFeatureName'] = $featureName
if ($testFiles.Count -eq 0)
{
# If an empty array is specified for the feature name, we run all tests with the feature enabled.
# This allows us to prevent regressions to a critical engine experimental feature.
$sudoPesterParam.Remove('Path')
}
else
{
# If a non-empty string or array is specified for the feature name, we only run those test files.
$sudoPesterParam['Path'] = $testFiles
}
$passThruResult = Start-PSPester @sudoPesterParam -Title "Pester Experimental Sudo - $featureName - $TagSet"
$sudoResultsWithExpFeatures += $passThruResult
}
}
# Determine whether the build passed
try {
$allTestResultsWithNoExpFeature = @($pesterPassThruNoSudoObject, $pesterPassThruSudoObject)
$allTestResultsWithExpFeatures = @($noSudoResultsWithExpFeatures, $sudoResultsWithExpFeatures)
# This throws if there was an error:
$allTestResultsWithNoExpFeature | Where-Object {$null -ne $_} | ForEach-Object { Test-PSPesterResults -ResultObject $_ }
$allTestResultsWithExpFeatures | Where-Object {$null -ne $_} | ForEach-Object { Test-PSPesterResults -ResultObject $_ -CanHaveNoResult }
$result = "PASS"
} catch {
# The build failed, set the result:
$resultError = $_
$result = "FAIL"
}
# If the tests did not pass, throw the reason why
if ( $result -eq "FAIL" )
{
Write-Warning "Tests failed. See the issue below."
Throw $resultError
}
else
{
Write-Verbose "Tests did not fail! Nice job!"
}
}
function New-LinuxPackage
{
$isFullBuild = Test-DailyBuild
$releaseTag = Get-ReleaseTag
$packageParams = @{}
$packageParams += @{ReleaseTag=$releaseTag}
# Only build packages for PowerShell/PowerShell repository
# branches, not pull requests
$packages = @(Start-PSPackage @packageParams -SkipReleaseChecks -Type deb, rpm, tar)
foreach($package in $packages)
{
if (Test-Path $package)
{
Write-Log "Package found: $package"
}
else
{
Write-Error -Message "Package NOT found: $package"
}
if ($package -isnot [System.IO.FileInfo])
{
$packageObj = Get-Item $package
Write-Error -Message "The PACKAGE is not a FileInfo object"
}
else
{
$packageObj = $package
}
Write-Log -message "Artifacts directory: ${env:BUILD_ARTIFACTSTAGINGDIRECTORY}"
Copy-Item $packageObj.FullName -Destination "${env:BUILD_ARTIFACTSTAGINGDIRECTORY}" -Force
}
if ($IsLinux)
{
# Create and package Raspbian .tgz
Start-PSBuild -PSModuleRestore -Clean -Runtime linux-arm -Configuration 'Release'
$armPackage = Start-PSPackage @packageParams -Type tar-arm -SkipReleaseChecks
Copy-Item $armPackage -Destination "${env:BUILD_ARTIFACTSTAGINGDIRECTORY}" -Force
}
}