diff --git a/CHANGELOG/preview.md b/CHANGELOG/7.4.md similarity index 97% rename from CHANGELOG/preview.md rename to CHANGELOG/7.4.md index d8ba3d0958e..5dd5481c919 100644 --- a/CHANGELOG/preview.md +++ b/CHANGELOG/7.4.md @@ -1,4 +1,42 @@ -# Current preview release +# 7.4 Changelog + +## [7.4.0] - 2023-11-16 + +### General Cmdlet Updates and Fixes + +- Added a missing `ConfigureAwait(false)` call to webcmdlets so they don't block (#20622) +- Fix `Group-Object` so output uses current culture (#20623) +- Block getting help from network locations in restricted remoting sessions (#20615) + +### Build and Packaging Improvements + + + + + +Bump .NET 8 to 8.0.0 RTM build + + + + +Add internal .NET SDK URL parameter to release pipeline (Internal 28474) +Update the CGManifest file for v7.4.0 release (Internal 28457) +Fix repository root for the nuget.config (Internal 28456) +Add internal nuget feed to compliance build (Internal 28449) +Copy azure blob with PowerShell global tool to private blob and move to CDN during release (Internal 28438) +Fix release build by making the internal SDK parameter optional (#20658) (Internal 28440) +Make internal .NET SDK URL as a parameter for release builld (#20655) (Internal 28428) +Update PSResourceGet version for 1.0.1 release (#20652) (Internal 28427) +Bump .NET 8 to 8.0.0 RTM build (Internal 28360) +Remove Auth header content from ErrorRecord (Internal 28409) +Fix setting of variable to consume internal SDK source (Internal 28354) +Bump Microsoft.Management.Infrastructure to v3.0.0 (Internal 28352) +Bump Microsoft.PowerShell.Native to v7.4.0 (#20617) (#20624) + + + + +[7.4.0]: https://github.com/PowerShell/PowerShell/compare/v7.4.0-rc.1...v7.4.0 ## [7.4.0-rc.1] - 2023-10-24 diff --git a/DotnetRuntimeMetadata.json b/DotnetRuntimeMetadata.json index 5b6ac60b802..0eca4cf79f4 100644 --- a/DotnetRuntimeMetadata.json +++ b/DotnetRuntimeMetadata.json @@ -1,15 +1,15 @@ { "sdk": { - "channel": "8.0.1xx-rc2", + "channel": "8.0.1xx", "quality": "daily", "qualityFallback": "preview", - "packageVersionPattern": "8.0.0-rc.2", + "packageVersionPattern": "8.0.0", "sdkImageVersion": "8.0.100", - "nextChannel": "8.0.1xx-rc2", + "nextChannel": "8.0.1xx", "azureFeed": "", - "sdkImageOverride": "8.0.100-rc.2.23502.2" + "sdkImageOverride": "8.0.100-rtm.23551.15" }, "internalfeed": { - "url": "" + "url": "https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-7.4-ga/nuget/v2" } } diff --git a/build.psm1 b/build.psm1 index ec95e071bf7..55110cd9cf6 100644 --- a/build.psm1 +++ b/build.psm1 @@ -19,7 +19,8 @@ $script:Options = $null $dotnetMetadata = Get-Content $PSScriptRoot/DotnetRuntimeMetadata.json | ConvertFrom-Json $dotnetCLIChannel = $dotnetMetadata.Sdk.Channel $dotnetCLIQuality = $dotnetMetadata.Sdk.Quality -$dotnetAzureFeed = if (-not $env:__DOTNET_RUNTIME_FEED ) { $dotnetMetadata.Sdk.azureFeed } +# __DOTNET_RUNTIME_FEED and __DOTNET_RUNTIME_FEED_KEY are private variables used in release builds +$dotnetAzureFeed = if ([string]::IsNullOrWhiteSpace($env:__DOTNET_RUNTIME_FEED)) { $dotnetMetadata.Sdk.azureFeed } else { $env:__DOTNET_RUNTIME_FEED } $dotnetAzureFeedSecret = $env:__DOTNET_RUNTIME_FEED_KEY $dotnetSDKVersionOveride = $dotnetMetadata.Sdk.sdkImageOverride $dotnetCLIRequiredVersion = $(Get-Content $PSScriptRoot/global.json | ConvertFrom-Json).Sdk.Version diff --git a/global.json b/global.json index 3ecc5db745d..5ce84955149 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "8.0.100-rc.2.23502.2" + "version": "8.0.100" } } diff --git a/src/Microsoft.Management.UI.Internal/commandHelpers/ShowCommandHelper.cs b/src/Microsoft.Management.UI.Internal/commandHelpers/ShowCommandHelper.cs index 13dfe839b9d..32c68e961c6 100644 --- a/src/Microsoft.Management.UI.Internal/commandHelpers/ShowCommandHelper.cs +++ b/src/Microsoft.Management.UI.Internal/commandHelpers/ShowCommandHelper.cs @@ -489,37 +489,6 @@ private static string GetSerializedCommandScript() @"Remove-Item -Path 'function:\PSGetSerializedShowCommandInfo' -Force"); } - /// - /// Gets the command to be run to in order to import a module and refresh the command data. - /// - /// Module we want to import. - /// Boolean flag determining whether Show-Command is queried in the local or remote runspace scenario. - /// Boolean flag to indicate that it is the second attempt to query Show-Command data. - /// The command to be run to in order to import a module and refresh the command data. - internal static string GetImportModuleCommand(string module, bool isRemoteRunspace = false, bool isFirstChance = true) - { - string scriptBase = "Import-Module " + ShowCommandHelper.SingleQuote(module); - - if (isRemoteRunspace) - { - if (isFirstChance) - { - scriptBase += ";@(Get-Command " + ShowCommandHelper.CommandTypeSegment + @" -ShowCommandInfo )"; - } - else - { - scriptBase += GetSerializedCommandScript(); - } - } - else - { - scriptBase += ";@(Get-Command " + ShowCommandHelper.CommandTypeSegment + ")"; - } - - scriptBase += ShowCommandHelper.GetGetModuleSuffix(); - return scriptBase; - } - /// /// Gets the command to be run in order to show help for a command. /// diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/Microsoft.PowerShell.Commands.Diagnostics.csproj b/src/Microsoft.PowerShell.Commands.Diagnostics/Microsoft.PowerShell.Commands.Diagnostics.csproj index 1e7f70bc8f8..1281bac664b 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/Microsoft.PowerShell.Commands.Diagnostics.csproj +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/Microsoft.PowerShell.Commands.Diagnostics.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj b/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj index 0d6c585478d..a4e24bf8be9 100644 --- a/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj +++ b/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj @@ -47,7 +47,7 @@ - + diff --git a/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj b/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj index a23b657f61e..fc5a61d44b8 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj +++ b/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj @@ -33,8 +33,8 @@ - - + + diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Group-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Group-Object.cs index 51f8f0a6011..0f0a9951967 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Group-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Group-Object.cs @@ -153,7 +153,7 @@ private static string BuildName(List propValues) foreach (object item in propertyValueItems) { - sb.Append(CultureInfo.InvariantCulture, $"{item}, "); + sb.AppendFormat(CultureInfo.CurrentCulture, $"{item}, "); } sb = sb.Length > length ? sb.Remove(sb.Length - 2, 2) : sb; @@ -161,7 +161,7 @@ private static string BuildName(List propValues) } else { - sb.Append(CultureInfo.InvariantCulture, $"{propValuePropertyValue}, "); + sb.AppendFormat(CultureInfo.CurrentCulture, $"{propValuePropertyValue}, "); } } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 95b25e4e4d5..981bdd08fdd 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -634,7 +634,7 @@ protected override void ProcessRecord() response.ReasonPhrase); HttpResponseException httpEx = new(message, response); - ErrorRecord er = new(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); + ErrorRecord er = new(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, RedactAuthorizationHeader(request)); string detailMsg = string.Empty; try { @@ -675,7 +675,7 @@ protected override void ProcessRecord() // (and still writing out the result), users can debug actual HTTP redirect problems. if (_maximumRedirection == 0 && IsRedirectCode(response.StatusCode)) { - ErrorRecord er = new(new InvalidOperationException(), "MaximumRedirectExceeded", ErrorCategory.InvalidOperation, request); + ErrorRecord er = new(new InvalidOperationException(), "MaximumRedirectExceeded", ErrorCategory.InvalidOperation, RedactAuthorizationHeader(request)); er.ErrorDetails = new ErrorDetails(WebCmdletStrings.MaximumRedirectionCountExceeded); WriteError(er); } @@ -687,7 +687,7 @@ protected override void ProcessRecord() } catch (HttpRequestException ex) { - ErrorRecord er = new(ex, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); + ErrorRecord er = new(ex, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, RedactAuthorizationHeader(request)); if (ex.InnerException is not null) { er.ErrorDetails = new ErrorDetails(ex.InnerException.Message); @@ -1525,6 +1525,27 @@ private string GetBearerAuthorizationHeader() return string.Create(CultureInfo.InvariantCulture, $"Bearer {new NetworkCredential(string.Empty, Token).Password}"); } + private static HttpRequestMessage RedactAuthorizationHeader(HttpRequestMessage request) + { + if (request.Headers is not null && request.Headers.Authorization is not null && request.Headers.Authorization.Parameter is not null) + { + // redact the auth parameter, but leave the last 4 characters for developers to validate + // the right token was sent + var authParameter = request.Headers.Authorization.Parameter; + var redactLength = authParameter.Length - 4; + if (redactLength < 0) + { + redactLength = authParameter.Length; + } + + request.Headers.Authorization = new AuthenticationHeaderValue( + request.Headers.Authorization.Scheme, + string.Concat("****", authParameter.Substring(redactLength).AsSpan())); + } + + return request; + } + private void ProcessAuthentication() { if (Authentication == WebAuthenticationType.Basic) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/StreamHelper.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/StreamHelper.cs index d03debf3fc0..52ff515b0b2 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/StreamHelper.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/StreamHelper.cs @@ -265,7 +265,7 @@ internal static async Task ReadAsync(this Stream stream, Memory buffe { if (readTimeout == Timeout.InfiniteTimeSpan) { - return await stream.ReadAsync(buffer, cancellationToken); + return await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); } using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); @@ -292,7 +292,7 @@ internal static async Task CopyToAsync(this Stream source, Stream destination, T if (perReadTimeout == Timeout.InfiniteTimeSpan) { // No timeout - use fast path - await source.CopyToAsync(destination, cancellationToken); + await source.CopyToAsync(destination, cancellationToken).ConfigureAwait(false); return; } diff --git a/src/Microsoft.PowerShell.CoreCLR.Eventing/Microsoft.PowerShell.CoreCLR.Eventing.csproj b/src/Microsoft.PowerShell.CoreCLR.Eventing/Microsoft.PowerShell.CoreCLR.Eventing.csproj index 3c00ae295b8..be5619b5dda 100644 --- a/src/Microsoft.PowerShell.CoreCLR.Eventing/Microsoft.PowerShell.CoreCLR.Eventing.csproj +++ b/src/Microsoft.PowerShell.CoreCLR.Eventing/Microsoft.PowerShell.CoreCLR.Eventing.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj b/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj index 749e916eab5..c6e8bf10326 100644 --- a/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj +++ b/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj @@ -19,9 +19,9 @@ - - - + + + - + diff --git a/src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj b/src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj index 084ba8e2ffe..b57908f94a6 100644 --- a/src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj +++ b/src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Modules/PSGalleryModules.csproj b/src/Modules/PSGalleryModules.csproj index 80a1b7e2022..0dd1a39c68f 100644 --- a/src/Modules/PSGalleryModules.csproj +++ b/src/Modules/PSGalleryModules.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/System.Management.Automation/System.Management.Automation.csproj b/src/System.Management.Automation/System.Management.Automation.csproj index 1568b76ee0e..a13051797df 100644 --- a/src/System.Management.Automation/System.Management.Automation.csproj +++ b/src/System.Management.Automation/System.Management.Automation.csproj @@ -34,19 +34,19 @@ - - - - + + + + - + - - - + + + - - + + diff --git a/src/System.Management.Automation/engine/Utils.cs b/src/System.Management.Automation/engine/Utils.cs index e31cf2f81ad..1ad23a40cc6 100644 --- a/src/System.Management.Automation/engine/Utils.cs +++ b/src/System.Management.Automation/engine/Utils.cs @@ -1256,7 +1256,8 @@ internal static bool PathIsDevicePath(string path) #if UNIX return false; #else - return path.StartsWith(@"\\.\") || path.StartsWith(@"\\?\"); + // device paths can be network paths, we would need windows to parse it. + return path.StartsWith(@"\\.\") || path.StartsWith(@"\\?\") || path.StartsWith(@"\\;"); #endif } @@ -1523,6 +1524,23 @@ internal static string DisplayHumanReadableFileSize(long bytes) _ => $"0 Bytes", }; } + + /// + /// Returns true if the current session is restricted (JEA or similar sessions) + /// + /// ExecutionContext. + /// True if the session is restricted. + internal static bool IsSessionRestricted(ExecutionContext context) + { + CmdletInfo cmdletInfo = context.SessionState.InvokeCommand.GetCmdlet("Microsoft.PowerShell.Core\\Import-Module"); + // if import-module is visible, then the session is not restricted, + // because the user can load arbitrary code. + if (cmdletInfo != null && cmdletInfo.Visibility == SessionStateEntryVisibility.Public) + { + return false; + } + return true; + } } } diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index af79758dcb3..1b451637a5d 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -255,6 +255,17 @@ protected override void BeginProcessing() /// protected override void ProcessRecord() { +#if !UNIX + string fileSystemPath = SessionState.Path.GetUnresolvedProviderPathFromPSPath(this.Name); + string normalizedName = FileSystemProvider.NormalizePath(fileSystemPath); + // In a restricted session, do not allow help on network paths or device paths, because device paths can be used to bypass the restrictions. + if (Utils.IsSessionRestricted(this.Context) && (FileSystemProvider.PathIsNetworkPath(normalizedName) || Utils.PathIsDevicePath(normalizedName))) { + Exception e = new ArgumentException(HelpErrors.NoNetworkCommands, "Name"); + ErrorRecord errorRecord = new ErrorRecord(e, "CommandNameNotAllowed", ErrorCategory.InvalidArgument, null); + this.ThrowTerminatingError(errorRecord); + } +#endif + HelpSystem helpSystem = this.Context.HelpSystem; try { @@ -504,7 +515,7 @@ private void GetAndWriteParameterInfo(HelpInfo helpInfo) } /// - /// Validates input parameters. + /// Validates input parameters. /// /// Category specified by the user. /// diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 7236a6f3891..9337b466805 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -105,7 +105,7 @@ public FileSystemProvider() /// /// The path with all / normalized to \ /// - private static string NormalizePath(string path) + internal static string NormalizePath(string path) { return GetCorrectCasedPath(path.Replace(StringLiterals.AlternatePathSeparator, StringLiterals.DefaultPathSeparator)); } diff --git a/src/System.Management.Automation/resources/HelpErrors.resx b/src/System.Management.Automation/resources/HelpErrors.resx index 851e457cf27..27634de2995 100644 --- a/src/System.Management.Automation/resources/HelpErrors.resx +++ b/src/System.Management.Automation/resources/HelpErrors.resx @@ -187,4 +187,7 @@ To update these Help topics, start PowerShell by using the "Run as Administrator ForwardHelpTargetName cannot refer to the function itself. + + Cannot get help from a network location when in a restricted session. + diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index c9de4236960..cd356071b48 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -1966,6 +1966,19 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" { $result.Headers.Authorization | Should -Match "^$AuthType " } + + It 'Invoke-WebRequest redacts Authorization header in ErrorRecord' { + $token = ConvertTo-SecureString -AsPlainText 'secret' + try { + Invoke-WebRequest -Authentication Bearer -Token $token -Uri https://localhost:443 + } + catch { + $errorText = Get-Error $_ | Out-String + } + + ($errorText | Select-String 'secret').Matches | Should -BeNullOrEmpty + ($errorText | Select-String '\*cret').Matches | Should -Not -BeNullOrEmpty + } } Context "Invoke-WebRequest -SslProtocol Test" { @@ -3922,6 +3935,19 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" { $result.Headers.Authorization | Should -Match "^$AuthType " } + + It 'Invoke-RestMethod redacts Authorization header in ErrorRecord' { + $token = ConvertTo-SecureString -AsPlainText 'secret' + try { + Invoke-RestMethod -Authentication Bearer -Token $token -Uri https://localhost:443 + } + catch { + $errorText = Get-Error $_ | Out-String + } + + ($errorText | Select-String 'secret').Matches | Should -BeNullOrEmpty + ($errorText | Select-String '\*cret').Matches | Should -Not -BeNullOrEmpty + } } Context "Invoke-RestMethod -SslProtocol Test" { @@ -4600,3 +4626,34 @@ Describe 'Invoke-WebRequest and Invoke-RestMethod support OperationTimeoutSecond RunWithNetworkTimeout -Command Invoke-RestMethod -Uri $uri -OperationTimeoutSeconds 2 -WillTimeout -Arguments '-SkipCertificateCheck' } } + + +Describe "Invoke-RestMethod should run in the default synchronization context (threadpool)" -Tag "CI" { + BeforeAll { + $oldProgress = $ProgressPreference + $ProgressPreference = 'SilentlyContinue' + $WebListener = Start-WebListener + } + + AfterAll { + $ProgressPreference = $oldProgress + } + + It "Invoke-RestMethod works after constructing a WindowsForm object" -Skip:(!$IsWindows) { + $env:URI_TO_TEST = Get-WebListenerUrl -Test 'Get' + $irmResult = $null + try { + $pwsh = Join-Path $PSHOME "pwsh" + $irmResult = & $pwsh -NoProfile { + Add-Type -AssemblyName System.Windows.Forms + $null = New-Object System.Windows.Forms.Form + Invoke-RestMethod $env:URI_TO_TEST + } + } finally { + $env:URI_TO_TEST = $null + } + + # Simply making it this far is good enough to ensure we didn't hit a deadlock + $irmResult | Should -Not -BeNullOrEmpty + } +} diff --git a/test/powershell/Modules/PowerShellGet/PowerShellGet.Tests.ps1 b/test/powershell/Modules/PowerShellGet/PowerShellGet.Tests.ps1 index fb5d632765c..1fd935b22dd 100644 --- a/test/powershell/Modules/PowerShellGet/PowerShellGet.Tests.ps1 +++ b/test/powershell/Modules/PowerShellGet/PowerShellGet.Tests.ps1 @@ -145,15 +145,10 @@ Describe "PowerShellGet - Module tests" -tags "Feature" { It "Should install a module correctly to the required location with default CurrentUser scope" { Install-Module -Name $TestModule -Repository $RepositoryName - $installedModuleInfo = Get-InstalledModule -Name $TestModule - - $installedModuleInfo | Should -Not -BeNullOrEmpty - $installedModuleInfo.Name | Should -Be $TestModule - $installedModuleInfo.InstalledLocation.StartsWith($script:MyDocumentsModulesPath, [System.StringComparison]::OrdinalIgnoreCase) | Should -BeTrue - - $module = Get-Module $TestModule -ListAvailable + $module = Get-Module -Name $TestModule -ListAvailable + $module | Should -Not -BeNullOrEmpty $module.Name | Should -Be $TestModule - $module.ModuleBase | Should -Be $installedModuleInfo.InstalledLocation + $module.ModuleBase.StartsWith($script:MyDocumentsModulesPath, [System.StringComparison]::OrdinalIgnoreCase) | Should -BeTrue } AfterAll { diff --git a/test/powershell/engine/Help/HelpSystem.OnlineHelp.Tests.ps1 b/test/powershell/engine/Help/HelpSystem.OnlineHelp.Tests.ps1 index b56effc8626..3e06c51f6cd 100644 --- a/test/powershell/engine/Help/HelpSystem.OnlineHelp.Tests.ps1 +++ b/test/powershell/engine/Help/HelpSystem.OnlineHelp.Tests.ps1 @@ -1,6 +1,8 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. +Import-Module HelpersCommon + Describe 'Online help tests for PowerShell Cmdlets' -Tags "Feature" { # The csv files (V2Cmdlets.csv and V3Cmdlets.csv) contain a list of cmdlets and expected HelpURIs. @@ -61,3 +63,18 @@ Describe 'Get-Help -Online is not supported on Nano Server and IoT' -Tags "CI" { { Get-Help Get-Help -Online } | Should -Throw -ErrorId "InvalidOperation,Microsoft.PowerShell.Commands.GetHelpCommand" } } + +Describe 'Get-Help should throw on network paths' -Tags "CI" { + BeforeAll { + $script:skipTest = -not $IsWindows + } + + It "Get-Help should throw not on " -Skip:$skipTest -TestCases (Get-HelpNetworkTestCases -PositiveCases) { + param( + $Command, + $ExpectedError + ) + + { Get-Help -Name $Command } | Should -Not -Throw + } +} diff --git a/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 b/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 index 8efe61de357..43f92cef295 100644 --- a/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 +++ b/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 @@ -106,7 +106,6 @@ Describe "JEA session Transcript script test" -Tag @("Feature", 'RequireAdminOnW Unregister-PSSessionConfiguration -Name JEA -Force -ErrorAction SilentlyContinue } } - } Describe "JEA session Get-Help test" -Tag @("CI", 'RequireAdminOnWindows') { @@ -155,6 +154,34 @@ Describe "JEA session Get-Help test" -Tag @("CI", 'RequireAdminOnWindows') { Remove-Item $RoleCapDirectory -Recurse -Force -ErrorAction SilentlyContinue } } + + It "Get-Help should throw on " -TestCases (Get-HelpNetworkTestCases) { + param( + $Command, + $ExpectedError + ) + + [string] $RoleCapDirectory = (New-Item -Path "$TestDrive\RoleCapability" -ItemType Directory -Force).FullName + [string] $PSSessionConfigFile = "$RoleCapDirectory\TestConfig.pssc" + $configurationName = 'RestrictedWithNoGetHelpProxy' + try + { + New-PSSessionConfigurationFile -Path $PSSessionConfigFile ` + -SessionType Empty ` + -LanguageMode NoLanguage ` + -ModulesToImport 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Core' ` + -VisibleCmdlets 'Get-command', 'measure-object', 'select-object', 'enter-pssession', 'get-formatdata', 'out-default', 'out-file', 'exit-pssession', 'get-help' + Register-PSSessionConfiguration -Name $configurationName -Path $PSSessionConfigFile -Force -ErrorAction SilentlyContinue + $scriptBlock = [scriptblock]::Create("Get-Help -Name $Command") + {Invoke-Command -ConfigurationName $configurationName -ComputerName localhost -ScriptBlock $scriptBlock -ErrorAction Stop} | + Should -Throw -ErrorId $ExpectedError + } + finally + { + Unregister-PSSessionConfiguration -Name $configurationName -Force -ErrorAction SilentlyContinue + Remove-Item $RoleCapDirectory -Recurse -Force -ErrorAction SilentlyContinue + } + } } Describe "Remoting loopback tests" -Tags @('CI', 'RequireAdminOnWindows') { @@ -358,6 +385,7 @@ Describe "Remoting loopback tests" -Tags @('CI', 'RequireAdminOnWindows') { $session = New-RemoteSession -ConfigurationName $endPoint try { $result = Invoke-Command -Session $session -ScriptBlock { $Host.Version } + Write-Verbose "host version: $result" -Verbose $result | Should -Be $PSVersionTable.PSVersion } finally { diff --git a/test/tools/Modules/HelpersCommon/HelpersCommon.psd1 b/test/tools/Modules/HelpersCommon/HelpersCommon.psd1 index 897d41c251b..dd7cd7a52aa 100644 --- a/test/tools/Modules/HelpersCommon/HelpersCommon.psd1 +++ b/test/tools/Modules/HelpersCommon/HelpersCommon.psd1 @@ -48,6 +48,7 @@ FunctionsToExport = @( 'Test-PSDefaultParameterValue' 'Push-DefaultParameterValueStack' 'Pop-DefaultParameterValueStack' + 'Get-HelpNetworkTestCases' ) CmdletsToExport= @() diff --git a/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 b/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 index aefd2893a21..50d6a2e668b 100644 --- a/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 +++ b/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 @@ -533,3 +533,87 @@ function Pop-DefaultParameterValueStack { return $false } } + +function Get-HelpNetworkTestCases +{ + param( + [switch] + $PositiveCases + ) + # .NET doesn't consider these path rooted and we won't go to the network: + # \\? + # \\. + # \?? + + # Command discovery does not follow symlinks to network locations for module qualified paths + $networkBlockedError = "CommandNameNotAllowed,Microsoft.PowerShell.Commands.GetHelpCommand" + $scriptBlockedError = "ScriptsNotAllowed" + + $formats = @( + '//{0}/share/{1}' + '\\{0}\share\{1}' + '//{0}\share/{1}' + 'Microsoft.PowerShell.Core\filesystem:://{0}/share/{1}' + ) + + if (!$PositiveCases) { + $formats += 'filesystem:://{0}/share/{1}' + } + + $moduleQualifiedCommand = 'test.dll\fakecommand' + $lanManFormat = @( + '//;LanmanRedirector/{0}/share/{1}' + ) + + $hosts = @( + 'fakehost' + 'fakehost.pstest' + ) + + $commands = @( + 'test.ps1' + 'test.dll' + $moduleQualifiedCommand + ) + + $variants = @() + $cases = @() + foreach($command in $commands) { + $hostName = $hosts[0] + $format = $formats[0] + $cases += @{ + Command = $format -f $hostName, $command + ExpectedError = $networkBlockedError + } + } + + foreach($hostName in $hosts) { + # chose the format with backslashes(\) to match the host with blackslashes + $format = $formats[1] + $command = $commands[0] + $cases += @{ + Command = $format -f $hostName, $command + ExpectedError = $networkBlockedError + } + } + foreach($format in $formats) { + $hostName = $hosts[0] + $command = $commands[0] + $cases += @{ + Command = $format -f $hostName, $command + ExpectedError = $networkBlockedError + } + } + + foreach($format in $lanManFormat) { + $hostName = $hosts[0] + $command = $moduleQualifiedCommand + $cases += @{ + Command = $format -f $hostName, $command + ExpectedError = $scriptBlockedError + } + } + + return $cases | Sort-Object -Property ExpectedError, Command -Unique +} + diff --git a/test/tools/TestService/TestService.csproj b/test/tools/TestService/TestService.csproj index ed5011fdc19..cca4de650bc 100644 --- a/test/tools/TestService/TestService.csproj +++ b/test/tools/TestService/TestService.csproj @@ -13,7 +13,7 @@ - + diff --git a/test/tools/WebListener/WebListener.csproj b/test/tools/WebListener/WebListener.csproj index 3d9d5a4eda6..b742b0f6566 100644 --- a/test/tools/WebListener/WebListener.csproj +++ b/test/tools/WebListener/WebListener.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/tools/cgmanifest.json b/tools/cgmanifest.json index 8b92f890ec2..87058bbd907 100644 --- a/tools/cgmanifest.json +++ b/tools/cgmanifest.json @@ -1,5 +1,4 @@ { - "$schema": "https://json.schemastore.org/component-detection-manifest.json", "Registrations": [ { "Component": { @@ -136,7 +135,7 @@ "Type": "nuget", "Nuget": { "Name": "Microsoft.Management.Infrastructure.Runtime.Unix", - "Version": "2.0.0" + "Version": "3.0.0" } }, "DevelopmentDependency": false @@ -146,7 +145,7 @@ "Type": "nuget", "Nuget": { "Name": "Microsoft.Management.Infrastructure.Runtime.Win", - "Version": "2.0.0" + "Version": "3.0.0" } }, "DevelopmentDependency": true @@ -156,7 +155,7 @@ "Type": "nuget", "Nuget": { "Name": "Microsoft.Management.Infrastructure", - "Version": "2.0.0" + "Version": "3.0.0" } }, "DevelopmentDependency": false @@ -176,7 +175,7 @@ "Type": "nuget", "Nuget": { "Name": "Microsoft.PowerShell.Native", - "Version": "7.3.2" + "Version": "7.4.0" } }, "DevelopmentDependency": false @@ -831,5 +830,6 @@ }, "DevelopmentDependency": false } - ] + ], + "$schema": "https://json.schemastore.org/component-detection-manifest.json" } diff --git a/tools/metadata.json b/tools/metadata.json index 6d85770f1d9..67b3080e0d7 100644 --- a/tools/metadata.json +++ b/tools/metadata.json @@ -1,10 +1,10 @@ { - "StableReleaseTag": "v7.3.6", + "StableReleaseTag": "v7.4.0", "PreviewReleaseTag": "v7.4.0-preview.4", "ServicingReleaseTag": "v7.0.13", - "ReleaseTag": "v7.3.6", + "ReleaseTag": "v7.4.0", "LTSReleaseTag" : ["v7.2.13"], "NextReleaseTag": "v7.4.0-preview.5", - "LTSRelease": { "Latest": false, "Package": false }, - "StableRelease": { "Latest": false, "Package": false } + "LTSRelease": { "Latest": true, "Package": true }, + "StableRelease": { "Latest": true, "Package": true } } diff --git a/tools/packaging/projects/reference/System.Management.Automation/System.Management.Automation.csproj b/tools/packaging/projects/reference/System.Management.Automation/System.Management.Automation.csproj index 4b756e722aa..910a5ae576b 100644 --- a/tools/packaging/projects/reference/System.Management.Automation/System.Management.Automation.csproj +++ b/tools/packaging/projects/reference/System.Management.Automation/System.Management.Automation.csproj @@ -8,7 +8,7 @@ 11.0 - + diff --git a/tools/releaseBuild/azureDevOps/compliance.yml b/tools/releaseBuild/azureDevOps/compliance.yml index 57c29194de6..3624f1e1081 100644 --- a/tools/releaseBuild/azureDevOps/compliance.yml +++ b/tools/releaseBuild/azureDevOps/compliance.yml @@ -19,6 +19,12 @@ resources: name: PowerShell/compliance ref: master +parameters: +- name: InternalSDKBlobURL + displayName: URL to the blob havibg internal .NET SDK + type: string + default: ' ' + variables: - name: DOTNET_CLI_TELEMETRY_OPTOUT value: 1 @@ -33,6 +39,9 @@ variables: # Defines the variables CgPat, CgOrganization, and CgProject - group: 'ComponentGovernance' - group: 'PoolNames' + - name: __DOTNET_RUNTIME_FEED + value: ${{ parameters.InternalSDKBlobURL }} + stages: - stage: compliance diff --git a/tools/releaseBuild/azureDevOps/releaseBuild.yml b/tools/releaseBuild/azureDevOps/releaseBuild.yml index dd576e1860d..3be90bbefbc 100644 --- a/tools/releaseBuild/azureDevOps/releaseBuild.yml +++ b/tools/releaseBuild/azureDevOps/releaseBuild.yml @@ -18,6 +18,10 @@ parameters: - true - false default: false + - name: InternalSDKBlobURL + displayName: URL to the blob having internal .NET SDK + type: string + default: ' ' resources: repositories: @@ -54,6 +58,8 @@ variables: - name: BUILDSECMON_OPT_IN value: true - group: PoolNames + - name: __DOTNET_RUNTIME_FEED + value: ${{ parameters.InternalSDKBlobURL }} stages: - stage: prep diff --git a/tools/releaseBuild/azureDevOps/releasePipeline.yml b/tools/releaseBuild/azureDevOps/releasePipeline.yml index fb6b8d5d956..21abb20e52c 100644 --- a/tools/releaseBuild/azureDevOps/releasePipeline.yml +++ b/tools/releaseBuild/azureDevOps/releasePipeline.yml @@ -13,6 +13,10 @@ parameters: displayName: Skip nuget publishing. Used in testing publishing stage. default: false type: boolean + - name: InternalSDKBlobURL + displayName: URL to the blob having internal .NET SDK + type: string + default: ' ' resources: pipelines: @@ -48,6 +52,8 @@ variables: value: true - group: ReleasePipelineSecrets - group: PipelineExecutionPats + - name: __DOTNET_RUNTIME_FEED + value: ${{ parameters.InternalSDKBlobURL }} stages: - stage: MSIXBundle @@ -290,8 +296,8 @@ stages: Update and merge the changelog for the release. This step is required for creating GitHub draft release. -- stage: GitHubDraftRelease - displayName: Create GitHub draft release +- stage: BlobPublic + displayName: Make Blob Public # do not include stages that are likely to fail in dependency as there is no way to force deploy. dependsOn: UpdateChangeLog @@ -314,6 +320,38 @@ stages: steps: - template: templates/release-MakeContainerPublic.yml + - template: templates/release/approvalJob.yml + parameters: + displayName: Copy Global tool packages to PSInfra storage + jobName: CopyBlobApproval + instructions: | + Approval for Copy global tool packages to PSInfra storage + + - job: PSInfraBlobPublic + displayName: Copy global tools to PSInfra storage + dependsOn: CopyBlobApproval + + pool: + name: PowerShell1ES + demands: + - ImageOverride -equals PSMMS2019-Secure + + variables: + - group: 'PSInfraStorage' + + steps: + - template: templates/release-CopyGlobalTools.yml + parameters: + sourceContainerName: 'tool-private' + destinationContainerName: 'tool' + sourceStorageAccountName: '$(GlobalToolStorageAccount)' + destinationStorageAccountName: '$(PSInfraStorageAccount)' + blobPrefix: '$(Version)' + +- stage: GitHubTasks + displayName: GitHub tasks + dependsOn: BlobPublic + jobs: - job: GitHubDraft displayName: Create GitHub Draft release @@ -326,28 +364,24 @@ stages: - group: 'Azure Blob variable group' - group: 'AzDevOpsArtifacts' - group: ReleasePipelineSecrets - dependsOn: AzureBlobPublic steps: - template: templates/release-CreateGitHubDraft.yml -- stage: GitHubManualTasks - displayName: GitHub manual tasks - dependsOn: GitHubDraftRelease - jobs: - deployment: PushTag + dependsOn: GitHubDraft displayName: Push Git Tag pool : server environment: PSReleasePushTag - deployment: MakeDraftPublic + dependsOn: PushTag displayName: Make GitHub Draft public pool : server environment: PSReleaseDraftPublic - dependsOn: PushTag - stage: PublishPackages displayName: Publish packages - dependsOn: GitHubManualTasks + dependsOn: GitHubTasks jobs: - job: PublishNuget @@ -405,7 +439,7 @@ stages: - stage: ReleaseDocker displayName: Release Docker dependsOn: - - GitHubManualTasks + - GitHubTasks jobs: - deployment: ReleaseDocker displayName: Release Docker @@ -504,7 +538,7 @@ stages: Notify the PM team to start the process of releasing to MU. - stage: UpdateDotnetDocker - dependsOn: GitHubManualTasks + dependsOn: GitHubTasks displayName: Update DotNet SDK Docker images jobs: - template: templates/release/approvalJob.yml @@ -519,7 +553,7 @@ stages: 4. create PR targeting nightly branch - stage: UpdateWinGet - dependsOn: GitHubManualTasks + dependsOn: GitHubTasks displayName: Add manifest entry to winget jobs: - template: templates/release/approvalJob.yml @@ -530,7 +564,7 @@ stages: This is typically done by the community 1-2 days after the release. - stage: PublishMsix - dependsOn: GitHubManualTasks + dependsOn: GitHubTasks displayName: Publish MSIX to store jobs: - template: templates/release/approvalJob.yml @@ -541,7 +575,7 @@ stages: Ask Steve to release MSIX bundle package to Store - stage: BuildInfoJson - dependsOn: GitHubManualTasks + dependsOn: GitHubTasks displayName: Upload BuildInfoJson jobs: - deployment: UploadJson @@ -562,7 +596,7 @@ stages: - template: templates/release-BuildJson.yml - stage: ReleaseVPack - dependsOn: GitHubManualTasks + dependsOn: GitHubTasks displayName: Release VPack jobs: - job: KickoffvPack @@ -611,7 +645,7 @@ stages: } - stage: ReleaseDeps - dependsOn: GitHubManualTasks + dependsOn: GitHubTasks displayName: Update pwsh.deps.json links jobs: - template: templates/release-UpdateDepsJson.yml diff --git a/tools/releaseBuild/azureDevOps/templates/compliance/apiscan.yml b/tools/releaseBuild/azureDevOps/templates/compliance/apiscan.yml index ea5efe0b224..232fc3fd374 100644 --- a/tools/releaseBuild/azureDevOps/templates/compliance/apiscan.yml +++ b/tools/releaseBuild/azureDevOps/templates/compliance/apiscan.yml @@ -19,6 +19,7 @@ jobs: - group: DotNetPrivateBuildAccess - group: Azure Blob variable group - group: ReleasePipelineSecrets + - group: AzDevOpsArtifacts pool: name: PowerShell1ES @@ -35,6 +36,10 @@ jobs: CreateJson: yes UseJson: no + - template: ../insert-nuget-config-azfeed.yml + parameters: + repoRoot: '$(Build.SourcesDirectory)' + - pwsh: | Import-Module .\build.psm1 -force Start-PSBootstrap @@ -42,7 +47,6 @@ jobs: retryCountOnTaskFailure: 2 displayName: 'Bootstrap' env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - pwsh: | diff --git a/tools/releaseBuild/azureDevOps/templates/linux-packaging.yml b/tools/releaseBuild/azureDevOps/templates/linux-packaging.yml index 4439ded9f26..59db37c64ac 100644 --- a/tools/releaseBuild/azureDevOps/templates/linux-packaging.yml +++ b/tools/releaseBuild/azureDevOps/templates/linux-packaging.yml @@ -253,7 +253,6 @@ jobs: condition: and(succeeded(), ne(variables['SkipBuild'], 'true')) workingDirectory: $(PowerShellRoot) env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - powershell: | diff --git a/tools/releaseBuild/azureDevOps/templates/linux.yml b/tools/releaseBuild/azureDevOps/templates/linux.yml index a65045ce323..bb343bed54e 100644 --- a/tools/releaseBuild/azureDevOps/templates/linux.yml +++ b/tools/releaseBuild/azureDevOps/templates/linux.yml @@ -62,7 +62,6 @@ jobs: condition: and(succeeded(), ne(variables['SkipBuild'], 'true')) workingDirectory: $(PowerShellRoot) env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - pwsh: | diff --git a/tools/releaseBuild/azureDevOps/templates/mac-package-build.yml b/tools/releaseBuild/azureDevOps/templates/mac-package-build.yml index f3801deaa9e..c853a21ef37 100644 --- a/tools/releaseBuild/azureDevOps/templates/mac-package-build.yml +++ b/tools/releaseBuild/azureDevOps/templates/mac-package-build.yml @@ -119,7 +119,6 @@ jobs: } displayName: 'Bootstrap VM' env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - pwsh: | @@ -133,7 +132,6 @@ jobs: } displayName: 'Package' env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 diff --git a/tools/releaseBuild/azureDevOps/templates/mac.yml b/tools/releaseBuild/azureDevOps/templates/mac.yml index f13c00ef421..892064fbbba 100644 --- a/tools/releaseBuild/azureDevOps/templates/mac.yml +++ b/tools/releaseBuild/azureDevOps/templates/mac.yml @@ -43,7 +43,6 @@ jobs: tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 -location $(PowerShellRoot) -BootStrap displayName: 'Bootstrap VM' env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - template: /tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml @@ -58,7 +57,6 @@ jobs: $env:AzDevOpsFeedPAT2 = $null displayName: 'Build' env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 diff --git a/tools/releaseBuild/azureDevOps/templates/nuget-pkg-sbom.yml b/tools/releaseBuild/azureDevOps/templates/nuget-pkg-sbom.yml index f0a033fd9e4..276ab1511cd 100644 --- a/tools/releaseBuild/azureDevOps/templates/nuget-pkg-sbom.yml +++ b/tools/releaseBuild/azureDevOps/templates/nuget-pkg-sbom.yml @@ -20,6 +20,19 @@ parameters: steps: +- pwsh: | + $configPath = "$(REPOROOT)/nuget.config" + Import-Module '$(REPOROOT)/build.psm1' -Force + New-NugetConfigFile -NugetFeedUrl $(PSInternalNugetFeed) -UserName $(PSInternalNugetFeedUserName) -ClearTextPAT $(PSInternalNugetFeedPAT) -FeedName AzDevOpsFeed -Destination "$(REPOROOT)" + + if(-not (Test-Path $configPath)) + { + throw "nuget.config is not created" + } + Get-Content $configPath | Write-Verbose -Verbose + displayName: 'Add nuget.config for Azure DevOps feed for packages' + condition: and(succeededOrFailed(), ne(variables['PSInternalNugetFeed'], '')) + - pwsh: | Import-Module "$env:REPOROOT/build.psm1" -Force Start-PSBootstrap @@ -81,6 +94,8 @@ steps: Write-Host "##$vstsCommandString" displayName: Build reference assemblies + env: + __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - ${{ each value in parameters.ListOfFiles }}: - pwsh: | diff --git a/tools/releaseBuild/azureDevOps/templates/nuget.yml b/tools/releaseBuild/azureDevOps/templates/nuget.yml index 247e91013a3..22f791bf0eb 100644 --- a/tools/releaseBuild/azureDevOps/templates/nuget.yml +++ b/tools/releaseBuild/azureDevOps/templates/nuget.yml @@ -60,7 +60,6 @@ jobs: Start-PSBootStrap -Verbose displayName: Bootstrap env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - task: DownloadBuildArtifacts@0 @@ -280,7 +279,7 @@ jobs: azureSubscription: '$(GlobalToolSubscription)' Destination: AzureBlob storage: '$(GlobalToolStorageAccount)' - ContainerName: 'tool' + ContainerName: 'tool-private' blobPrefix: '$(Version)' condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) retryCountOnTaskFailure: 2 diff --git a/tools/releaseBuild/azureDevOps/templates/release-CopyGlobalTools.yml b/tools/releaseBuild/azureDevOps/templates/release-CopyGlobalTools.yml new file mode 100644 index 00000000000..7c9306496ed --- /dev/null +++ b/tools/releaseBuild/azureDevOps/templates/release-CopyGlobalTools.yml @@ -0,0 +1,56 @@ +parameters: +- name: sourceContainerName + type: string + default: 'source-container' + +- name: destinationContainerName + type: string + default: 'destination-container' + +- name: sourceStorageAccountName + type: string + default: 'source-storage-account' + +- name: destinationStorageAccountName + type: string + default: 'destination-storage-account' + +- name: blobPrefix + type: string + default: '$(Version)' + +steps: +- template: release-SetReleaseTagAndContainerName.yml + +- pwsh: | + Import-module '$(BUILD.SOURCESDIRECTORY)/build.psm1' + Install-AzCopy + displayName: Install AzCopy + retryCountOnTaskFailure: 2 + +- pwsh: | + Import-module '$(BUILD.SOURCESDIRECTORY)/build.psm1' + $azcopy = Find-AzCopy + Write-Verbose -Verbose "Found AzCopy: $azcopy" + + $sourceContainerName = "${{ parameters.sourceContainerName }}" + $destinationContainerName = "${{ parameters.destinationContainerName }}" + $sourceStorageAccountName = "${{ parameters.sourceStorageAccountName }}" + $destinationStorageAccountName = "${{ parameters.destinationStorageAccountName }}" + $blobPrefix = "${{ parameters.blobPrefix }}" + + $sourceBlobUrl = "https://${sourceStorageAccountName}.blob.core.windows.net/${sourceContainerName}/${blobPrefix}" + Write-Verbose -Verbose "Source blob url: $sourceBlobUrl" + $destinationBlobUrl = "https://${destinationStorageAccountName}.blob.core.windows.net/${destinationContainerName}" + Write-Verbose -Verbose "Destination blob url: $destinationBlobUrl" + + & $azcopy cp $sourceBlobUrl $destinationBlobUrl --recursive + + $packagesPath = Get-ChildItem -Path $(System.ArtifactsDirectory)\*.deb -Recurse -File | Select-Object -First 1 -ExpandProperty DirectoryName + Write-Host "sending -- vso[task.setvariable variable=PackagesRoot]$packagesPath" + Write-Host "##vso[task.setvariable variable=PackagesRoot]$packagesPath" + + displayName: Copy blobs + retryCountOnTaskFailure: 2 + env: + AZCOPY_AUTO_LOGIN_TYPE: MSI diff --git a/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml b/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml index cc6af2d8526..8591791de0e 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml @@ -61,7 +61,6 @@ jobs: displayName: Install .NET env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - pwsh: | @@ -85,7 +84,6 @@ jobs: displayName: Install global tool env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - pwsh: | @@ -148,5 +146,4 @@ jobs: } displayName: Basic validation env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) diff --git a/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml b/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml index 2279c3325e1..880967a37a7 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml @@ -97,7 +97,6 @@ jobs: displayName: Install .NET env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - pwsh: | @@ -136,7 +135,6 @@ jobs: displayName: Restore and execute tests env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - task: PublishTestResults@2 diff --git a/tools/releaseBuild/azureDevOps/templates/release-SetReleaseTagAndContainerName.yml b/tools/releaseBuild/azureDevOps/templates/release-SetReleaseTagAndContainerName.yml index 26229325b82..7e88624b45c 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-SetReleaseTagAndContainerName.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-SetReleaseTagAndContainerName.yml @@ -18,4 +18,9 @@ steps: $vstsCommandString = "vso[task.setvariable variable=AzureVersion]$azureVersion" Write-Host "sending " + $vstsCommandString Write-Host "##$vstsCommandString" + + $version = '$(ReleaseTag)'.ToLowerInvariant().Substring(1) + $vstsCommandString = "vso[task.setvariable variable=Version]$version" + Write-Host ("sending " + $vstsCommandString) + Write-Host "##$vstsCommandString" displayName: Set container name diff --git a/tools/releaseBuild/azureDevOps/templates/release-ValidateFxdPackage.yml b/tools/releaseBuild/azureDevOps/templates/release-ValidateFxdPackage.yml index 1aa88af9143..7f2c816a20f 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-ValidateFxdPackage.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-ValidateFxdPackage.yml @@ -38,7 +38,6 @@ jobs: Write-Verbose -Message "Installing .NET SDK completed." -Verbose displayName: Install .NET env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - pwsh: | diff --git a/tools/releaseBuild/azureDevOps/templates/testartifacts.yml b/tools/releaseBuild/azureDevOps/templates/testartifacts.yml index 09f5c5bce5d..43c09236da9 100644 --- a/tools/releaseBuild/azureDevOps/templates/testartifacts.yml +++ b/tools/releaseBuild/azureDevOps/templates/testartifacts.yml @@ -25,7 +25,6 @@ jobs: Start-PSBootstrap displayName: Bootstrap env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - pwsh: | @@ -86,7 +85,6 @@ jobs: Start-PSBootstrap displayName: Bootstrap env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - pwsh: | diff --git a/tools/releaseBuild/azureDevOps/templates/windows-hosted-build.yml b/tools/releaseBuild/azureDevOps/templates/windows-hosted-build.yml index b533061178f..4b36f6f396e 100644 --- a/tools/releaseBuild/azureDevOps/templates/windows-hosted-build.yml +++ b/tools/releaseBuild/azureDevOps/templates/windows-hosted-build.yml @@ -66,7 +66,6 @@ jobs: tools/releaseBuild/Images/microsoft_powershell_windowsservercore/PowerShellPackage.ps1 -location '$(PowerShellRoot)' -destination '$(Build.ArtifactStagingDirectory)/Symbols_$(Architecture)' -Runtime $runtime -ReleaseTag '$(ReleaseTagVar)' -Symbols @params displayName: 'Build Windows Universal - $(Architecture)-$(BuildConfiguration) Symbols zip' env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - pwsh: | diff --git a/tools/releaseBuild/azureDevOps/templates/windows-packaging.yml b/tools/releaseBuild/azureDevOps/templates/windows-packaging.yml index 91a5c15f112..4d1273d135d 100644 --- a/tools/releaseBuild/azureDevOps/templates/windows-packaging.yml +++ b/tools/releaseBuild/azureDevOps/templates/windows-packaging.yml @@ -259,7 +259,6 @@ jobs: $(PowerShellRoot)/tools/releaseBuild/Images/microsoft_powershell_windowsservercore/PowerShellPackage.ps1 -BuildZip $signedPkg -location '$(PowerShellRoot)' -destination '$(System.ArtifactsDirectory)\pkgSigned' -Runtime $runtime -ReleaseTag '$(ReleaseTagVar)' @params displayName: 'Build Windows Universal - $(Architecture) Package' env: - __DOTNET_RUNTIME_FEED: $(RUNTIME_SOURCEFEED) __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) - pwsh: |
Bump .NET 8 to 8.0.0 RTM build
PSResourceGet
1.0.1
Microsoft.PowerShell.Native
v7.4.0