mirror of
https://github.com/PowerShell/PowerShell.git
synced 2024-11-23 09:43:57 +08:00
Refactor macOS CI so that tests run in parallel (#9056)
Refactor macOS CI so that tests run in parallel - Also: - Fix bootstrap issue where curl was failing for a month (so obviously not needed) - Change Windows test stages to use PowerShell Core (where we can) to avoid compat issues ## PR Context This allows running all tests in about the same about of clock time.
This commit is contained in:
parent
0ebbdc1cc4
commit
058a19028d
@ -81,7 +81,7 @@ jobs:
|
||||
|
||||
- powershell: |
|
||||
Import-Module ./tools/ci.psm1
|
||||
Invoke-Bootstrap-Stage
|
||||
Invoke-BootstrapStage
|
||||
displayName: Bootstrap
|
||||
condition: succeeded()
|
||||
|
||||
|
@ -35,43 +35,64 @@ resources:
|
||||
- repo: self
|
||||
clean: true
|
||||
jobs:
|
||||
- job: macOS_CI
|
||||
- template: templates/ci-build.yml
|
||||
parameters:
|
||||
pool: Hosted macOS
|
||||
jobName: mac_build
|
||||
displayName: macOS Build
|
||||
|
||||
- template: templates/nix-test.yml
|
||||
parameters:
|
||||
purpose: UnelevatedPesterTests
|
||||
tagSet: CI
|
||||
parentJobs:
|
||||
- mac_build
|
||||
|
||||
- template: templates/nix-test.yml
|
||||
parameters:
|
||||
purpose: ElevatedPesterTests
|
||||
tagSet: CI
|
||||
parentJobs:
|
||||
- mac_build
|
||||
|
||||
- template: templates/nix-test.yml
|
||||
parameters:
|
||||
purpose: UnelevatedPesterTests
|
||||
tagSet: Others
|
||||
parentJobs:
|
||||
- mac_build
|
||||
|
||||
- template: templates/nix-test.yml
|
||||
parameters:
|
||||
purpose: ElevatedPesterTests
|
||||
tagSet: Others
|
||||
parentJobs:
|
||||
- mac_build
|
||||
|
||||
- job: verify_xunit
|
||||
displayName: Verify xUnit Results
|
||||
pool:
|
||||
name: Hosted macOS
|
||||
|
||||
timeoutInMinutes: 120
|
||||
|
||||
name: 'Hosted macOS'
|
||||
dependsOn:
|
||||
- mac_build
|
||||
steps:
|
||||
- powershell: |
|
||||
Get-ChildItem -Path env:
|
||||
displayName: Capture environment
|
||||
condition: succeededOrFailed()
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download build artifacts'
|
||||
inputs:
|
||||
downloadType: specific
|
||||
itemPattern: |
|
||||
xunit/**/*
|
||||
downloadPath: '$(System.ArtifactsDirectory)'
|
||||
|
||||
- powershell: Write-Host "##vso[build.updatebuildnumber]$env:BUILD_SOURCEBRANCHNAME-$env:BUILD_SOURCEVERSION-$((get-date).ToString("yyyyMMddhhmmss"))"
|
||||
displayName: Set Build Name for Non-PR
|
||||
condition: ne(variables['Build.Reason'], 'PullRequest')
|
||||
|
||||
- template: ../tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml
|
||||
|
||||
- powershell: |
|
||||
Import-Module ./tools/ci.psm1
|
||||
Invoke-Bootstrap-Stage
|
||||
displayName: Bootstrap
|
||||
condition: succeeded()
|
||||
|
||||
- powershell: |
|
||||
Import-Module ./tools/ci.psm1
|
||||
$env:NugetKey = '$(NUGET_KEY)'
|
||||
Invoke-LinuxTests
|
||||
displayName: Build and Test
|
||||
condition: succeeded()
|
||||
|
||||
# Uploads any packages as an artifact
|
||||
- powershell: |
|
||||
Get-ChildItem -Path ${env:BUILD_ARTIFACTSTAGINGDIRECTORY} -Include *.nupkg, *.pkg, *.tar.gz, TestPackage.zip -Recurse | Select-Object -ExpandProperty FullName | ForEach-Object {
|
||||
Write-Host "##vso[artifact.upload containerfolder=artifacts;artifactname=artifacts]$_"
|
||||
}
|
||||
displayName: Publish Artifacts
|
||||
condition: succeededOrFailed()
|
||||
- pwsh: |
|
||||
Get-ChildItem "$(System.ArtifactsDirectory)\*" -Recurse
|
||||
displayName: 'Capture artifacts directory'
|
||||
continueOnError: true
|
||||
|
||||
- pwsh: |
|
||||
Import-Module .\tools\ci.psm1
|
||||
$xUnitTestResultsFile = "$(System.ArtifactsDirectory)\xunit\xUnitTestResults.xml"
|
||||
|
||||
Test-XUnitTestResults -TestResultsFile $xUnitTestResultsFile
|
||||
displayName: Test
|
||||
condition: succeeded()
|
||||
|
@ -1,13 +1,14 @@
|
||||
parameters:
|
||||
pool: 'Hosted VS2017'
|
||||
jobName: 'win_build'
|
||||
displayName: Windows Build
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.jobName }}
|
||||
pool:
|
||||
name: ${{ parameters.pool }}
|
||||
|
||||
displayName: Windows Build
|
||||
displayName: ${{ parameters.displayName }}
|
||||
|
||||
steps:
|
||||
- powershell: |
|
||||
@ -24,7 +25,7 @@ jobs:
|
||||
- powershell: |
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
|
||||
Import-Module .\tools\ci.psm1
|
||||
Invoke-CIInstall
|
||||
Invoke-CIInstall -SkipUser
|
||||
displayName: Bootstrap
|
||||
condition: succeededOrFailed()
|
||||
|
72
.vsts-ci/templates/nix-test.yml
Normal file
72
.vsts-ci/templates/nix-test.yml
Normal file
@ -0,0 +1,72 @@
|
||||
parameters:
|
||||
pool: 'Hosted macOS'
|
||||
parentJobs: []
|
||||
purpose: ''
|
||||
tagSet: 'CI'
|
||||
name: 'mac'
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}_test_${{ parameters.purpose }}_${{ parameters.tagSet }}
|
||||
dependsOn:
|
||||
${{ parameters.parentJobs }}
|
||||
pool:
|
||||
name: ${{ parameters.pool }}
|
||||
|
||||
displayName: ${{ parameters.name }} Test - ${{ parameters.purpose }} - ${{ parameters.tagSet }}
|
||||
|
||||
steps:
|
||||
- pwsh: |
|
||||
Get-ChildItem -Path env:
|
||||
displayName: Capture environment
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download build artifacts'
|
||||
inputs:
|
||||
downloadType: specific
|
||||
itemPattern: |
|
||||
build/**/*
|
||||
downloadPath: '$(System.ArtifactsDirectory)'
|
||||
|
||||
- pwsh: |
|
||||
Get-ChildItem "$(System.ArtifactsDirectory)\*" -Recurse
|
||||
displayName: 'Capture artifacts directory'
|
||||
continueOnError: true
|
||||
|
||||
- pwsh: |
|
||||
Import-Module .\tools\ci.psm1
|
||||
Invoke-CIInstall -SkipUser
|
||||
displayName: Bootstrap
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- task: ExtractFiles@1
|
||||
displayName: 'Extract build zip'
|
||||
inputs:
|
||||
archiveFilePatterns: '$(System.ArtifactsDirectory)/build/build.zip'
|
||||
destinationFolder: '$(System.ArtifactsDirectory)/bins'
|
||||
|
||||
- bash: |
|
||||
find "$(System.ArtifactsDirectory)/bins" -type d -exec chmod +rwx {} \;
|
||||
find "$(System.ArtifactsDirectory)/bins" -type f -exec chmod +rw {} \;
|
||||
displayName: 'Fix permissions'
|
||||
continueOnError: true
|
||||
|
||||
- pwsh: |
|
||||
Get-ChildItem "$(System.ArtifactsDirectory)\bins\*" -Recurse -ErrorAction SilentlyContinue
|
||||
displayName: 'Capture extracted build zip'
|
||||
continueOnError: true
|
||||
|
||||
- pwsh: |
|
||||
Import-Module .\tools\ci.psm1
|
||||
Restore-PSOptions -PSOptionsPath '$(System.ArtifactsDirectory)\build\psoptions.json'
|
||||
$options = (Get-PSOptions)
|
||||
$rootPath = '$(System.ArtifactsDirectory)\bins'
|
||||
$originalRootPath = Split-Path -path $options.Output
|
||||
$path = Join-Path -path $rootPath -ChildPath (split-path -leaf -path $originalRootPath)
|
||||
$pwshPath = Join-Path -path $path -ChildPath 'pwsh'
|
||||
chmod a+x $pwshPath
|
||||
$options.Output = $pwshPath
|
||||
Set-PSOptions $options
|
||||
Invoke-CITest -Purpose '${{ parameters.purpose }}' -TagSet '${{ parameters.tagSet }}'
|
||||
displayName: Test
|
||||
condition: succeeded()
|
@ -14,7 +14,7 @@ jobs:
|
||||
displayName: Windows Test - ${{ parameters.purpose }} - ${{ parameters.tagSet }}
|
||||
|
||||
steps:
|
||||
- powershell: |
|
||||
- pwsh: |
|
||||
Get-ChildItem -Path env:
|
||||
displayName: Capture environment
|
||||
condition: succeededOrFailed()
|
||||
@ -27,19 +27,19 @@ jobs:
|
||||
build/**/*
|
||||
downloadPath: '$(System.ArtifactsDirectory)'
|
||||
|
||||
- powershell: |
|
||||
dir "$(System.ArtifactsDirectory)\*" -Recurse
|
||||
- pwsh: |
|
||||
Get-ChildItem "$(System.ArtifactsDirectory)\*" -Recurse
|
||||
displayName: 'Capture artifacts directory'
|
||||
continueOnError: true
|
||||
|
||||
# must be run frow Windows PowerShell
|
||||
- powershell: |
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
|
||||
Import-Module .\tools\ci.psm1
|
||||
Invoke-CIInstall
|
||||
displayName: Bootstrap
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- powershell: |
|
||||
- pwsh: |
|
||||
Import-Module .\tools\ci.psm1
|
||||
Restore-PSOptions -PSOptionsPath '$(System.ArtifactsDirectory)\build\psoptions.json'
|
||||
$options = (Get-PSOptions)
|
||||
|
@ -36,7 +36,7 @@ resources:
|
||||
clean: true
|
||||
|
||||
jobs:
|
||||
- template: templates/windows-build.yml
|
||||
- template: templates/ci-build.yml
|
||||
|
||||
- template: templates/windows-test.yml
|
||||
parameters:
|
||||
|
@ -1636,9 +1636,6 @@ function Start-PSBootstrap {
|
||||
# Install dependencies
|
||||
# ignore exitcode, because they may be already installed
|
||||
Start-NativeExecution { brew install $Deps } -IgnoreExitcode
|
||||
|
||||
# Install patched version of curl
|
||||
Start-NativeExecution { brew install curl --with-openssl --with-gssapi } -IgnoreExitcode
|
||||
} elseif ($Environment.IsAlpine) {
|
||||
$Deps += 'libunwind', 'libcurl', 'bash', 'cmake', 'clang', 'build-base', 'git', 'curl'
|
||||
|
||||
|
77
tools/WindowsCI.psm1
Normal file
77
tools/WindowsCI.psm1
Normal file
@ -0,0 +1,77 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
if($PSVersionTable.PSEdition -ne 'Desktop')
|
||||
{
|
||||
throw 'Must be run from Windows PowerShell'
|
||||
}
|
||||
|
||||
function New-LocalUser
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Creates a local user with the specified username and password
|
||||
.DESCRIPTION
|
||||
.EXAMPLE
|
||||
.PARAMETER
|
||||
username Username of the user which will be created
|
||||
.PARAMETER
|
||||
password Password of the user which will be created
|
||||
.OUTPUTS
|
||||
.NOTES
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $username,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $password
|
||||
|
||||
)
|
||||
$LocalComputer = [ADSI] "WinNT://$env:computername";
|
||||
$user = $LocalComputer.Create('user', $username);
|
||||
$user.SetPassword($password) | out-null;
|
||||
$user.SetInfo() | out-null;
|
||||
}
|
||||
|
||||
<#
|
||||
Converts SID to NT Account Name
|
||||
#>
|
||||
function ConvertTo-NtAccount
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $sid
|
||||
)
|
||||
(new-object System.Security.Principal.SecurityIdentifier($sid)).translate([System.Security.Principal.NTAccount]).Value
|
||||
}
|
||||
|
||||
<#
|
||||
Add a user to a local security group
|
||||
Requires Windows PowerShell
|
||||
#>
|
||||
function Add-UserToGroup
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $username,
|
||||
|
||||
[Parameter(Mandatory=$true, ParameterSetName = "SID")]
|
||||
[string] $groupSid,
|
||||
|
||||
[Parameter(Mandatory=$true, ParameterSetName = "Name")]
|
||||
[string] $group
|
||||
)
|
||||
|
||||
$userAD = [ADSI] "WinNT://$env:computername/${username},user"
|
||||
|
||||
if($PsCmdlet.ParameterSetName -eq "SID")
|
||||
{
|
||||
$ntAccount=ConvertTo-NtAccount $groupSid
|
||||
$group =$ntAccount.Split("\\")[1]
|
||||
}
|
||||
|
||||
$groupAD = [ADSI] "WinNT://$env:computername/${group},group"
|
||||
|
||||
$groupAD.Add($userAD.AdsPath);
|
||||
}
|
414
tools/ci.psm1
414
tools/ci.psm1
@ -15,75 +15,12 @@ if(Test-Path $dotNetPath)
|
||||
|
||||
# import build into the global scope so it can be used by packaging
|
||||
Import-Module (Join-Path $repoRoot 'build.psm1') -Scope Global
|
||||
Import-Module (Join-Path $repoRoot 'tools\packaging')
|
||||
Import-Module (Join-Path $repoRoot 'tools\packaging') -scope Global
|
||||
|
||||
function New-LocalUser
|
||||
# import the windows specific functcion only in Windows PowerShell or on Windows
|
||||
if($PSVersionTable.PSEdition -eq 'Desktop' -or $isWindows)
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Creates a local user with the specified username and password
|
||||
.DESCRIPTION
|
||||
.EXAMPLE
|
||||
.PARAMETER
|
||||
username Username of the user which will be created
|
||||
.PARAMETER
|
||||
password Password of the user which will be created
|
||||
.OUTPUTS
|
||||
.NOTES
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $username,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $password
|
||||
|
||||
)
|
||||
$LocalComputer = [ADSI] "WinNT://$env:computername";
|
||||
$user = $LocalComputer.Create('user', $username);
|
||||
$user.SetPassword($password) | out-null;
|
||||
$user.SetInfo() | out-null;
|
||||
}
|
||||
|
||||
<#
|
||||
Converts SID to NT Account Name
|
||||
#>
|
||||
function ConvertTo-NtAccount
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $sid
|
||||
)
|
||||
(new-object System.Security.Principal.SecurityIdentifier($sid)).translate([System.Security.Principal.NTAccount]).Value
|
||||
}
|
||||
|
||||
<#
|
||||
Add a user to a local security group
|
||||
#>
|
||||
function Add-UserToGroup
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $username,
|
||||
|
||||
[Parameter(Mandatory=$true, ParameterSetName = "SID")]
|
||||
[string] $groupSid,
|
||||
|
||||
[Parameter(Mandatory=$true, ParameterSetName = "Name")]
|
||||
[string] $group
|
||||
)
|
||||
|
||||
$userAD = [ADSI] "WinNT://$env:computername/${username},user"
|
||||
|
||||
if($PsCmdlet.ParameterSetName -eq "SID")
|
||||
{
|
||||
$ntAccount=ConvertTo-NtAccount $groupSid
|
||||
$group =$ntAccount.Split("\\")[1]
|
||||
}
|
||||
|
||||
$groupAD = [ADSI] "WinNT://$env:computername/${group},group"
|
||||
|
||||
$groupAD.Add($userAD.AdsPath);
|
||||
Import-Module (Join-Path $PSScriptRoot 'WindowsCI.psm1') -scope Global
|
||||
}
|
||||
|
||||
# tests if we should run a daily build
|
||||
@ -209,6 +146,10 @@ function Invoke-CIBuild
|
||||
# Implements the CI 'install' step
|
||||
function Invoke-CIInstall
|
||||
{
|
||||
param(
|
||||
[switch]
|
||||
$SkipUser
|
||||
)
|
||||
# Make sure we have all the tags
|
||||
Sync-PSTags -AddRemoteIfMissing
|
||||
$releaseTag = Get-ReleaseTag
|
||||
@ -221,7 +162,7 @@ function Invoke-CIInstall
|
||||
}
|
||||
}
|
||||
|
||||
if ($env:TF_BUILD)
|
||||
if ($env:TF_BUILD -and !$SkipUser.IsPresent)
|
||||
{
|
||||
# Generate new credential for CI (only) remoting tests.
|
||||
Write-Log -Message "Creating account for remoting tests in CI."
|
||||
@ -269,12 +210,18 @@ function Invoke-CIxUnit
|
||||
$SkipFailing
|
||||
)
|
||||
$env:CoreOutput = Split-Path -Parent (Get-PSOutput -Options (Get-PSOptions))
|
||||
if(!(Test-Path "$env:CoreOutput\pwsh.exe"))
|
||||
$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 = "$pwd\xUnitTestResults.xml"
|
||||
$xUnitTestResultsFile = Join-Path -Path $pwd -childpath "xUnitTestResults.xml"
|
||||
|
||||
Start-PSxUnit -xUnitTestResultsFile $xUnitTestResultsFile
|
||||
Push-Artifact -Path $xUnitTestResultsFile -name xunit
|
||||
@ -296,16 +243,6 @@ function Invoke-CITest
|
||||
[ValidateSet('CI', 'Others')]
|
||||
[string] $TagSet
|
||||
)
|
||||
# CoreCLR
|
||||
|
||||
$env:CoreOutput = Split-Path -Parent (Get-PSOutput -Options (Get-PSOptions))
|
||||
Write-Host -Foreground Green 'Run CoreCLR tests'
|
||||
$testResultsNonAdminFile = "$pwd\TestsResultsNonAdmin-$TagSet.xml"
|
||||
$testResultsAdminFile = "$pwd\TestsResultsAdmin-$TagSet.xml"
|
||||
if(!(Test-Path "$env:CoreOutput\pwsh.exe"))
|
||||
{
|
||||
throw "CoreCLR pwsh.exe was not built"
|
||||
}
|
||||
|
||||
# Pester doesn't allow Invoke-Pester -TagAll@('CI', 'RequireAdminOnWindows') currently
|
||||
# https://github.com/pester/Pester/issues/608
|
||||
@ -324,6 +261,22 @@ function Invoke-CITest
|
||||
}
|
||||
}
|
||||
|
||||
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'
|
||||
$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
|
||||
|
||||
@ -336,6 +289,7 @@ function Invoke-CITest
|
||||
Tag = @()
|
||||
ExcludeTag = $ExcludeTag + 'RequireAdminOnWindows'
|
||||
}
|
||||
|
||||
Start-PSPester @arguments -Title "Pester Unelevated - $TagSet"
|
||||
# Fail the build, if tests failed
|
||||
Test-PSPesterResults -TestResultsFile $testResultsNonAdminFile
|
||||
@ -357,6 +311,7 @@ function Invoke-CITest
|
||||
# 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
|
||||
@ -372,6 +327,7 @@ function Invoke-CITest
|
||||
Tag = @('RequireAdminOnWindows')
|
||||
ExcludeTag = $ExcludeTag
|
||||
}
|
||||
|
||||
Start-PSPester @arguments -Title "Pester Elevated - $TagSet"
|
||||
|
||||
# Fail the build, if tests failed
|
||||
@ -499,6 +455,12 @@ function Invoke-CIFinish
|
||||
param(
|
||||
[string] $NuGetKey
|
||||
)
|
||||
|
||||
if($IsLinux -or $IsMacOS)
|
||||
{
|
||||
return New-LinuxPackage -NugetKey $NugetKey
|
||||
}
|
||||
|
||||
try {
|
||||
$releaseTag = Get-ReleaseTag
|
||||
|
||||
@ -613,7 +575,7 @@ function Invoke-CIFinish
|
||||
}
|
||||
|
||||
# Bootstrap script for Linux and macOS
|
||||
function Invoke-Bootstrap-Stage
|
||||
function Invoke-BootstrapStage
|
||||
{
|
||||
$createPackages = Test-DailyBuild
|
||||
Write-Log -Message "Executing ci.psm1 Bootstrap Stage"
|
||||
@ -622,42 +584,33 @@ function Invoke-Bootstrap-Stage
|
||||
Start-PSBootstrap -Package:$createPackages
|
||||
}
|
||||
|
||||
# Build and test script for Linux and macOS:
|
||||
function Invoke-LinuxTests
|
||||
# Run pester tests for Linux and macOS
|
||||
function Invoke-LinuxTestsCore
|
||||
{
|
||||
$releaseTag = Get-ReleaseTag
|
||||
Write-Log -Message "Executing ci.psm1 build and test on a Linux based operating system."
|
||||
$originalProgressPreference = $ProgressPreference
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
try {
|
||||
# We use CrossGen build to run tests only if it's the daily build.
|
||||
Start-PSBuild -CrossGen -PSModuleRestore -CI -ReleaseTag $releaseTag -Configuration 'Release'
|
||||
}
|
||||
finally
|
||||
{
|
||||
$ProgressPreference = $originalProgressPreference
|
||||
}
|
||||
[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))
|
||||
$testResultsNoSudo = "$pwd/TestResultsNoSudo.xml"
|
||||
$testResultsSudo = "$pwd/TestResultsSudo.xml"
|
||||
$excludeTag = @('RequireSudoOnUnix')
|
||||
$testExcludeTag = $ExcludeTag + 'RequireSudoOnUnix'
|
||||
|
||||
$noSudoPesterParam = @{
|
||||
'BinDir' = $output
|
||||
'PassThru' = $true
|
||||
'Terse' = $true
|
||||
'Tag' = @()
|
||||
'ExcludeTag' = $excludeTag
|
||||
'ExcludeTag' = $testExcludeTag
|
||||
'OutputFile' = $testResultsNoSudo
|
||||
}
|
||||
# create packages if it is a full build
|
||||
$isFullBuild = Test-DailyBuild
|
||||
$createPackages = $isFullBuild
|
||||
if ($isFullBuild) {
|
||||
$noSudoPesterParam['Tag'] = @('CI','Feature','Scenario')
|
||||
} else {
|
||||
$noSudoPesterParam['Tag'] = @('CI')
|
||||
if (!$isFullBuild) {
|
||||
$noSudoPesterParam['ThrowOnFailure'] = $true
|
||||
}
|
||||
if ($hasRunFailingTestTag) {
|
||||
@ -668,60 +621,68 @@ function Invoke-LinuxTests
|
||||
$ExperimentalFeatureTests = Get-ExperimentalFeatureTests
|
||||
|
||||
# Running tests which do not require sudo.
|
||||
$pesterPassThruNoSudoObject = Start-PSPester @noSudoPesterParam -Title 'Pester No 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
|
||||
# Running tests that do not require sudo, with specified experimental features enabled
|
||||
$noSudoResultsWithExpFeatures = @()
|
||||
foreach ($entry in $ExperimentalFeatureTests.GetEnumerator()) {
|
||||
$featureName = $entry.Key
|
||||
$testFiles = $entry.Value
|
||||
|
||||
$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')
|
||||
$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
|
||||
}
|
||||
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"
|
||||
$noSudoResultsWithExpFeatures += $passThruResult
|
||||
}
|
||||
# Running tests, which require sudo.
|
||||
$sudoPesterParam = $noSudoPesterParam.Clone()
|
||||
$sudoPesterParam.Remove('Path')
|
||||
$sudoPesterParam['Tag'] = @('RequireSudoOnUnix')
|
||||
$sudoPesterParam['ExcludeTag'] = @()
|
||||
$sudoPesterParam['Sudo'] = $true
|
||||
$sudoPesterParam['OutputFile'] = $testResultsSudo
|
||||
$pesterPassThruSudoObject = Start-PSPester @sudoPesterParam -Title 'Pester Sudo'
|
||||
# Running tests that require sudo, with specified experimental features enabled
|
||||
$sudoResultsWithExpFeatures = @()
|
||||
foreach ($entry in $ExperimentalFeatureTests.GetEnumerator()) {
|
||||
$featureName = $entry.Key
|
||||
$testFiles = $entry.Value
|
||||
|
||||
$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')
|
||||
# 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
|
||||
|
||||
$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
|
||||
}
|
||||
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"
|
||||
$sudoResultsWithExpFeatures += $passThruResult
|
||||
}
|
||||
|
||||
# Determine whether the build passed
|
||||
@ -737,6 +698,33 @@ function Invoke-LinuxTests
|
||||
$resultError = $_
|
||||
$result = "FAIL"
|
||||
}
|
||||
}
|
||||
|
||||
# Build and test script for Linux and macOS:
|
||||
function Invoke-LinuxTests
|
||||
{
|
||||
param(
|
||||
[switch]
|
||||
$SkipBuild
|
||||
)
|
||||
|
||||
if(!$SkipBuild.IsPresent)
|
||||
{
|
||||
$releaseTag = Get-ReleaseTag
|
||||
Write-Log -Message "Executing ci.psm1 build and test on a Linux based operating system."
|
||||
$originalProgressPreference = $ProgressPreference
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
try {
|
||||
# We use CrossGen build to run tests only if it's the daily build.
|
||||
Start-PSBuild -CrossGen -PSModuleRestore -CI -ReleaseTag $releaseTag -Configuration 'Release'
|
||||
}
|
||||
finally
|
||||
{
|
||||
$ProgressPreference = $originalProgressPreference
|
||||
}
|
||||
}
|
||||
|
||||
Invoke-LinuxTestsCore
|
||||
|
||||
try {
|
||||
$xUnitTestResultsFile = "$pwd/xUnitTestResults.xml"
|
||||
@ -751,64 +739,11 @@ function Invoke-LinuxTests
|
||||
}
|
||||
}
|
||||
|
||||
$createPackages = $isFullBuild
|
||||
|
||||
if ($createPackages)
|
||||
{
|
||||
$packageParams = @{}
|
||||
$packageParams += @{ReleaseTag=$releaseTag}
|
||||
|
||||
# Only build packages for PowerShell/PowerShell repository
|
||||
# branches, not pull requests
|
||||
$packages = @(Start-PSPackage @packageParams -SkipReleaseChecks)
|
||||
foreach($package in $packages)
|
||||
{
|
||||
if (Test-Path $package)
|
||||
{
|
||||
Write-Log "Package found: $package"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Error -Message "Package NOT found: $package"
|
||||
}
|
||||
|
||||
# Publish the packages to the nuget feed if:
|
||||
# 1 - It's a Daily build (already checked, for not a PR)
|
||||
# 2 - We have the info to publish (NUGET_KEY and NUGET_URL)
|
||||
# 3 - it's a nupkg file
|
||||
if($isFullBuild -and $NugetKey -and $env:NUGET_URL -and [system.io.path]::GetExtension($package) -ieq '.nupkg')
|
||||
{
|
||||
Write-Log "pushing $package to $env:NUGET_URL"
|
||||
Start-NativeExecution -sb {dotnet nuget push $package --api-key $NugetKey --source "$env:NUGET_URL/api/v2/package"} -IgnoreExitcode
|
||||
}
|
||||
|
||||
if($isFullBuild)
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
if ($isFullBuild)
|
||||
{
|
||||
New-TestPackage -Destination "${env:SYSTEM_ARTIFACTSDIRECTORY}"
|
||||
}
|
||||
New-LinuxPackage -NugetKey $env:NugetKey
|
||||
}
|
||||
|
||||
# If the tests did not pass, throw the reason why
|
||||
@ -822,3 +757,70 @@ function Invoke-LinuxTests
|
||||
Write-Verbose "Tests did not fail! Nice job!"
|
||||
}
|
||||
}
|
||||
|
||||
function New-LinuxPackage
|
||||
{
|
||||
param(
|
||||
[string]
|
||||
$NugetKey
|
||||
)
|
||||
|
||||
$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)
|
||||
foreach($package in $packages)
|
||||
{
|
||||
if (Test-Path $package)
|
||||
{
|
||||
Write-Log "Package found: $package"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Error -Message "Package NOT found: $package"
|
||||
}
|
||||
|
||||
# Publish the packages to the nuget feed if:
|
||||
# 1 - It's a Daily build (already checked, for not a PR)
|
||||
# 2 - We have the info to publish (NUGET_KEY and NUGET_URL)
|
||||
# 3 - it's a nupkg file
|
||||
if($isFullBuild -and $NugetKey -and $env:NUGET_URL -and [system.io.path]::GetExtension($package) -ieq '.nupkg')
|
||||
{
|
||||
Write-Log "pushing $package to $env:NUGET_URL"
|
||||
Start-NativeExecution -sb {dotnet nuget push $package --api-key $NugetKey --source "$env:NUGET_URL/api/v2/package"} -IgnoreExitcode
|
||||
}
|
||||
|
||||
if($isFullBuild)
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
if ($isFullBuild)
|
||||
{
|
||||
New-TestPackage -Destination "${env:SYSTEM_ARTIFACTSDIRECTORY}"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user