From 882cbf367f7cc90d08c928b48f2e7d774fa2d146 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 8 Aug 2019 11:37:25 -0700 Subject: [PATCH] Enable Experimental Features by default on Preview builds (#10228) --- build.psm1 | 29 ++++++++- .../powershell.config.json | 1 - .../powershell-win-core.csproj | 5 -- .../engine/Basic/DefaultCommands.Tests.ps1 | 65 +++++++++++++++---- .../ExperimentalFeature.Basic.Tests.ps1 | 4 -- .../Get-ExperimentalFeature.Tests.ps1 | 48 ++++++++++++++ 6 files changed, 128 insertions(+), 24 deletions(-) delete mode 100644 src/System.Management.Automation/powershell.config.json diff --git a/build.psm1 b/build.psm1 index 7e6e21bb21..f8b6696f03 100644 --- a/build.psm1 +++ b/build.psm1 @@ -446,6 +446,31 @@ Fix steps: Pop-Location } + # publish powershell.config.json + $config = @{} + if ($Environment.IsWindows) { + $config = @{ "Microsoft.PowerShell:ExecutionPolicy" = "RemoteSigned" } + } + + if ($ReleaseTag) { + $psVersion = $ReleaseTag + } + else { + $psVersion = git --git-dir="$PSSCriptRoot/.git" describe + } + + # ARM is cross compiled, so we can't run pwsh to enumerate Experimental Features + if ((Test-IsPreview $psVersion) -and -not $Runtime.Contains("arm")) { + $expFeatures = [System.Collections.Generic.List[string]]::new() + & $publishPath\pwsh -noprofile -out XML -command Get-ExperimentalFeature | ForEach-Object { $expFeatures.Add($_.Name) } + $config += @{ ExperimentalFeatures = $expFeatures.ToArray() } + } + + if ($config.Count -gt 0) { + $configPublishPath = Join-Path -Path $publishPath -ChildPath "powershell.config.json" + Set-Content -Path $configPublishPath -Value ($config | ConvertTo-Json) -Force -ErrorAction Stop + } + if ($Environment.IsRedHatFamily -or $Environment.IsDebian9) { # add two symbolic links to system shared libraries that libmi.so is dependent on to handle # platform specific changes. This is the only set of platforms needed for this currently @@ -1506,8 +1531,8 @@ function Install-Dotnet { # Note that when it is null, Invoke-Expression (but not &) must be used to interpolate properly $sudo = if (!$NoSudo) { "sudo" } - $installObtainUrl = "https://dot.net/v1" - $uninstallObtainUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain" + $installObtainUrl = "https://dot.net/v1" + $uninstallObtainUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain" # Install for Linux and OS X if ($Environment.IsLinux -or $Environment.IsMacOS) { diff --git a/src/System.Management.Automation/powershell.config.json b/src/System.Management.Automation/powershell.config.json deleted file mode 100644 index 088f5cb24d..0000000000 --- a/src/System.Management.Automation/powershell.config.json +++ /dev/null @@ -1 +0,0 @@ -{"Microsoft.PowerShell:ExecutionPolicy":"RemoteSigned"} diff --git a/src/powershell-win-core/powershell-win-core.csproj b/src/powershell-win-core/powershell-win-core.csproj index 8bb6d2cfdc..f1ca7c18ac 100644 --- a/src/powershell-win-core/powershell-win-core.csproj +++ b/src/powershell-win-core/powershell-win-core.csproj @@ -25,11 +25,6 @@ - - powershell.config.json - PreserveNewest - PreserveNewest - Modules\%(RecursiveDir)\%(FileName)%(Extension) PreserveNewest diff --git a/test/powershell/engine/Basic/DefaultCommands.Tests.ps1 b/test/powershell/engine/Basic/DefaultCommands.Tests.ps1 index 1c64bc8171..6d4be92eb0 100644 --- a/test/powershell/engine/Basic/DefaultCommands.Tests.ps1 +++ b/test/powershell/engine/Basic/DefaultCommands.Tests.ps1 @@ -5,6 +5,17 @@ Describe "Verify approved aliases list" -Tags "CI" { $FullCLR = !$isCoreCLR $CoreWindows = $isCoreCLR -and $IsWindows $CoreUnix = $isCoreCLR -and !$IsWindows + $isPreview = $PSVersionTable.GitCommitId.Contains("preview") + if ($IsWindows) { + $configPath = Join-Path -Path $env:USERPROFILE -ChildPath 'Documents' -AdditionalChildPath 'PowerShell' + } + else { + $configPath = Join-Path -Path $env:HOME -ChildPath '.config' -AdditionalChildPath 'powershell' + } + + if (Test-Path "$configPath/powershell.config.json") { + Move-Item -Path "$configPath/powershell.config.json" -Destination "$configPath/powershell.config.json.backup" + } $AllScope = '[System.Management.Automation.ScopedItemOptions]::AllScope' $ReadOnly = '[System.Management.Automation.ScopedItemOptions]::ReadOnly' @@ -485,13 +496,50 @@ Describe "Verify approved aliases list" -Tags "CI" { # We control only default engine aliases (Source -eq "") and aliases from following default loaded modules # We control only default engine Cmdlets (Source -eq "") and Cmdlets from following default loaded modules $moduleList = @("Microsoft.PowerShell.Utility", "Microsoft.PowerShell.Management", "Microsoft.PowerShell.Security", "Microsoft.PowerShell.Host", "Microsoft.PowerShell.Diagnostics", "PSWorkflow", "Microsoft.WSMan.Management", "Microsoft.PowerShell.Core") - Import-Module -Name $moduleList -ErrorAction SilentlyContinue - $currentAliasList = Get-Alias | Where-Object { $_.Source -eq "" -or $moduleList -contains $_.Source } + $getAliases = { + param($moduleList) + + if ($moduleList -is [string]) { + $moduleList = $moduleList | ConvertFrom-Json + } + + Import-Module -Name $moduleList -ErrorAction SilentlyContinue + Get-Alias | Where-Object { $_.Source -eq "" -or $moduleList -contains $_.Source } + } + + $getCommands = { + param($moduleList) + + if ($moduleList -is [string]) { + $moduleList = $moduleList | ConvertFrom-Json + } + + Import-Module -Name $moduleList -ErrorAction SilentlyContinue + Get-Command -CommandType Cmdlet | Where-Object { $moduleList -contains $_.Source } + } + + # On Preview releases, Experimental Features may add new cmdlets/aliases, so we get cmdlets/aliases with features disabled + if ($isPreview) { + $emptyConfigPath = Join-Path -Path $TestDrive -ChildPath "test.config.json" + Set-Content -Path $emptyConfigPath -Value "" -Force -ErrorAction Stop + $currentAliasList = pwsh -out XML -SettingsFile $emptyConfigPath -Command $getAliases -args ($moduleList | ConvertTo-Json) + $currentCmdletList = pwsh -out XML -SettingsFile $emptyConfigPath -Command $getCommands -args ($moduleList | ConvertTo-Json) + } + else { + $currentAliasList = & $getAliases $moduleList + $currentCmdletList = & $getCommands $moduleList + } $commandList = $commandString | ConvertFrom-CSV -Delimiter "," $aliasFullList = $commandList | Where-Object { $_.Present -eq "True" -and $_.CommandType -eq "Alias" } } + AfterAll { + if (Test-Path "$configPath/powershell.config.json.backup") { + Move-Item -Path "$configPath/powershell.config.json.backup" -Destination "$configPath/powershell.config.json" + } + } + It "All approved aliases present (no new aliases added, no aliases removed)" { $currentDisplayNameAliasList = $currentAliasList | Select-Object -ExpandProperty DisplayName $aliasDisplayNameAliasList = $aliasFullList | ForEach-Object { "{0} -> {1}" -f $_.Name, $_.Definition} @@ -530,13 +578,8 @@ Describe "Verify approved aliases list" -Tags "CI" { It "All approved Cmdlets present (no new Cmdlets added, no Cmdlets removed)" { $cmdletList = $commandList | Where-Object { $_.Present -eq "True" -and $_.CommandType -eq "Cmdlet" } | Select-Object -ExpandProperty Name - $currentCmdletList = (Get-Command -CommandType Cmdlet | Where-Object { $moduleList -contains $_.Source }).Name - $result = Compare-Object -ReferenceObject $currentCmdletList -DifferenceObject $cmdletList - - # Below 'Should Be' don't show full list wrong Cmdlets so we output them explicitly - # if all Cmdlets is Ok we output nothing - $result | Write-Host + $result = (Compare-Object -ReferenceObject $currentCmdletList.Name -DifferenceObject $cmdletList).InputObject $result | Should -BeNullOrEmpty } @@ -545,7 +588,8 @@ Describe "Verify approved aliases list" -Tags "CI" { Where-Object { $_.Present -eq "True" -and $_.CommandType -eq "Cmdlet"} | Select-Object -Property Name, ConfirmImpact - $currentCmdletList = Get-Command -CommandType Cmdlet | + # if Preview, $currentCmdletList is deserialized, so we re-hydrate them so comparison succeeds + $currentCmdletList = $currentCmdletList | ForEach-Object { Get-Command $_.Name } | Where-Object { $moduleList -contains $_.Source -and $null -ne $_.ImplementingType } | Select-Object -Property Name, @{ Name = 'ConfirmImpact' @@ -558,9 +602,6 @@ Describe "Verify approved aliases list" -Tags "CI" { # -PassThru is provided to give meaningful output when differences arise $result = Compare-Object -ReferenceObject $currentCmdletList -DifferenceObject $CmdletList -Property ConfirmImpact -PassThru - - # As above, the test message doesn't give full list, so we write-host it explicitly - $result | Sort-Object -Property Name, SideIndicator | Write-Host $result | Should -BeNullOrEmpty } } diff --git a/test/powershell/engine/ExperimentalFeature/ExperimentalFeature.Basic.Tests.ps1 b/test/powershell/engine/ExperimentalFeature/ExperimentalFeature.Basic.Tests.ps1 index e4d6f52937..e84f52cbe6 100644 --- a/test/powershell/engine/ExperimentalFeature/ExperimentalFeature.Basic.Tests.ps1 +++ b/test/powershell/engine/ExperimentalFeature/ExperimentalFeature.Basic.Tests.ps1 @@ -36,10 +36,6 @@ Describe "Experimental Feature Basic Tests - Feature-Disabled" -tags "CI" { } } - It "No experimental feature is enabled" { - $EnabledExperimentalFeatures.Count | Should -Be 0 - } - It "Replace existing command - version one should be shown" -TestCases @( @{ Name = "Invoke-AzureFunction"; CommandType = "Function" } @{ Name = "Invoke-AzureFunctionCSharp"; CommandType = "Cmdlet" } diff --git a/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 b/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 index bf2bbc855a..bf72bbca73 100644 --- a/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 +++ b/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 @@ -129,3 +129,51 @@ Describe "Get-ExperimentalFeature Tests" -tags "Feature","RequireAdminOnWindows" } } } + +Describe "Default enablement of Experimental Features" -Tags CI { + BeforeAll { + $isPreview = $PSVersionTable.GitCommitId.Contains("preview") + + Function BeEnabled { + [CmdletBinding()] + Param( + $ActualValue, + $Name, + [switch]$Negate + ) + + $failure = if ($Negate) { + "Expected: Feature $Name to not be Enabled" + } + else { + "Expected: Feature $Name to be Enabled" + } + + return [PSCustomObject]@{ + Succeeded = if ($Negate) { + $ActualValue -eq $false + } + else { + $ActualValue -eq $true + } + FailureMessage = $failure + } + } + + Add-AssertionOperator -Name 'BeEnabled' -Test $Function:BeEnabled + } + + It "On stable builds, Experimental Features are not enabled" -Skip:($isPreview) { + foreach ($expFeature in Get-ExperimentalFeature) { + $expFeature.Enabled | Should -Not -BeEnabled -Name $expFeature.Name + } + } + + It "On preview builds, Experimental Features are enabled" -Skip:(!$isPreview) { + (Join-Path -Path $PSHOME -ChildPath 'powershell.config.json') | Should -Exist + + foreach ($expFeature in Get-ExperimentalFeature) { + $expFeature.Enabled | Should -BeEnabled -Name $expFeature.Name + } + } +}