diff --git a/.vsts-ci/linux.yml b/.vsts-ci/linux.yml
index 66e2e2c7c57..3e6288406a2 100644
--- a/.vsts-ci/linux.yml
+++ b/.vsts-ci/linux.yml
@@ -80,24 +80,16 @@ jobs:
- template: ../tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml
- powershell: |
- tools/travis.ps1 -Stage Bootstrap
+ Import-Module ./tools/ci.psm1
+ Invoke-Bootstrap-Stage
displayName: Bootstrap
condition: succeeded()
- powershell: |
- $ErrorActionPreference = 'continue'
- tools/travis.ps1 -NugetKey $(NUGET_KEY)
- displayName: Build and test
- condition: succeeded()
-
- - powershell: |
- tools/travis.ps1 -Stage Failure
- displayName: After Failure
- condition: failed()
-
- - powershell: |
- tools/travis.ps1 -Stage Success
- displayName: After Success
+ Import-Module ./tools/ci.psm1
+ $env:NugetKey = '$(NUGET_KEY)'
+ Invoke-LinuxTests
+ displayName: Build and Test
condition: succeeded()
# Uploads any packages as an artifact
diff --git a/.vsts-ci/mac.yml b/.vsts-ci/mac.yml
index 842464a98ff..ec73ac4ba3e 100644
--- a/.vsts-ci/mac.yml
+++ b/.vsts-ci/mac.yml
@@ -55,24 +55,16 @@ jobs:
- template: ../tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml
- powershell: |
- tools/travis.ps1 -Stage Bootstrap
+ Import-Module ./tools/ci.psm1
+ Invoke-Bootstrap-Stage
displayName: Bootstrap
condition: succeeded()
- powershell: |
- $ErrorActionPreference = 'continue'
- tools/travis.ps1 -NugetKey $(NUGET_KEY)
- displayName: Build and test
- condition: succeeded()
-
- - powershell: |
- tools/travis.ps1 -Stage Failure
- displayName: After Failure
- condition: failed()
-
- - powershell: |
- tools/travis.ps1 -Stage Success
- displayName: After Success
+ Import-Module ./tools/ci.psm1
+ $env:NugetKey = '$(NUGET_KEY)'
+ Invoke-LinuxTests
+ displayName: Build and Test
condition: succeeded()
# Uploads any packages as an artifact
diff --git a/tools/ci.psm1 b/tools/ci.psm1
index f268663f25a..12f070cb954 100644
--- a/tools/ci.psm1
+++ b/tools/ci.psm1
@@ -1,17 +1,19 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
-$ErrorActionPreference = 'Stop'
+
+$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 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')
@@ -37,7 +39,6 @@ function New-LocalUser
[string] $password
)
-
$LocalComputer = [ADSI] "WinNT://$env:computername";
$user = $LocalComputer.Create('user', $username);
$user.SetPassword($password) | out-null;
@@ -91,27 +92,25 @@ function Add-UserToGroup
Function Test-DailyBuild
{
$trueString = 'True'
- # PS_DAILY_BUILD says that we have previously determined that this is a daily build
- # APPVEYOR_SCHEDULED_BUILD is True means that we are in an AppVeyor Scheduled build
- # APPVEYOR_REPO_TAG_NAME means we are building a tag in AppVeyor
- # BUILD_REASON is Schedule means we are in a VSTS Scheduled build
if(($env:PS_DAILY_BUILD -eq $trueString) -or $env:BUILD_REASON -eq 'Schedule')
{
return $true
}
- # if [Feature] is in the commit message,
+ # if [feature] is in the commit message,
# Run Daily tests
$commitMessage = Get-CommitMessage
- Write-Verbose "commitMessage: $commitMessage" -verbose
+ Write-log -message "commitMessage: $commitMessage"
if($commitMessage -match '\[feature\]' -or $env:FORCE_FEATURE -eq 'True')
{
Set-BuildVariable -Name PS_DAILY_BUILD -Value $trueString
return $true
}
-
- return $false
+ else
+ {
+ return $false
+ }
}
# Returns the commit message for the current build
@@ -144,10 +143,10 @@ Function Set-BuildVariable
if($env:TF_BUILD)
{
- #In VSTS
+ # 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 AppVeyor
+ # Setting in the current session for the same behavior as the CI
Set-Item env:/$name -Value $Value
}
else
@@ -156,7 +155,7 @@ Function Set-BuildVariable
}
}
-# Emulates running all of AppVeyor but locally
+# Emulates running all of CI but locally
function Invoke-AppVeyorFull
{
param(
@@ -174,13 +173,14 @@ function Invoke-AppVeyorFull
Invoke-AppveyorFinish
}
-# Implements the AppVeyor 'build_script' step
+# Implements the CI 'build_script' step
function Invoke-AppVeyorBuild
{
$releaseTag = Get-ReleaseTag
# check to be sure our test tags are correct
$result = Get-PesterTag
- if ( $result.Result -ne "Pass" ) {
+ if ( $result.Result -ne "Pass" )
+ {
$result.Warnings
throw "Tags must be CI, Feature, Scenario, or Slow"
}
@@ -193,25 +193,25 @@ function Invoke-AppVeyorBuild
Start-PSBuild -CrossGen -PSModuleRestore -Configuration 'Release' -CI -ReleaseTag $releaseTag
}
-# Implements the AppVeyor 'install' step
+# Implements the CI 'install' step
function Invoke-AppVeyorInstall
{
# Make sure we have all the tags
Sync-PSTags -AddRemoteIfMissing
$releaseTag = Get-ReleaseTag
- if(Test-DailyBuild){
- if ($env:BUILD_REASON -eq 'Schedule') {
+ 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)
{
- #
- # Generate new credential for appveyor (only) remoting tests.
- #
- Write-Verbose "Creating account for remoting tests in AppVeyor."
+ # Generate new credential for CI (only) remoting tests.
+ Write-Log -Message "Creating account for remoting tests in CI."
# Password
$randomObj = [System.Random]::new()
@@ -225,18 +225,19 @@ function Invoke-AppVeyorInstall
# Provide credentials globally for remote tests.
$ss = ConvertTo-SecureString -String $password -AsPlainText -Force
- $appveyorRemoteCredential = [PSCredential]::new("$env:COMPUTERNAME\$userName", $ss)
- $appveyorRemoteCredential | Export-Clixml -Path "$env:TEMP\AppVeyorRemoteCred.xml" -Force
+ $ciRemoteCredential = [PSCredential]::new("$env:COMPUTERNAME\$userName", $ss)
+ $ciRemoteCredential | Export-Clixml -Path "$env:TEMP\AppVeyorRemoteCred.xml" -Force
# Check that LocalAccountTokenFilterPolicy policy is set, since it is needed for remoting
# using above local admin account.
- Write-Verbose "Checking for LocalAccountTokenFilterPolicy in AppVeyor."
+ 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)
}
- catch { }
+ # ignore if anything is caught:
+ catch {}
if (!$haveLocalAccountTokenFilterPolicy)
{
Write-Verbose "Setting the LocalAccountTokenFilterPolicy for remoting tests"
@@ -251,7 +252,7 @@ function Invoke-AppVeyorInstall
# A wrapper to ensure that we upload test results
# and that if we are not able to that it does not fail
# the CI build
-function Update-AppVeyorTestResults
+function Update-TestResults
{
param(
[string] $resultsFile
@@ -262,7 +263,7 @@ function Update-AppVeyorTestResults
}
}
-# Implement AppVeyor 'Test_script'
+# Implement CI 'Test_script'
function Invoke-AppVeyorTest
{
[CmdletBinding()]
@@ -270,7 +271,6 @@ function Invoke-AppVeyorTest
[ValidateSet('UnelevatedPesterTests', 'ElevatedPesterTests_xUnit_Packaging')]
[string] $Purpose
)
- #
# CoreCLR
$env:CoreOutput = Split-Path -Parent (Get-PSOutput -Options (Get-PSOptions))
@@ -286,11 +286,13 @@ function Invoke-AppVeyorTest
# 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
- if (Test-DailyBuild) {
+ if (Test-DailyBuild)
+ {
$ExcludeTag = @()
Write-Host -Foreground Green 'Running all CoreCLR tests..'
}
- else {
+ else
+ {
$ExcludeTag = @('Slow', 'Feature', 'Scenario')
Write-Host -Foreground Green 'Running "CI" CoreCLR tests..'
}
@@ -309,12 +311,13 @@ function Invoke-AppVeyorTest
}
Start-PSPester @arguments -Title 'Pester Unelevated'
Write-Host -Foreground Green 'Upload CoreCLR Non-Admin test results'
- Update-AppVeyorTestResults -resultsFile $testResultsNonAdminFile
+ Update-TestResults -resultsFile $testResultsNonAdminFile
# Fail the build, if tests failed
Test-PSPesterResults -TestResultsFile $testResultsNonAdminFile
# Run tests with specified experimental features enabled
- foreach ($entry in $ExperimentalFeatureTests.GetEnumerator()) {
+ foreach ($entry in $ExperimentalFeatureTests.GetEnumerator())
+ {
$featureName = $entry.Key
$testFiles = $entry.Value
@@ -332,7 +335,7 @@ function Invoke-AppVeyorTest
Start-PSPester @arguments -Title "Pester Experimental Unelevated - $featureName"
Write-Host -ForegroundColor Green "Upload CoreCLR Non-Admin test results for experimental feature '$featureName'"
- Update-AppVeyorTestResults -resultsFile $expFeatureTestResultFile
+ Update-TestResults -resultsFile $expFeatureTestResultFile
# Fail the build, if tests failed
Test-PSPesterResults -TestResultsFile $expFeatureTestResultFile
}
@@ -348,36 +351,40 @@ function Invoke-AppVeyorTest
}
Start-PSPester @arguments -Title 'Pester Elevated'
Write-Host -Foreground Green 'Upload CoreCLR Admin test results'
- Update-AppVeyorTestResults -resultsFile $testResultsAdminFile
+ Update-TestResults -resultsFile $testResultsAdminFile
Start-PSxUnit -ParallelTestResultsFile $ParallelXUnitTestResultsFile
Write-Host -ForegroundColor Green 'Uploading PSxUnit test results'
- Update-AppVeyorTestResults -resultsFile $ParallelXUnitTestResultsFile
+ Update-TestResults -resultsFile $ParallelXUnitTestResultsFile
# Fail the build, if tests failed
Test-PSPesterResults -TestResultsFile $testResultsAdminFile
Test-XUnitTestResults -TestResultsFile $ParallelXUnitTestResultsFile
# Run tests with specified experimental features enabled
- foreach ($entry in $ExperimentalFeatureTests.GetEnumerator()) {
+ foreach ($entry in $ExperimentalFeatureTests.GetEnumerator())
+ {
$featureName = $entry.Key
$testFiles = $entry.Value
$expFeatureTestResultFile = "$pwd\TestsResultsAdmin.$featureName.xml"
$arguments['OutputFile'] = $expFeatureTestResultFile
$arguments['ExperimentalFeatureName'] = $featureName
- if ($testFiles.Count -eq 0) {
+ 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 {
+ }
+ 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"
Write-Host -ForegroundColor Green "Upload CoreCLR Admin test results for experimental feature '$featureName'"
- Update-AppVeyorTestResults -resultsFile $expFeatureTestResultFile
+ Update-TestResults -resultsFile $expFeatureTestResultFile
# Fail the build, if tests failed
Test-PSPesterResults -TestResultsFile $expFeatureTestResultFile
}
@@ -386,7 +393,7 @@ function Invoke-AppVeyorTest
Set-BuildVariable -Name TestPassed -Value True
}
-#Implement AppVeyor 'after_test' phase
+# Implement CI 'after_test' phase
function Invoke-AppVeyorAfterTest
{
[CmdletBinding()]
@@ -395,7 +402,8 @@ function Invoke-AppVeyorAfterTest
if (Test-DailyBuild)
{
## Publish code coverage build, tests and OpenCover module to artifacts, so webhook has the information.
- ## Build webhook is called after 'after_test' phase, hence we need to do this here and not in AppveyorFinish.
+ Push-Artifact -Path $_ -Name 'CodeCoverage'
+ Push-Artifact $testPackageFullName -Name 'artifacts'
$codeCoverageOutput = Split-Path -Parent (Get-PSOutput -Options (New-PSOptions -Configuration CodeCoverage))
$codeCoverageArtifacts = Compress-CoverageArtifacts -CodeCoverageOutput $codeCoverageOutput
@@ -433,7 +441,7 @@ function Push-Artifact
}
if ($env:TF_BUILD) {
- # In VSTS
+ # In Azure DevOps
Write-Host "##vso[artifact.upload containerfolder=$artifactName;artifactname=$artifactName;]$Path"
}
}
@@ -444,7 +452,6 @@ function Compress-CoverageArtifacts
# Create archive for test content, OpenCover module and CodeCoverage build
$artifacts = New-Object System.Collections.ArrayList
-
$zipTestContentPath = Join-Path $pwd 'tests.zip'
Compress-TestContent -Destination $zipTestContentPath
$null = $artifacts.Add($zipTestContentPath)
@@ -467,30 +474,21 @@ function Get-ReleaseTag
{
$metaDataPath = Join-Path -Path $PSScriptRoot -ChildPath 'metadata.json'
$metaData = Get-Content $metaDataPath | ConvertFrom-Json
-
$releaseTag = $metadata.PreviewReleaseTag
- if($env:APPVEYOR_BUILD_NUMBER)
+ if($env:BUILD_BUILID)
{
- $releaseTag = $releaseTag.split('.')[0..2] -join '.'
- $releaseTag = $releaseTag + '.' + $env:APPVEYOR_BUILD_NUMBER
- }
- elseif($env:BUILD_BUILID)
- {
- #In VSTS
$releaseTag = $releaseTag.split('.')[0..2] -join '.'
$releaseTag = $releaseTag + '.' + $env:BUILD_BUILID
}
-
return $releaseTag
}
-# Implements AppVeyor 'on_finish' step
+# Implements CI 'on_finish' step
function Invoke-AppveyorFinish
{
param(
[string] $NuGetKey
)
-
try {
$releaseTag = Get-ReleaseTag
@@ -513,6 +511,15 @@ function Invoke-AppveyorFinish
$artifacts = New-Object System.Collections.ArrayList
foreach ($package in $packages) {
+ if (Test-Path $package)
+ {
+ Write-Log "Package found: $package"
+ }
+ else
+ {
+ Write-Warning -Message "Package NOT found: $package"
+ }
+
if($package -is [string])
{
$null = $artifacts.Add($package)
@@ -565,7 +572,7 @@ function Invoke-AppveyorFinish
$pushedAllArtifacts = $true
$artifacts | ForEach-Object {
- Write-Host "Pushing $_ as Appveyor artifact"
+ Write-Log -Message "Pushing $_ as CI artifact"
if(Test-Path $_)
{
Push-Artifact -Path $_ -Name 'artifacts'
@@ -587,9 +594,221 @@ function Invoke-AppveyorFinish
throw "Some artifacts did not exist!"
}
}
- catch {
+ catch
+ {
Write-Host -Foreground Red $_
Write-Host -Foreground Red $_.ScriptStackTrace
throw $_
}
}
+
+# Bootstrap script for Linux and macOS
+function Invoke-Bootstrap-Stage
+{
+ $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
+}
+
+# Build and test script for Linux and macOS:
+function Invoke-LinuxTests
+{
+ $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
+ }
+
+ $output = Split-Path -Parent (Get-PSOutput -Options (Get-PSOptions))
+ $testResultsNoSudo = "$pwd/TestResultsNoSudo.xml"
+ $testResultsSudo = "$pwd/TestResultsSudo.xml"
+ $excludeTag = @('RequireSudoOnUnix')
+
+ $noSudoPesterParam = @{
+ 'BinDir' = $output
+ 'PassThru' = $true
+ 'Terse' = $true
+ 'Tag' = @()
+ 'ExcludeTag' = $excludeTag
+ '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')
+ $noSudoPesterParam['ThrowOnFailure'] = $true
+ }
+ if ($hasRunFailingTestTag) {
+ $noSudoPesterParam['IncludeFailingTest'] = $true
+ }
+
+ # Get the experimental feature names and the tests associated with them
+ $ExperimentalFeatureTests = Get-ExperimentalFeatureTests
+
+ # Running tests which do not require sudo.
+ $pesterPassThruNoSudoObject = Start-PSPester @noSudoPesterParam -Title 'Pester No Sudo'
+
+ # 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')
+ }
+ 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')
+ }
+ 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
+ try {
+ $allTestResultsWithNoExpFeature = @($pesterPassThruNoSudoObject, $pesterPassThruSudoObject)
+ $allTestResultsWithExpFeatures = $noSudoResultsWithExpFeatures + $sudoResultsWithExpFeatures
+ # This throws if there was an error:
+ $allTestResultsWithNoExpFeature | ForEach-Object { Test-PSPesterResults -ResultObject $_ }
+ $allTestResultsWithExpFeatures | ForEach-Object { Test-PSPesterResults -ResultObject $_ -CanHaveNoResult }
+ $result = "PASS"
+ } catch {
+ # The build failed, set the result:
+ $resultError = $_
+ $result = "FAIL"
+ }
+
+ try {
+ $ParallelXUnitTestResultsFile = "$pwd/ParallelXUnitTestResults.xml"
+ Start-PSxUnit -ParallelTestResultsFile $ParallelXUnitTestResultsFile
+ # If there are failures, Test-XUnitTestResults throws
+ Test-XUnitTestResults -TestResultsFile $ParallelXUnitTestResultsFile
+ } catch {
+ $result = "FAIL"
+ if (!$resultError)
+ {
+ $resultError = $_
+ }
+ }
+
+ 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($isDailyBuild -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($isDailyBuild)
+ {
+ 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 ($isDailyBuild)
+ {
+ New-TestPackage -Destination "${env:SYSTEM_ARTIFACTSDIRECTORY}"
+ }
+ }
+
+ # 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!"
+ }
+}
diff --git a/tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml b/tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml
index 1b32bb07079..ae697e70e33 100644
--- a/tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml
+++ b/tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml
@@ -7,5 +7,5 @@ steps:
{
throw "nuget.config is not created"
}
- displayName: 'Add nuget.config for AzDevOps feed for PSGallery modules '
+ displayName: 'Add nuget.config for Azure DevOps feed for PSGallery modules'
condition: and(succeededOrFailed(), ne(variables['AzDevOpsFeed'], ''))
diff --git a/tools/releaseTools.psm1 b/tools/releaseTools.psm1
index 2f9d0dcdc8c..42274c8f4f0 100644
--- a/tools/releaseTools.psm1
+++ b/tools/releaseTools.psm1
@@ -1,7 +1,7 @@
#requires -Version 6.0
-
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
+
class CommitNode {
[string] $Hash
[string[]] $Parents
@@ -43,6 +43,7 @@ $Script:community_login_map = @{
"info@powercode-consulting.se" = "powercode"
}
+# ignore dependency bumping bot (dependabot):
$Script:attribution_ignore_list = @(
'dependabot[bot]@users.noreply.github.com'
)
diff --git a/tools/travis.ps1 b/tools/travis.ps1
deleted file mode 100644
index 2b08cddf95a..00000000000
--- a/tools/travis.ps1
+++ /dev/null
@@ -1,453 +0,0 @@
-# Copyright (c) Microsoft Corporation. All rights reserved.
-# Licensed under the MIT License.
-param(
- [ValidateSet('Bootstrap','Build','Failure','Success')]
- [String]$Stage = 'Build',
- [String]$NugetKey
-)
-
-Import-Module $PSScriptRoot/../build.psm1 -Force
-Import-Module $PSScriptRoot/packaging -Force
-
-function Send-DailyWebHook
-{
- param (
- [Parameter(Mandatory=$true,Position=0)][ValidateSet("Pass","Fail")]$result
- )
-
- # Only send web hook if the environment variable is present
- # Varible should be set in Travis-CI.org settings
- if ($env:WebHookUrl)
- {
- Write-Log "Sending DailyWebHook with result '$result'."
- $webhook = $env:WebHookUrl
-
- $Body = @{
- 'text'= @"
-Build Result: $result
-OS Type: $($PSVersionTable.OS)
-Build $env:TRAVIS_BUILD_NUMBER
-Job $env:TRAVIS_JOB_NUMBER
-"@
- }
-
- $params = @{
- Headers = @{'accept'='application/json'}
- Body = $Body | convertto-json
- Method = 'Post'
- URI = $webhook
- }
-
- Invoke-RestMethod @params
- }
- else
- {
- Write-Log "Skipping DailyWebHook. WebHookUrl environment variable not present."
- }
-}
-
-function Get-ReleaseTag
-{
- $metaDataPath = Join-Path -Path $PSScriptRoot -ChildPath 'metadata.json'
- $metaData = Get-Content $metaDataPath | ConvertFrom-Json
-
- $releaseTag = $metadata.PreviewReleaseTag
- $previewVersion = $releaseTag.Split('-')
- $previewPrefix = $previewVersion[0]
- $previewLabel = $previewVersion[1].replace('.','')
-
- if($isDailyBuild)
- {
- $previewLabel= "daily{0}" -f $previewLabel
- }
-
- $preReleaseVersion = "$previewPrefix-$previewLabel.$env:BUILD_BUILDID"
-
- return $preReleaseVersion
-}
-
-# This function retrieves the appropriate svg to be used when presenting
-# the daily test run badge
-# the location in azure is public readonly
-function Get-DailyBadge
-{
- param (
- [Parameter(Mandatory=$true,Position=0)][ValidateSet("Pass","Fail")]$result
- )
- $PASS = "https://jimtru1979.blob.core.windows.net/badges/DailyBuild.Pass.svg"
- $FAIL = "https://jimtru1979.blob.core.windows.net/badges/DailyBuild.Fail.svg"
-
- if ( $result -eq "Pass" ) { $BadgeUrl = $PASS } else { $BadgeUrl = $FAIL }
- $response = Invoke-WebRequest -Uri $BadgeUrl
- if ( $response.StatusCode -ne 200 ) { throw "Could not read badge '$BadgeUrl'" }
- $response.Content
-}
-
-# This function uses Azure REST api to update the daily test pass results
-# it relies on writing a specific SVG into a constant location so the
-# README.MD can report on the status of the daily test pass
-# it also relies on two environment variables which need to be set in the
-# Travis-CI config which is the account name and key for the azure blob location
-#
-# the best way to do this would be if travis-ci supported a webcall to get
-# the status of cron_job builds, but it doesn't, so we have this
-# also, since we can have a build on Linux which succeeds and one on macOS which
-# doesn't we'll set the appropriate badge so the the README can pick it up
-function Set-DailyBuildBadge
-{
- [CmdletBinding(SupportsShouldProcess=$true)]
- param ( [Parameter(Mandatory=$true,Position=0)]$content )
- $method = "PUT"
- $headerDate = '2015-12-11'
-
- $storageAccountName = $Env:TestResultAccountName
- $storageAccountKey = $Env:TestResultAccountKey
-
- # this is the url referenced in README.MD which displays the badge
- $platform = if ( $IsLinux ) { "Linux" } else { "OSX" }
- $Url = "https://jimtru1979.blob.core.windows.net/badges/DailyBuildStatus.${platform}.svg"
-
- $body = $content
- $bytes = ([System.Text.Encoding]::UTF8.GetBytes($body))
- $contentLength = $bytes.length
-
- $now = [datetime]::UtcNow.ToString("R", [System.Globalization.CultureInfo]::InvariantCulture)
- $headers = @{
- "x-ms-date" = $now
- "cache-control" = "no-cache"
- "x-ms-blob-type" = "BlockBlob"
- "x-ms-version" = "$headerDate"
- }
-
- $contentType = "image/svg+xml"
- # more info: https://docs.microsoft.com/rest/api/storageservices/fileservices/put-blob
- $sb = [text.stringbuilder]::new()
- # can't use AppendLine because the `r`n causes the command to fail, it must be `n and only `n
- $null = $sb.Append("$method`n")
- $null = $sb.Append("`n")
- $null = $sb.Append("`n")
- $null = $sb.Append("$contentLength`n")
- $null = $sb.Append("`n")
- $null = $sb.Append("$contentType`n")
- $null = $sb.Append("`n")
- $null = $sb.Append("`n")
- $null = $sb.Append("`n")
- $null = $sb.Append("`n")
- $null = $sb.Append("`n")
- $null = $sb.Append("`n")
-
- $null = $sb.Append("x-ms-blob-type:" + $headers["x-ms-blob-type"] + "`n")
- $null = $sb.Append("x-ms-date:" + $headers["x-ms-date"] + "`n")
- $null = $sb.Append("x-ms-version:" + $headers["x-ms-version"] + "`n")
- $null = $sb.Append("/" + $storageAccountName + ([System.Uri]::new($url).AbsolutePath))
-
- $dataToMac = [System.Text.Encoding]::UTF8.GetBytes($sb.ToString())
- $accountKeyBytes = [System.Convert]::FromBase64String($storageAccountKey)
- $hmac = [System.Security.Cryptography.HMACSHA256]::new($accountKeyBytes)
- $signature = [System.Convert]::ToBase64String($hmac.ComputeHash($dataToMac))
-
- $headers["Authorization"] = "SharedKey " + $storageAccountName + ":" + $signature
-
- if ( $PSCmdlet.ShouldProcess("$signaturestring"))
- {
- # if this fails, it will throw, you can't check the response for a success code
- $response = Invoke-RestMethod -Uri $Url -Method $method -headers $headers -Body $body -ContentType "image/svg+xml"
- }
-}
-
-# https://docs.travis-ci.com/user/environment-variables/
-# TRAVIS_EVENT_TYPE: Indicates how the build was triggered.
-# One of push, pull_request, api, cron.
-$isPR = $env:TRAVIS_EVENT_TYPE -eq 'pull_request'
-
-$commitMessage = [string]::Empty
-
-# For PRs, Travis-ci strips out [ and ] so read the message directly from git
-if($env:TRAVIS_EVENT_TYPE -eq 'pull_request' -or $env:BUILD_REASON)
-{
- $commitId = $null
- if ($env:TRAVIS_EVENT_TYPE)
- {
- # We are in Travis-CI
- $commitId = $env:TRAVIS_PULL_REQUEST_SHA
-
- # If the current job is a pull request, the env variable 'TRAVIS_PULL_REQUEST_SHA' contains
- # the commit SHA of the HEAD commit of the PR.
- $commitMessage = git log --format=%B -n 1 $commitId
- Write-Log -message "commitMessage: $commitMessage"
- }
- elseif($env:TF_BUILD)
- {
- if($env:BUILD_SOURCEVERSIONMESSAGE -match 'Merge\s*([0-9A-F]*)')
- {
- # We are in VSTS and have a commit ID in the Source Version Message
- $commitId = $Matches[1]
- $commitMessage = git log --format=%B -n 1 $commitId
- }
- else
- {
- Write-Log "Unknown BUILD_SOURCEVERSIONMESSAGE format '$env:BUILD_SOURCEVERSIONMESSAGE'" -Verbose
- }
- }
-}
-else
-{
- $commitMessage = $env:TRAVIS_COMMIT_MESSAGE
-}
-
-# Run a full build if the build was trigger via cron, api or the commit message contains `[Feature]`
-# or the environment variable `FORCE_FEATURE` equals `True`
-$hasFeatureTag = $commitMessage -match '\[feature\]' -or $env:FORCE_FEATURE -eq 'True'
-
-# Run a packaging if the commit message contains `[Package]`
-# or the environment variable `FORCE_PACKAGE` equals `True`
-$hasPackageTag = $commitMessage -match '\[package\]' -or $env:FORCE_PACKAGE -eq 'True'
-$createPackages = -not $isPr -or $hasPackageTag
-$hasRunFailingTestTag = $commitMessage -match '\[includeFailingTest\]'
-$isDailyBuild = $env:TRAVIS_EVENT_TYPE -eq 'cron' -or $env:TRAVIS_EVENT_TYPE -eq 'api' -or $env:BUILD_REASON -eq 'Schedule'
-# only update the build badge for the cron job
-$cronBuild = $env:TRAVIS_EVENT_TYPE -eq 'cron' -or $env:BUILD_REASON -eq 'Schedule'
-$isFullBuild = $isDailyBuild -or $hasFeatureTag
-
-if($Stage -eq 'Bootstrap')
-{
- if($cronBuild -and $env:TF_BUILD)
- {
- Write-Host "##vso[build.updatebuildnumber]Daily-$env:BUILD_SOURCEBRANCHNAME-$env:BUILD_SOURCEVERSION-$((get-date).ToString("yyyyMMddhhmmss"))"
- }
-
- Write-Host -Foreground Green "Executing travis.ps1 -BootStrap `$isPR='$isPr' - $commitMessage"
- # Make sure we have all the tags
- Sync-PSTags -AddRemoteIfMissing
- Start-PSBootstrap -Package:$createPackages
-}
-elseif($Stage -eq 'Build')
-{
- $releaseTag = Get-ReleaseTag
-
- Write-Host -Foreground Green "Executing travis.ps1 `$isPR='$isPr' `$isFullBuild='$isFullBuild' - $commitMessage"
-
- $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
- }
-
- $output = Split-Path -Parent (Get-PSOutput -Options (Get-PSOptions))
-
- $testResultsNoSudo = "$pwd/TestResultsNoSudo.xml"
- $testResultsSudo = "$pwd/TestResultsSudo.xml"
-
- $excludeTag = @('RequireSudoOnUnix')
-
- $noSudoPesterParam = @{
- 'BinDir' = $output
- 'PassThru' = $true
- 'Terse' = $true
- 'Tag' = @()
- 'ExcludeTag' = $excludeTag
- 'OutputFile' = $testResultsNoSudo
- }
-
- if ($isFullBuild) {
- $noSudoPesterParam['Tag'] = @('CI','Feature','Scenario')
- } else {
- $noSudoPesterParam['Tag'] = @('CI')
- $noSudoPesterParam['ThrowOnFailure'] = $true
- }
-
- if ($hasRunFailingTestTag) {
- $noSudoPesterParam['IncludeFailingTest'] = $true
- }
-
- # Get the experimental feature names and the tests associated with them
- $ExperimentalFeatureTests = Get-ExperimentalFeatureTests
-
- # Running tests which do not require sudo.
- $pesterPassThruNoSudoObject = Start-PSPester @noSudoPesterParam -Title 'Pester No Sudo'
-
- # 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')
- } 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')
- } 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
- try {
- $allTestResultsWithNoExpFeature = @($pesterPassThruNoSudoObject, $pesterPassThruSudoObject)
- $allTestResultsWithExpFeatures = $noSudoResultsWithExpFeatures + $sudoResultsWithExpFeatures
- # this throws if there was an error
- $allTestResultsWithNoExpFeature | ForEach-Object { Test-PSPesterResults -ResultObject $_ }
- $allTestResultsWithExpFeatures | ForEach-Object { Test-PSPesterResults -ResultObject $_ -CanHaveNoResult }
- $result = "PASS"
- }
- catch {
- $resultError = $_
- $result = "FAIL"
- }
-
- try {
- $ParallelXUnitTestResultsFile = "$pwd/ParallelXUnitTestResults.xml"
-
- Start-PSxUnit -ParallelTestResultsFile $ParallelXUnitTestResultsFile
- # If there are failures, Test-XUnitTestResults throws
- Test-XUnitTestResults -TestResultsFile $ParallelXUnitTestResultsFile
- }
- catch {
- $result = "FAIL"
- if (!$resultError)
- {
- $resultError = $_
- }
- }
-
- if ($createPackages) {
-
- $packageParams = @{}
- $packageParams += @{ReleaseTag=$releaseTag}
-
- # Only build packages for 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($isDailyBuild -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($isDailyBuild)
- {
- 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 ($isDailyBuild)
- {
- New-TestPackage -Destination "${env:SYSTEM_ARTIFACTSDIRECTORY}"
- }
- }
-
- # if the tests did not pass, throw the reason why
- if ( $result -eq "FAIL" ) {
- Throw $resultError
- }
-}
-elseif($Stage -in 'Failure', 'Success')
-{
- $result = 'PASS'
- if($Stage -eq 'Failure')
- {
- $result = 'FAIL'
- }
-
- if ($cronBuild) {
- # update the badge if you've done a cron build, these are not fatal issues
- try {
- $svgData = Get-DailyBadge -result $result
- if ( ! $svgData ) {
- write-warning "Could not retrieve $result badge"
- }
- else {
- Write-Log "Setting status badge to '$result'"
- Set-DailyBuildBadge -content $svgData
- }
- }
- catch {
- Write-Warning "Could not update status badge: $_"
- }
-
- try {
- Send-DailyWebHook -result $result
- }
- catch {
- Write-Warning "Could not send webhook: $_"
- }
- }
- else {
- Write-Log 'We only send bagde or webhook update for Cron builds'
- }
-
-}
diff --git a/tools/windows/Reset-PWSHSystemPath.ps1 b/tools/windows/Reset-PWSHSystemPath.ps1
index eb3b182d419..527f726bd66 100644
--- a/tools/windows/Reset-PWSHSystemPath.ps1
+++ b/tools/windows/Reset-PWSHSystemPath.ps1
@@ -1,3 +1,6 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License.
+
<#
.SYNOPSIS
Idempotently removes extra PowerShell Core paths from the machine, user and/or process environment scope with no reordering.