From cedb0589b63afa57baad5494310c34ddf51d1f95 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 4 Apr 2024 18:21:42 -0400 Subject: [PATCH 01/18] [release/v7.4.2] Fix Get-Error serialization of array values (#21085) (#21419) --- .../PowerShellCore_format_ps1xml.cs | 21 +++- .../Get-Error.Tests.ps1 | 107 ++++++++++++++++++ 2 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Core/Get-Error.Tests.ps1 diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index 182af55d641..8bc6b1971cf 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -946,14 +946,29 @@ private static IEnumerable ViewsOf_System_Management_Autom $isFirstElement = $true foreach ($value in $prop.Value) { $null = $output.Append($newline) - if (!$isFirstElement) { - $null = $output.Append($newline) + $valueIndent = ' ' * ($newIndent + 2) + + if ($value -is [Type]) { + # Just show the typename instead of it as an object + $null = $output.Append(""${prefix}${valueIndent}[$($value.ToString())]"") + } + elseif ($value -is [string] -or $value.GetType().IsPrimitive) { + $null = $output.Append(""${prefix}${valueIndent}${value}"") + } + else { + if (!$isFirstElement) { + $null = $output.Append($newline) + } + $null = $output.Append((Show-ErrorRecord $value $newIndent ($depth + 1))) } - $null = $output.Append((Show-ErrorRecord $value $newIndent ($depth + 1))) $isFirstElement = $false } } } + elseif ($prop.Value -is [Type]) { + # Just show the typename instead of it as an object + $null = $output.Append(""[$($prop.Value.ToString())]"") + } # Anything else, we convert to string. # ToString() can throw so we use LanguagePrimitives.TryConvertTo() to hide a convert error else { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/Get-Error.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/Get-Error.Tests.ps1 new file mode 100644 index 00000000000..9bec24f302e --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/Get-Error.Tests.ps1 @@ -0,0 +1,107 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +Describe "Get-Error" -Tags "CI" { + It "Does not hang when serializing exception with array with type instances" { + $ps = [PowerShell]::Create() + $null = $ps.AddScript(@' + class GetErrorWithTypeArray : Exception { + [type[]]$Values + [type]$Type + + GetErrorWithTypeArray ([string]$Message) : base($Message) { + $this.Values = [type[]]@([string], [int]) + $this.Type = [bool] + } + } + try { throw [GetErrorWithTypeArray]::new("") } catch {} + Get-Error | Out-String +'@) + + $task = $ps.BeginInvoke() + if (-not $task.AsyncWaitHandle.WaitOne(5000)) { + $null = $ps.BeginStop($null, $null) + throw "Timed out waiting for Get-Error to serialize" + } + + $result = $ps.EndInvoke($task) + $result.Count | Should -Be 1 + $result[0] | Should -BeOfType ([string]) + + $formattedError = (@( + $result[0] -split "\r?\n" | ForEach-Object { + $_.TrimEnd() + } + ) -join ([Environment]::NewLine)).Trim() + + $formattedError | Should -Be @' +Exception : + Values : + [System.String] + [System.Int32] + Type : [System.Boolean] + HResult : -2146233088 +CategoryInfo : OperationStopped: (:) [], GetErrorWithTypeArray +InvocationInfo : + ScriptLineNumber : 10 + OffsetInLine : 19 + HistoryId : 1 + Line : try { throw [GetErrorWithTypeArray]::new("") } catch {} + + Statement : throw [GetErrorWithTypeArray]::new("") + PositionMessage : At line:10 char:19 + + try { throw [GetErrorWithTypeArray]::new("") } catch {} + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CommandOrigin : Internal +ScriptStackTrace : at , : line 10 +'@.Trim() + } + + It "Formats strings and primitive types in an array" { + $ps = [PowerShell]::Create() + $null = $ps.AddScript(@' + class GetErrorPrimitiveArray : Exception { + [object[]]$Values + + GetErrorPrimitiveArray ([string]$Message) : base($Message) { + $this.Values = @(1, "alpha", 0.5) + } + } + try { throw [GetErrorPrimitiveArray]::new("") } catch {} + Get-Error | Out-String +'@) + + $result = $ps.Invoke() + $result.Count | Should -Be 1 + $result[0] | Should -BeOfType ([string]) + + $formattedError = (@( + $result[0] -split "\r?\n" | ForEach-Object { + $_.TrimEnd() + } + ) -join ([Environment]::NewLine)).Trim() + + $formattedError | Should -Be @' +Exception : + Type : GetErrorPrimitiveArray + Values : + 1 + alpha + 0.5 + HResult : -2146233088 +CategoryInfo : OperationStopped: (:) [], GetErrorPrimitiveArray +InvocationInfo : + ScriptLineNumber : 8 + OffsetInLine : 19 + HistoryId : 1 + Line : try { throw [GetErrorPrimitiveArray]::new("") } catch {} + + Statement : throw [GetErrorPrimitiveArray]::new("") + PositionMessage : At line:8 char:19 + + try { throw [GetErrorPrimitiveArray]::new("") } catch {} + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CommandOrigin : Internal +ScriptStackTrace : at , : line 8 +'@.Trim() + } +} From feafe7aa671b5e4d661c3f5ba2f48917e15571ab Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 4 Apr 2024 18:22:02 -0400 Subject: [PATCH 02/18] [release/v7.4.2] Fix a regression in `Format-Table` when header label is empty (#21156) (#21420) --- .../common/FormatViewGenerator_Table.cs | 5 +- .../Format-Table.Tests.ps1 | 49 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Table.cs b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Table.cs index 64ed5bad6cf..0ddc307b646 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Table.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Table.cs @@ -173,7 +173,10 @@ private TableHeaderInfo GenerateTableHeaderInfoFromDataBaseInfo(PSObject so) ci.alignment = colHeader.alignment; if (colHeader.label != null) { - ci.HeaderMatchesProperty = so.Properties[colHeader.label.text] is not null; + if (colHeader.label.text != string.Empty) + { + ci.HeaderMatchesProperty = so.Properties[colHeader.label.text] is not null; + } ci.label = this.dataBaseInfo.db.displayResourceManagerCache.GetTextTokenString(colHeader.label); } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 index 78cfb88b613..34f2245909c 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 @@ -879,6 +879,55 @@ A Name B $numDecimals | Should -Be $expectedDecimals -Because $num } } + + It 'Works for empty column header label' { + $ps1xml = @' + + + + Test.Header.Empty + + Test.Format + + + + + + 4 + + + + + + + Prop + + + + + + + + +'@ + + $ps1xmlPath = Join-Path -Path $TestDrive -ChildPath 'empty.format.ps1xml' + Set-Content -Path $ps1xmlPath -Value $ps1xml + $object = [pscustomobject]@{Prop = '123'} + # run in own runspace so not affect global sessionstate + $ps = [powershell]::Create() + $ps.AddScript( { + param($ps1xmlPath, $object) + Update-FormatData -AppendPath $ps1xmlPath + $object.PSObject.TypeNames.Insert(0, 'Test.Format') + $object | Format-Table | Out-String + } ).AddArgument($ps1xmlPath).AddArgument($object) | Out-Null + $output = $ps.Invoke() + $expected = @" +Prop----123 +"@ + $output.Replace("`n","").Replace("`r","") | Should -BeExactly $expected + } } Describe 'Table color tests' -Tag 'CI' { From 73865ce253887b0458f81c36efcaa73f7ad07082 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 4 Apr 2024 18:22:20 -0400 Subject: [PATCH 03/18] [release/v7.4.2] Fix the regression when doing type inference for `$_` (#21223) (#21421) --- .../engine/parser/TypeInferenceVisitor.cs | 13 ++++++++++++- .../Host/TabCompletion/TabCompletion.Tests.ps1 | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs b/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs index 1e1ff771ac5..05c6f0f5f1e 100644 --- a/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs +++ b/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs @@ -1983,8 +1983,19 @@ private void InferTypeFrom(VariableExpressionAst variableExpressionAst, List 0) { - parent = switchErrorStatement.Conditions[0]; + if (switchErrorStatement.Conditions[0].Extent.EndOffset < variableExpressionAst.Extent.StartOffset) + { + parent = switchErrorStatement.Conditions[0]; + break; + } + else + { + // $_ is inside the condition that is being declared, eg: Get-Process | Sort-Object -Property {switch ($_.Proc + parent = switchErrorStatement.Parent; + continue; + } } + break; } else if (parent is ScriptBlockExpressionAst) diff --git a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 index 209c3757133..0f6c1430ddc 100644 --- a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 +++ b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 @@ -1693,6 +1693,11 @@ class InheritedClassTest : System.Attribute $res.CompletionMatches[0].CompletionText | Should -BeExactly 'Black' # 0 = NonPositive } + It 'Tab completion of $_ inside incomplete switch condition' { + $res = TabExpansion2 -inputScript 'Get-PSDrive | Sort-Object -Property {switch ($_.nam' + $res.CompletionMatches[0].CompletionText | Should -Be 'Name' + } + It "Test [CommandCompletion]::GetNextResult" { $inputStr = "Get-Command -Type Alias,c" $res = TabExpansion2 -inputScript $inputStr -cursorColumn $inputStr.Length From 0e4b9d74f39fb2e20562080c76fa270e6ae11d44 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 4 Apr 2024 18:22:35 -0400 Subject: [PATCH 04/18] [release/v7.4.2] Fix PowerShell class to support deriving from an abstract class with abstract properties (#21331) (#21422) --- .../engine/parser/PSType.cs | 21 ++++++--- .../scripting.Classes.inheritance.tests.ps1 | 44 +++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/System.Management.Automation/engine/parser/PSType.cs b/src/System.Management.Automation/engine/parser/PSType.cs index d01a22c305d..2fe7190f38d 100644 --- a/src/System.Management.Automation/engine/parser/PSType.cs +++ b/src/System.Management.Automation/engine/parser/PSType.cs @@ -276,7 +276,7 @@ private sealed class DefineTypeHelper internal readonly TypeBuilder _staticHelpersTypeBuilder; private readonly Dictionary _definedProperties; private readonly Dictionary>> _definedMethods; - private HashSet> _interfaceProperties; + private HashSet> _abstractProperties; internal readonly List<(string fieldName, IParameterMetadataProvider bodyAst, bool isStatic)> _fieldsToInitForMemberFunctions; private bool _baseClassHasDefaultCtor; @@ -446,9 +446,9 @@ private Type GetBaseTypes(Parser parser, TypeDefinitionAst typeDefinitionAst, ou private bool ShouldImplementProperty(string name, Type type) { - if (_interfaceProperties == null) + if (_abstractProperties == null) { - _interfaceProperties = new HashSet>(); + _abstractProperties = new HashSet>(); var allInterfaces = new HashSet(); // TypeBuilder.GetInterfaces() returns only the interfaces that was explicitly passed to its constructor. @@ -467,12 +467,23 @@ private bool ShouldImplementProperty(string name, Type type) { foreach (var property in interfaceType.GetProperties()) { - _interfaceProperties.Add(Tuple.Create(property.Name, property.PropertyType)); + _abstractProperties.Add(Tuple.Create(property.Name, property.PropertyType)); + } + } + + if (_typeBuilder.BaseType.IsAbstract) + { + foreach (var property in _typeBuilder.BaseType.GetProperties()) + { + if (property.GetAccessors().Any(m => m.IsAbstract)) + { + _abstractProperties.Add(Tuple.Create(property.Name, property.PropertyType)); + } } } } - return _interfaceProperties.Contains(Tuple.Create(name, type)); + return _abstractProperties.Contains(Tuple.Create(name, type)); } public void DefineMembers() diff --git a/test/powershell/Language/Classes/scripting.Classes.inheritance.tests.ps1 b/test/powershell/Language/Classes/scripting.Classes.inheritance.tests.ps1 index cf304d5918e..af013076029 100644 --- a/test/powershell/Language/Classes/scripting.Classes.inheritance.tests.ps1 +++ b/test/powershell/Language/Classes/scripting.Classes.inheritance.tests.ps1 @@ -628,3 +628,47 @@ class Derived : Base $sb.Invoke() | Should -Be 200 } } + +Describe 'Base type has abstract properties' -Tags "CI" { + It 'can derive from `FileSystemInfo`' { + ## FileSystemInfo has 3 abstract members that a derived type needs to implement + ## - public abstract bool Exists { get; } + ## - public abstract string Name { get; } + ## - public abstract void Delete (); + + class myFileSystemInfo : System.IO.FileSystemInfo + { + [string] $Name + [bool] $Exists + + myFileSystemInfo([string]$path) + { + # ctor + $this.Name = $path + $this.Exists = $true + } + + [void] Delete() + { + } + } + + $myFile = [myFileSystemInfo]::new('Hello') + $myFile.Name | Should -Be 'Hello' + $myFile.Exists | Should -BeTrue + } + + It 'deriving from `FileSystemInfo` will fail when the abstract property `Exists` is not implemented' { + $script = [scriptblock]::Create('class WillFail : System.IO.FileSystemInfo { [string] $Name }') + $failure = $null + try { + & $script + } catch { + $failure = $_ + } + + $failure | Should -Not -BeNullOrEmpty + $failure.FullyQualifiedErrorId | Should -BeExactly "TypeCreationError" + $failure.Exception.Message | Should -BeLike "*'get_Exists'*" + } +} From 7b6be492714d293ce09a9001314fa55a81da3afd Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 4 Apr 2024 18:22:51 -0400 Subject: [PATCH 05/18] [release/v7.4.2] Handle the case that `Runspace.DefaultRunspace is null` when logging for WDAC Audit (#21344) (#21423) --- .../security/wldpNativeMethods.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/System.Management.Automation/security/wldpNativeMethods.cs b/src/System.Management.Automation/security/wldpNativeMethods.cs index a95a78dbdbe..a59f37c0a8f 100644 --- a/src/System.Management.Automation/security/wldpNativeMethods.cs +++ b/src/System.Management.Automation/security/wldpNativeMethods.cs @@ -8,6 +8,7 @@ using System.Diagnostics.CodeAnalysis; using System.Management.Automation.Internal; +using System.Management.Automation.Runspaces; using System.Management.Automation.Tracing; using System.Runtime.InteropServices; @@ -91,9 +92,8 @@ internal static void LogWDACAuditMessage( string messageToWrite = message; // Augment the log message with current script information from the script debugger, if available. - context ??= System.Management.Automation.Runspaces.LocalPipeline.GetExecutionContextFromTLS(); + context ??= LocalPipeline.GetExecutionContextFromTLS(); bool debuggerAvailable = context is not null && - context._debugger is not null && context._debugger is ScriptDebugger; if (debuggerAvailable) @@ -108,10 +108,9 @@ context._debugger is not null && PSEtwLog.LogWDACAuditEvent(title, messageToWrite, fqid); // We drop into the debugger only if requested and we are running in the interactive host session runspace (Id == 1). - if (debuggerAvailable && - dropIntoDebugger is true && + if (debuggerAvailable && dropIntoDebugger && context._debugger.DebugMode.HasFlag(DebugModes.LocalScript) && - System.Management.Automation.Runspaces.Runspace.DefaultRunspace.Id == 1 && + Runspace.DefaultRunspace?.Id == 1 && context.DebugPreferenceVariable.HasFlag(ActionPreference.Break) && context.InternalHost?.UI is not null) { From 200ac639e14e42b546250c998eaa7769b89696e2 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 4 Apr 2024 18:23:05 -0400 Subject: [PATCH 06/18] [release/v7.4.2] Make sure the assembly/library resolvers are registered at early stage (#21361) (#21424) --- .../CoreCLR/CorePsAssemblyLoadContext.cs | 12 ++++++---- .../engine/hostifaces/ConnectionBase.cs | 22 +++++++++++++++++++ .../utils/ClrFacade.cs | 16 +++++++++++--- .../Basic/RegisterAssemblyResolverEarly.ps1 | 13 +++++++++++ 4 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 test/powershell/engine/Basic/RegisterAssemblyResolverEarly.ps1 diff --git a/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs b/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs index 0aba1eddfe4..6be8d3c595e 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs @@ -36,16 +36,19 @@ internal sealed partial class PowerShellAssemblyLoadContext /// /// Initialize a singleton of PowerShellAssemblyLoadContext. /// - internal static PowerShellAssemblyLoadContext InitializeSingleton(string basePaths) + internal static PowerShellAssemblyLoadContext InitializeSingleton(string basePaths, bool throwOnReentry) { lock (s_syncObj) { - if (Instance != null) + if (Instance is null) + { + Instance = new PowerShellAssemblyLoadContext(basePaths); + } + else if (throwOnReentry) { throw new InvalidOperationException(SingletonAlreadyInitialized); } - Instance = new PowerShellAssemblyLoadContext(basePaths); return Instance; } } @@ -581,7 +584,8 @@ public static void SetPowerShellAssemblyLoadContext([MarshalAs(UnmanagedType.LPW { ArgumentException.ThrowIfNullOrEmpty(basePaths); - PowerShellAssemblyLoadContext.InitializeSingleton(basePaths); + // Disallow calling this method from native code for more than once. + PowerShellAssemblyLoadContext.InitializeSingleton(basePaths, throwOnReentry: true); } } diff --git a/src/System.Management.Automation/engine/hostifaces/ConnectionBase.cs b/src/System.Management.Automation/engine/hostifaces/ConnectionBase.cs index 23daa3c8713..0969d7b08c6 100644 --- a/src/System.Management.Automation/engine/hostifaces/ConnectionBase.cs +++ b/src/System.Management.Automation/engine/hostifaces/ConnectionBase.cs @@ -25,6 +25,28 @@ internal abstract class RunspaceBase : Runspace { #region constructors + /// + /// Initialize powershell AssemblyLoadContext and register the 'Resolving' event, if it's not done already. + /// If powershell is hosted by a native host such as DSC, then PS ALC may be initialized via 'SetPowerShellAssemblyLoadContext' before loading S.M.A. + /// + /// + /// We do this both here and during the initialization of the 'ClrFacade' type. + /// This is because we want to make sure the assembly/library resolvers are: + /// 1. registered before any script/cmdlet can run. + /// 2. registered before 'ClrFacade' gets used for assembly related operations. + /// + /// The 'ClrFacade' type may be used without a Runspace created, for example, by calling type conversion methods in the 'LanguagePrimitive' type. + /// And at the mean time, script or cmdlet may run without the 'ClrFacade' type initialized. + /// That's why we attempt to create the singleton of 'PowerShellAssemblyLoadContext' at both places. + /// + static RunspaceBase() + { + if (PowerShellAssemblyLoadContext.Instance is null) + { + PowerShellAssemblyLoadContext.InitializeSingleton(string.Empty, throwOnReentry: false); + } + } + /// /// Construct an instance of an Runspace using a custom /// implementation of PSHost. diff --git a/src/System.Management.Automation/utils/ClrFacade.cs b/src/System.Management.Automation/utils/ClrFacade.cs index aa997734353..058c33a68bf 100644 --- a/src/System.Management.Automation/utils/ClrFacade.cs +++ b/src/System.Management.Automation/utils/ClrFacade.cs @@ -22,13 +22,23 @@ internal static class ClrFacade { /// /// Initialize powershell AssemblyLoadContext and register the 'Resolving' event, if it's not done already. - /// If powershell is hosted by a native host such as DSC, then PS ALC might be initialized via 'SetPowerShellAssemblyLoadContext' before loading S.M.A. + /// If powershell is hosted by a native host such as DSC, then PS ALC may be initialized via 'SetPowerShellAssemblyLoadContext' before loading S.M.A. /// + /// + /// We do this both here and during the initialization of the 'RunspaceBase' type. + /// This is because we want to make sure the assembly/library resolvers are: + /// 1. registered before any script/cmdlet can run. + /// 2. registered before 'ClrFacade' gets used for assembly related operations. + /// + /// The 'ClrFacade' type may be used without a Runspace created, for example, by calling type conversion methods in the 'LanguagePrimitive' type. + /// And at the mean time, script or cmdlet may run without the 'ClrFacade' type initialized. + /// That's why we attempt to create the singleton of 'PowerShellAssemblyLoadContext' at both places. + /// static ClrFacade() { - if (PowerShellAssemblyLoadContext.Instance == null) + if (PowerShellAssemblyLoadContext.Instance is null) { - PowerShellAssemblyLoadContext.InitializeSingleton(string.Empty); + PowerShellAssemblyLoadContext.InitializeSingleton(string.Empty, throwOnReentry: false); } } diff --git a/test/powershell/engine/Basic/RegisterAssemblyResolverEarly.ps1 b/test/powershell/engine/Basic/RegisterAssemblyResolverEarly.ps1 new file mode 100644 index 00000000000..fbd745b3e1d --- /dev/null +++ b/test/powershell/engine/Basic/RegisterAssemblyResolverEarly.ps1 @@ -0,0 +1,13 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +Describe "Assembly resolvers should be registered early at startup" -Tags "CI" { + + ## The PKI module requires loading an assembly from GAC, and thus depends on the PowerShell assembly resolver to work. + It "Can load the PKI module with 'pwsh -ExecutionPolicy bypass -NoProfile -c `"Import-Module PKI`"'" -Skip:(!$IsWindows) { + ## Use 'Bypass' execution policy so that it doesn't trigger 'AuthorizationManager' which would trigger 'ClrFacade' initialization. + ## We want to make sure even if 'ClrFacade' is not hit during startup, the resolvers are still registered early enough. + $out = pwsh -ExecutionPolicy bypass -NoProfile -c "Import-Module PKI; Get-Module | % name" + $out | Should -BeExactly "PKI" + } +} From 3dd445136040c96042518c40240ae5f57ec0cb28 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 4 Apr 2024 18:23:22 -0400 Subject: [PATCH 07/18] [release/v7.4.2] Revert the PR #17856 (Do not preserve temporary results when no need to do so) (#21368) (#21425) --- .../engine/parser/Compiler.cs | 27 +++++------ .../Scripting/Scripting.Followup.Tests.ps1 | 45 ++++++++++--------- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/System.Management.Automation/engine/parser/Compiler.cs b/src/System.Management.Automation/engine/parser/Compiler.cs index 3fac9de74f6..91daf43821d 100644 --- a/src/System.Management.Automation/engine/parser/Compiler.cs +++ b/src/System.Management.Automation/engine/parser/Compiler.cs @@ -2278,25 +2278,26 @@ private Expression CaptureAstResults( switch (context) { case CaptureAstContext.AssignmentWithResultPreservation: - result = Expression.Call(CachedReflectionInfo.PipelineOps_PipelineResult, resultList); - - // PipelineResult might get skipped in some circumstances due to an early return or a FlowControlException thrown out, in which case - // we write to the oldPipe. This can happen in cases like: - // $(1;2;return 3) - finallyExprs.Add(Expression.Call(CachedReflectionInfo.PipelineOps_FlushPipe, oldPipe, resultList)); - break; case CaptureAstContext.AssignmentWithoutResultPreservation: result = Expression.Call(CachedReflectionInfo.PipelineOps_PipelineResult, resultList); // Clear the temporary pipe in case of exception, if we are not required to preserve the results - var catchExprs = new List + if (context == CaptureAstContext.AssignmentWithoutResultPreservation) { - Expression.Call(CachedReflectionInfo.PipelineOps_ClearPipe, resultList), - Expression.Rethrow(), - Expression.Constant(null, typeof(object)) - }; + var catchExprs = new List + { + Expression.Call(CachedReflectionInfo.PipelineOps_ClearPipe, resultList), + Expression.Rethrow(), + Expression.Constant(null, typeof(object)) + }; + + catches.Add(Expression.Catch(typeof(RuntimeException), Expression.Block(typeof(object), catchExprs))); + } - catches.Add(Expression.Catch(typeof(RuntimeException), Expression.Block(typeof(object), catchExprs))); + // PipelineResult might get skipped in some circumstances due to an early return or a FlowControlException thrown out, + // in which case we write to the oldPipe. This can happen in cases like: + // $(1;2;return 3) + finallyExprs.Add(Expression.Call(CachedReflectionInfo.PipelineOps_FlushPipe, oldPipe, resultList)); break; case CaptureAstContext.Condition: result = DynamicExpression.Dynamic(PSPipelineResultToBoolBinder.Get(), typeof(bool), resultList); diff --git a/test/powershell/Language/Scripting/Scripting.Followup.Tests.ps1 b/test/powershell/Language/Scripting/Scripting.Followup.Tests.ps1 index fff4993ffec..56bc16b2710 100644 --- a/test/powershell/Language/Scripting/Scripting.Followup.Tests.ps1 +++ b/test/powershell/Language/Scripting/Scripting.Followup.Tests.ps1 @@ -81,28 +81,6 @@ Describe "Scripting.Followup.Tests" -Tags "CI" { $result | Should -BeOfType 'System.Collections.Specialized.OrderedDictionary' } - It "Don't preserve result when no need to do so in case of flow-control exception" { - function TestFunc1([switch]$p) { - ## No need to preserve and flush the results from the IF statement to the outer - ## pipeline, because the results are supposed to be assigned to a variable. - if ($p) { - $null = if ($true) { "one"; return "two" } - } else { - $a = foreach ($a in 1) { "one"; return; } - } - } - - function TestFunc2 { - ## The results from the sub-expression need to be preserved and flushed to the outer pipeline. - $("1";return "2") - } - - TestFunc1 | Should -Be $null - TestFunc1 -p | Should -Be $null - - TestFunc2 | Should -Be @("1", "2") - } - It "'[NullString]::Value' should be treated as string type when resolving .NET method" { $testType = 'NullStringTest' -as [type] if (-not $testType) { @@ -146,4 +124,27 @@ public class NullStringTest { $result = & $powershell -noprofile -c '[System.Text.Encoding]::GetEncoding("IBM437").WebName' $result | Should -BeExactly "ibm437" } + + It 'Return statement on the right side of an assignment should write the retrun value to outer pipe' { + function TestFunc1 { + ## The return value are not assigned to the variable but should be written to the outer pipe. + $Global:mylhsvar = if ($true) { return "one" } + } + + function TestFunc2 { + ## The results from the sub-expression need to be preserved and flushed to the outer pipeline. + $("1";return "2") + } + + try { + $Global:mylhsvar = $null + TestFunc1 | Should -BeExactly "one" + TestFunc2 | Should -Be @("1", "2") + + $Global:mylhsvar | Should -Be $null + } + finally { + Remove-Variable -Name mylhsvar -Scope Global + } + } } From e1bcda344f341b59e3ad3cca3de66101afd622d4 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 4 Apr 2024 18:23:38 -0400 Subject: [PATCH 08/18] [release/v7.4.2] PowerShell co-ordinated build OneBranch pipeline (#21364) (#21426) --- .config/suppress.json | 17 ++ .config/tsaoptions.json | 5 + ...werShell-Coordinated_Packages-Official.yml | 251 ++++++++++++++++++ .pipelines/templates/SetVersionVariables.yml | 68 +++++ .pipelines/templates/checkAzureContainer.yml | 90 +++++++ .pipelines/templates/cloneToOfficialPath.yml | 19 ++ .../templates/insert-nuget-config-azfeed.yml | 33 +++ .pipelines/templates/linux.yml | 183 +++++++++++++ .pipelines/templates/mac.yml | 132 +++++++++ .pipelines/templates/obp-file-signing.yml | 152 +++++++++++ .pipelines/templates/shouldSign.yml | 23 ++ .pipelines/templates/step/finalize.yml | 6 + .pipelines/templates/testartifacts.yml | 108 ++++++++ .pipelines/templates/windows-hosted-build.yml | 126 +++++++++ tools/packaging/packaging.psm1 | 45 +++- tools/releaseBuild/setReleaseTag.ps1 | 7 + 16 files changed, 1261 insertions(+), 4 deletions(-) create mode 100644 .config/suppress.json create mode 100644 .config/tsaoptions.json create mode 100644 .pipelines/PowerShell-Coordinated_Packages-Official.yml create mode 100644 .pipelines/templates/SetVersionVariables.yml create mode 100644 .pipelines/templates/checkAzureContainer.yml create mode 100644 .pipelines/templates/cloneToOfficialPath.yml create mode 100644 .pipelines/templates/insert-nuget-config-azfeed.yml create mode 100644 .pipelines/templates/linux.yml create mode 100644 .pipelines/templates/mac.yml create mode 100644 .pipelines/templates/obp-file-signing.yml create mode 100644 .pipelines/templates/shouldSign.yml create mode 100644 .pipelines/templates/step/finalize.yml create mode 100644 .pipelines/templates/testartifacts.yml create mode 100644 .pipelines/templates/windows-hosted-build.yml diff --git a/.config/suppress.json b/.config/suppress.json new file mode 100644 index 00000000000..55e607b1b0c --- /dev/null +++ b/.config/suppress.json @@ -0,0 +1,17 @@ +{ + "tool": "Credential Scanner", + "suppressions": [ + { + "file": "\\test\\tools\\Modules\\WebListener\\ClientCert.pfx", + "_justification": "Test certificate with private key" + }, + { + "file": "\\test\\tools\\Modules\\WebListener\\ServerCert.pfx", + "_justification": "Test certificate with private key" + }, + { + "file": "\\test\\powershell\\Modules\\Microsoft.PowerShell.Security\\certificateCommon.psm1", + "_justification": "Test certificate with private key and inline suppression isn't working" + } + ] +} diff --git a/.config/tsaoptions.json b/.config/tsaoptions.json new file mode 100644 index 00000000000..90d4db36755 --- /dev/null +++ b/.config/tsaoptions.json @@ -0,0 +1,5 @@ +{ + "instanceUrl": "https://msazure.visualstudio.com", + "projectName": "One", + "areaPath": "One\\MGMT\\Compute\\Powershell\\Powershell\\PowerShell Core" +} diff --git a/.pipelines/PowerShell-Coordinated_Packages-Official.yml b/.pipelines/PowerShell-Coordinated_Packages-Official.yml new file mode 100644 index 00000000000..432a627b0d0 --- /dev/null +++ b/.pipelines/PowerShell-Coordinated_Packages-Official.yml @@ -0,0 +1,251 @@ +name: UnifiedPackageBuild-$(Build.BuildId) +trigger: + branches: + include: + - master + - release* +pr: + branches: + include: + - master + - release* + +parameters: + - name: ForceAzureBlobDelete + displayName: Delete Azure Blob + type: string + values: + - true + - false + default: false + - name: InternalSDKBlobURL + displayName: URL to the blob having internal .NET SDK + type: string + default: ' ' + - name: ReleaseTagVar + displayName: Release Tag + type: string + default: 'fromBranch' + - name: SKIP_SIGNING + displayName: Skip Signing + type: string + default: 'NO' + +resources: + repositories: + - repository: ComplianceRepo + type: github + endpoint: ComplianceGHRepo + name: PowerShell/compliance + ref: master + - repository: onebranchTemplates + type: git + name: OneBranch.Pipelines/GovernedTemplates + ref: refs/heads/main + +variables: + - name: PS_RELEASE_BUILD + value: 1 + - name: DOTNET_CLI_TELEMETRY_OPTOUT + value: 1 + - name: POWERSHELL_TELEMETRY_OPTOUT + value: 1 + - name: nugetMultiFeedWarnLevel + value: none + - name: NugetSecurityAnalysisWarningLevel + value: none + - name: skipNugetSecurityAnalysis + value: true + - name: branchCounterKey + value: $[format('{0:yyyyMMdd}-{1}', pipeline.startTime,variables['Build.SourceBranch'])] + - name: branchCounter + value: $[counter(variables['branchCounterKey'], 1)] + - name: ForceAzureBlobDelete + value: ${{ parameters.ForceAzureBlobDelete }} + - name: BUILDSECMON_OPT_IN + value: true + - name: __DOTNET_RUNTIME_FEED + value: ${{ parameters.InternalSDKBlobURL }} + - name: LinuxContainerImage + value: onebranch.azurecr.io/linux/ubuntu-2004:latest + - name: WindowsContainerImage + value: onebranch.azurecr.io/windows/ltsc2019/vse2022:latest + - name: CDP_DEFINITION_BUILD_COUNT + value: $[counter('', 0)] + - name: ReleaseTagVar + value: ${{ parameters.ReleaseTagVar }} + - name: SKIP_SIGNING + value: ${{ parameters.SKIP_SIGNING }} + - group: 'AzDevOpsArtifacts' + +extends: + template: v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates + parameters: + customTags: 'ES365AIMigrationTooling' + globalSdl: + disableLegacyManifest: true + # disabled Armorty as we dont have any ARM templates to scan. It fails on some sample ARM templates. + armory: + enabled: false + sbom: + enabled: true + compiled: + ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}: + enabled: true + ${{ else }}: + enabled: false + credscan: + enabled: true + scanFolder: $(Build.SourcesDirectory) + suppressionsFile: $(Build.SourcesDirectory)\.config\suppress.json + cg: + enabled: true + ignoreDirectories: '.devcontainer,demos,docker,docs,src,test,tools/packaging' + asyncSdl: # https://aka.ms/obpipelines/asyncsdl + enabled: true + forStages: [prep, macos, linux, windows, SignFiles, test_and_release_artifacts] + credscan: + enabled: true + scanFolder: $(Build.SourcesDirectory) + suppressionsFile: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json + binskim: + enabled: false + # APIScan requires a non-Ready-To-Run build + apiscan: + enabled: false + tsaOptionsFile: .config\tsaoptions.json + + stages: + - stage: prep + jobs: + - template: /.pipelines/templates/checkAzureContainer.yml@self + + - stage: macos + displayName: macOS - build and sign + dependsOn: ['prep'] + jobs: + - template: /.pipelines/templates/mac.yml@self + parameters: + buildArchitecture: x64 + - template: /.pipelines/templates/mac.yml@self + parameters: + buildArchitecture: arm64 + + - stage: linux + displayName: linux - build and sign + dependsOn: ['prep'] + jobs: + - template: /.pipelines/templates/linux.yml@self + parameters: + Runtime: 'linux-x64' + JobName: 'linux_x64' + + - template: /.pipelines/templates/linux.yml@self + parameters: + Runtime: 'linux-x64' + JobName: 'linux_x64_minSize' + BuildConfiguration: 'minSize' + + - template: /.pipelines/templates/linux.yml@self + parameters: + Runtime: 'linux-arm' + JobName: 'linux_arm' + + - template: /.pipelines/templates/linux.yml@self + parameters: + Runtime: 'linux-arm64' + JobName: 'linux_arm64' + + - template: /.pipelines/templates/linux.yml@self + parameters: + Runtime: 'fxdependent-linux-x64' + JobName: 'linux_fxd_x64_mariner' + + - template: /.pipelines/templates/linux.yml@self + parameters: + Runtime: 'fxdependent-linux-arm64' + JobName: 'linux_fxd_arm64_mariner' + + - template: /.pipelines/templates/linux.yml@self + parameters: + Runtime: 'fxdependent-noopt-linux-musl-x64' + JobName: 'linux_fxd_x64_alpine' + + - template: /.pipelines/templates/linux.yml@self + parameters: + Runtime: 'fxdependent' + JobName: 'linux_fxd' + + - template: /.pipelines/templates/linux.yml@self + parameters: + Runtime: 'linux-musl-x64' + JobName: 'linux_x64_alpine' + + - stage: windows + displayName: windows - build and sign + dependsOn: ['prep'] + jobs: + - template: /.pipelines/templates/windows-hosted-build.yml@self + parameters: + Architecture: x64 + BuildConfiguration: release + JobName: build_windows_x64_release + - template: /.pipelines/templates/windows-hosted-build.yml@self + parameters: + Architecture: x64 + BuildConfiguration: minSize + JobName: build_windows_x64_minSize + - template: /.pipelines/templates/windows-hosted-build.yml@self + parameters: + Architecture: x86 + JobName: build_windows_x86_release + - template: /.pipelines/templates/windows-hosted-build.yml@self + parameters: + Architecture: arm64 + JobName: build_windows_arm64_release + - template: /.pipelines/templates/windows-hosted-build.yml@self + parameters: + Architecture: fxdependent + JobName: build_windows_fxdependent_release + - template: /.pipelines/templates/windows-hosted-build.yml@self + parameters: + Architecture: fxdependentWinDesktop + JobName: build_windows_fxdependentWinDesktop_release + + - stage: test_and_release_artifacts + displayName: Test and Release Artifacts + dependsOn: ['prep'] + jobs: + - template: /.pipelines/templates/testartifacts.yml@self + + - job: release_json + displayName: Create and Upload release.json + pool: + type: windows + variables: + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' + - name: ob_sdl_tsa_configFile + value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json + - name: ob_sdl_credscan_suppressionsFile + value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json + steps: + - checkout: self + clean: true + - template: /.pipelines/templates/SetVersionVariables.yml@self + parameters: + ReleaseTagVar: $(ReleaseTagVar) + - powershell: | + $metadata = Get-Content '$(Build.SourcesDirectory)/PowerShell/tools/metadata.json' -Raw | ConvertFrom-Json + $LTS = $metadata.LTSRelease.Package + @{ ReleaseVersion = "$(Version)"; LTSRelease = $LTS } | ConvertTo-Json | Out-File "$(Build.StagingDirectory)\release.json" + Get-Content "$(Build.StagingDirectory)\release.json" + + if (-not (Test-Path "$(ob_outputDirectory)\metadata")) { + New-Item -ItemType Directory -Path "$(ob_outputDirectory)\metadata" + } + + Copy-Item -Path "$(Build.StagingDirectory)\release.json" -Destination "$(ob_outputDirectory)\metadata" -Force + displayName: Create and upload release.json file to build artifact + retryCountOnTaskFailure: 2 + - template: /.pipelines/templates/step/finalize.yml@self diff --git a/.pipelines/templates/SetVersionVariables.yml b/.pipelines/templates/SetVersionVariables.yml new file mode 100644 index 00000000000..f8fb68c10bd --- /dev/null +++ b/.pipelines/templates/SetVersionVariables.yml @@ -0,0 +1,68 @@ +parameters: + ReleaseTagVar: v6.2.0 + ReleaseTagVarName: ReleaseTagVar + CreateJson: 'no' + UseJson: 'yes' + +steps: +- ${{ if eq(parameters['UseJson'],'yes') }}: + - task: DownloadBuildArtifacts@0 + inputs: + artifactName: 'drop_prep_DeleteBlob' + itemPattern: '*.json' + downloadPath: '$(System.ArtifactsDirectory)' + displayName: Download Build Info Json + env: + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase + +- powershell: | + $path = "./build.psm1" + if($env:REPOROOT){ + Write-Verbose "reporoot already set to ${env:REPOROOT}" -Verbose + exit 0 + } + if(Test-Path -Path $path) + { + Write-Verbose "reporoot detect at: ." -Verbose + $repoRoot = '.' + } + else{ + $path = "./PowerShell/build.psm1" + if(Test-Path -Path $path) + { + Write-Verbose "reporoot detect at: ./PowerShell" -Verbose + $repoRoot = './PowerShell' + } + } + if($repoRoot) { + $vstsCommandString = "vso[task.setvariable variable=repoRoot]$repoRoot" + Write-Host ("sending " + $vstsCommandString) + Write-Host "##$vstsCommandString" + } else { + Write-Verbose -Verbose "repo not found" + } + displayName: 'Set repo Root' + env: + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase + +- powershell: | + $createJson = ("${{ parameters.CreateJson }}" -ne "no") + $releaseTag = & "$env:REPOROOT/tools/releaseBuild/setReleaseTag.ps1" -ReleaseTag ${{ parameters.ReleaseTagVar }} -Variable "${{ parameters.ReleaseTagVarName }}" -CreateJson:$createJson + $version = $releaseTag.Substring(1) + $vstsCommandString = "vso[task.setvariable variable=Version]$version" + Write-Host ("sending " + $vstsCommandString) + Write-Host "##$vstsCommandString" + $azureVersion = $releaseTag.ToLowerInvariant() -replace '\.', '-' + $vstsCommandString = "vso[task.setvariable variable=AzureVersion]$azureVersion" + Write-Host ("sending " + $vstsCommandString) + Write-Host "##$vstsCommandString" + displayName: 'Set ${{ parameters.ReleaseTagVarName }} and other version Variables' + env: + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase + +- powershell: | + Get-ChildItem -Path env: + displayName: Capture environment + condition: succeededOrFailed() + env: + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase diff --git a/.pipelines/templates/checkAzureContainer.yml b/.pipelines/templates/checkAzureContainer.yml new file mode 100644 index 00000000000..d761d9f3275 --- /dev/null +++ b/.pipelines/templates/checkAzureContainer.yml @@ -0,0 +1,90 @@ +jobs: +- job: DeleteBlob + variables: + - group: Azure Blob variable group + - group: AzureBlobServiceConnection + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT/BuildJson' + - name: ob_sdl_sbom_enabled + value: false + - name: ob_sdl_codeSignValidation_enabled + value: false + - name: ob_sdl_tsa_configFile + value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json + - name: ob_sdl_credscan_suppressionsFile + value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json + - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}: + - name: ob_sdl_codeql_compiled_enabled + value: true + + displayName: Delete blob is exists + pool: + type: windows + steps: + - checkout: self + clean: true + env: + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase + + - template: /.pipelines/templates/SetVersionVariables.yml@self + parameters: + ReleaseTagVar: $(ReleaseTagVar) + CreateJson: yes + UseJson: no + + - template: /.pipelines/templates/cloneToOfficialPath.yml@self + + - template: /.pipelines/templates/insert-nuget-config-azfeed.yml@self + parameters: + repoRoot: $(PowerShellRoot) + + - pwsh: | + if (-not (Test-Path -Path $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json)) { + Get-ChildItem -Path $(Build.SourcesDirectory) -Recurse + throw 'tsaoptions.json not found' + } + displayName: 'Check tsaoptions.json' + + - pwsh: | + if (-not (Test-Path -Path $(Build.SourcesDirectory)\PowerShell\.config\suppress.json)) { + Get-ChildItem -Path $(Build.SourcesDirectory) -Recurse + throw 'suppress.json not found' + } + displayName: 'Check suppress.json' + + # Needed as per FAQ here: https://eng.ms/docs/products/onebranch/build/troubleshootingfaqs + - task: PowerShell@2 + displayName: 'Update Az.Storage Module' + inputs: + targetType: 'inline' + script: | + Get-PackageProvider -Name NuGet -ForceBootstrap + Install-Module -Name Az.Storage -Verbose -Force -AllowClobber + Uninstall-AzureRm -Verbose + + - task: AzurePowerShell@5 + displayName: Check if blob exists and delete if specified + inputs: + azureSubscription: az-blob-cicd-infra + scriptType: inlineScript + azurePowerShellVersion: latestVersion + inline: | + try { + $container = Get-AzStorageContainer -Container '$(AzureVersion)' -Context (New-AzStorageContext -StorageAccountName '$(StorageAccount)') -ErrorAction Stop + if ($container -ne $null -and '$(ForceAzureBlobDelete)' -eq 'false') { + throw 'Azure blob container $(AzureVersion) already exists. To overwrite, use ForceAzureBlobDelete parameter' + } + elseif ($container -ne $null -and '$(ForceAzureBlobDelete)' -eq 'true') { + Write-Verbose -Verbose 'Removing container $(AzureVersion) due to ForceAzureBlobDelete parameter' + Remove-AzStorageContainer -Name '$(AzureVersion)' -Context (New-AzStorageContext -StorageAccountName '$(StorageAccount)') -Force + } + } + catch { + if ($_.FullyQualifiedErrorId -eq 'ResourceNotFoundException,Microsoft.WindowsAzure.Commands.Storage.Blob.Cmdlet.GetAzureStorageContainerCommand') { + Write-Verbose -Verbose 'Container "$(AzureVersion)" does not exists.' + } + else { + throw $_ + } + } + - template: /.pipelines/templates/step/finalize.yml@self diff --git a/.pipelines/templates/cloneToOfficialPath.yml b/.pipelines/templates/cloneToOfficialPath.yml new file mode 100644 index 00000000000..844d8b8028d --- /dev/null +++ b/.pipelines/templates/cloneToOfficialPath.yml @@ -0,0 +1,19 @@ +parameters: + nativePathRoot: '' + +steps: +- powershell: | + $dirSeparatorChar = [system.io.path]::DirectorySeparatorChar + $nativePath = "${{parameters.nativePathRoot }}${dirSeparatorChar}PowerShell" + Write-Host "##vso[task.setvariable variable=PowerShellRoot]$nativePath" + if ((Test-Path "$nativePath")) { + Remove-Item -Path "$nativePath" -Force -Recurse -Verbose -ErrorAction ignore + } + else { + Write-Verbose -Verbose -Message "No cleanup required." + } + git clone --quiet $env:REPOROOT $nativePath + displayName: Clone PowerShell Repo to /PowerShell + errorActionPreference: silentlycontinue + env: + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase diff --git a/.pipelines/templates/insert-nuget-config-azfeed.yml b/.pipelines/templates/insert-nuget-config-azfeed.yml new file mode 100644 index 00000000000..2279c4839aa --- /dev/null +++ b/.pipelines/templates/insert-nuget-config-azfeed.yml @@ -0,0 +1,33 @@ +parameters: +- name: "repoRoot" + default: $(REPOROOT) +steps: +- pwsh: | + $configPath = "${env:NugetConfigDir}/nuget.config" + Import-Module ${{ parameters.repoRoot }}/build.psm1 -Force + New-NugetConfigFile -NugetFeedUrl $(AzDevOpsFeed) -UserName $(AzDevOpsFeedUserName) -ClearTextPAT $(AzDevOpsFeedPAT2) -FeedName AzDevOpsFeed -Destination "${env:NugetConfigDir}" + 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 PSGallery modules' + condition: and(succeededOrFailed(), ne(variables['AzDevOpsFeed'], '')) + env: + NugetConfigDir: ${{ parameters.repoRoot }}/src/Modules + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase + +- pwsh: | + $configPath = "${env:NugetConfigDir}/nuget.config" + Import-Module ${{ parameters.repoRoot }}/build.psm1 -Force + New-NugetConfigFile -NugetFeedUrl $(PSInternalNugetFeed) -UserName $(PSInternalNugetFeedUserName) -ClearTextPAT $(PSInternalNugetFeedPAT) -FeedName AzDevOpsFeed -Destination "${env:NugetConfigDir}" + 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'], '')) + env: + NugetConfigDir: ${{ parameters.repoRoot }} + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase diff --git a/.pipelines/templates/linux.yml b/.pipelines/templates/linux.yml new file mode 100644 index 00000000000..134d581833d --- /dev/null +++ b/.pipelines/templates/linux.yml @@ -0,0 +1,183 @@ +parameters: + Runtime: 'linux-x64' + BuildConfiguration: 'release' + JobName: 'build_linux' + +jobs: +- job: build_${{ parameters.JobName }} + displayName: Build_Linux_${{ parameters.Runtime }}_${{ parameters.BuildConfiguration }} + condition: succeeded() + pool: + type: linux + variables: + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none + - name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE + value: 1 + - group: DotNetPrivateBuildAccess + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' + - name: ob_sdl_codeSignValidation_enabled + value: false + - name: ob_sdl_binskim_enabled + value: true + - name: ob_sdl_tsa_configFile + value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json + - name: ob_sdl_credscan_suppressionsFile + value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json + - name: BuildConfiguration + value: ${{ parameters.BuildConfiguration }} + - name: Runtime + value: ${{ parameters.Runtime }} + - name: ob_sdl_sbom_packageName + value: 'Microsoft.Powershell.Linux.${{ parameters.Runtime }}' + - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}: + - name: ob_sdl_codeql_compiled_enabled + value: true + + steps: + - checkout: self + clean: true + env: + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase + + - template: /.pipelines/templates/SetVersionVariables.yml@self + parameters: + ReleaseTagVar: $(ReleaseTagVar) + + - template: /.pipelines/templates/cloneToOfficialPath.yml@self + + - template: /.pipelines/templates/insert-nuget-config-azfeed.yml@self + parameters: + repoRoot: $(PowerShellRoot) + + - task: CodeQL3000Init@0 # Add CodeQL Init task right before your 'Build' step. + condition: eq(variables['Build.SourceBranch'], 'refs/heads/master') + env: + ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + inputs: + Enabled: true + AnalyzeInPipeline: true + Language: csharp + + - pwsh: | + $runtime = $env:RUNTIME + + $params = @{} + if ($env:BuildConfiguration -eq 'minSize') { + $params['ForMinimalSize'] = $true + } + + Write-Verbose -Message "Building PowerShell with Runtime: $runtime" + Import-Module -Name $(PowerShellRoot)/build.psm1 -Force + $buildWithSymbolsPath = New-Item -ItemType Directory -Path $(Pipeline.Workspace)/Symbols_$(Runtime) -Force + + Start-PSBootstrap + $null = New-Item -ItemType Directory -Path $buildWithSymbolsPath -Force -Verbose + Start-PSBuild -Runtime $runtime -Configuration Release -Output $buildWithSymbolsPath @params -Clean -PSModuleRestore + + Write-Verbose -Verbose "Verifying pdbs exist in build folder" + $pdbs = Get-ChildItem -Path $buildWithSymbolsPath -Recurse -Filter *.pdb + if ($pdbs.Count -eq 0) { + Write-Error -Message "No pdbs found in build folder" + } + else { + Write-Verbose -Verbose "Found $($pdbs.Count) pdbs in build folder" + $pdbs | ForEach-Object { + Write-Verbose -Verbose "Pdb: $($_.FullName)" + } + } + + Write-Verbose -Verbose "Completed building PowerShell for '$env:BuildConfiguration' configuration" + displayName: 'Build Linux - $(Runtime)' + env: + __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) + ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + + - task: CodeQL3000Finalize@0 # Add CodeQL Finalize task right after your 'Build' step. + condition: eq(variables['Build.SourceBranch'], 'refs/heads/master') + env: + ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + + - pwsh: | + $platform = 'linux' + $vstsCommandString = "vso[task.setvariable variable=ArtifactPlatform]$platform" + Write-Host ("sending " + $vstsCommandString) + Write-Host "##$vstsCommandString" + displayName: Set artifact platform + + - pwsh: | + $pathForUpload = New-Item -ItemType Directory -Path '$(ob_outputDirectory)/Unsigned-$(Runtime)' -Force + Write-Verbose -Verbose -Message "pathForUpload: $pathForUpload" + Copy-Item -Path '$(Pipeline.Workspace)/Symbols_$(Runtime)/*' -Destination $pathForUpload -Recurse -Force -Verbose + displayName: Copy unsigned files for upload + + - template: /.pipelines/templates/step/finalize.yml@self + +- job: sign_${{ parameters.JobName }} + displayName: Sign_Linux_${{ parameters.Runtime }}_${{ parameters.BuildConfiguration }} + condition: succeeded() + dependsOn: build_${{ parameters.JobName }} + pool: + type: windows + variables: + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none + - name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE + value: 1 + - group: DotNetPrivateBuildAccess + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' + - name: ob_sdl_codeSignValidation_enabled + value: false + - name: ob_sdl_binskim_enabled + value: false + - name: ob_sdl_tsa_configFile + value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json + - name: ob_sdl_credscan_suppressionsFile + value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json + - name: BuildConfiguration + value: ${{ parameters.BuildConfiguration }} + - name: Runtime + value: ${{ parameters.Runtime }} + - name: ob_sdl_codeql_compiled_enabled + value: false + + steps: + - checkout: self + clean: true + env: + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase + + - template: /.pipelines/templates/SetVersionVariables.yml@self + parameters: + ReleaseTagVar: $(ReleaseTagVar) + + - template: /.pipelines/templates/cloneToOfficialPath.yml@self + + - task: DownloadPipelineArtifact@2 + inputs: + artifact: drop_linux_build_${{ parameters.JobName }} + path: $(Pipeline.Workspace)/drop_linux_build + displayName: Download build + + - pwsh: | + Get-ChildItem -Path $(Pipeline.Workspace)/drop_linux_build -Recurse + displayName: Capture downloaded files + + - pwsh: | + $pwshPath = Get-ChildItem -Path $(Pipeline.Workspace)/drop_linux_build -File -Recurse | Where-Object { $_.Name -eq 'pwsh' } + $rootPath = Split-Path -Path $pwshPath.FullName -Parent + Write-Verbose -Verbose "Setting vso[task.setvariable variable=DropRootPath]$rootPath" + Write-Host "##vso[task.setvariable variable=DropRootPath]$rootPath" + displayName: Set drop root path + + - template: /.pipelines/templates/obp-file-signing.yml@self + parameters: + binPath: $(DropRootPath) + + - template: /.pipelines/templates/step/finalize.yml@self diff --git a/.pipelines/templates/mac.yml b/.pipelines/templates/mac.yml new file mode 100644 index 00000000000..7542ffad4c1 --- /dev/null +++ b/.pipelines/templates/mac.yml @@ -0,0 +1,132 @@ +parameters: + buildArchitecture: 'x64' +jobs: +- job: build_macOS_${{ parameters.buildArchitecture }} + displayName: Build macOS ${{ parameters.buildArchitecture }} + condition: succeeded() + pool: + type: linux + isCustom: true + name: Azure Pipelines + vmImage: 'macOS-latest' + + variables: + - name: HOMEBREW_NO_ANALYTICS + value: 1 + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none + - group: DotNetPrivateBuildAccess + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' + - name: ob_sdl_binskim_enabled + value: true + - name: ob_sdl_credscan_suppressionsfileforartifacts + value: $(Build.SourcesDirectory)/PowerShell/.config/suppress.json + steps: + - checkout: self + clean: true + env: + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase + + - template: /.pipelines/templates/SetVersionVariables.yml@self + parameters: + ReleaseTagVar: $(ReleaseTagVar) + - pwsh: | + # create folder + sudo mkdir "$(Agent.TempDirectory)/PowerShell" + # make the current user the owner + sudo chown $env:USER "$(Agent.TempDirectory)/PowerShell" + displayName: 'Create $(Agent.TempDirectory)/PowerShell' + - template: /.pipelines/templates/cloneToOfficialPath.yml@self + parameters: + nativePathRoot: '$(Agent.TempDirectory)' + - pwsh: | + tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 -location $(PowerShellRoot) -BootStrap + displayName: 'Bootstrap VM' + env: + __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) + - template: /.pipelines/templates/insert-nuget-config-azfeed.yml@self + parameters: + repoRoot: $(PowerShellRoot) + - pwsh: | + $env:AzDevOpsFeedPAT2 = '$(AzDevOpsFeedPAT2)' + # Add -SkipReleaseChecks as a mitigation to unblock release. + # macos-10.15 does not allow creating a folder under root. Hence, moving the folder. + $(Build.SourcesDirectory)/tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 -ReleaseTag $(ReleaseTagVar) -Destination $(System.ArtifactsDirectory) -Symbols -location $(PowerShellRoot) -Build -ArtifactName macosBinResults -Runtime 'osx-${{ parameters.buildArchitecture }}' -SkipReleaseChecks + $env:AzDevOpsFeedPAT2 = $null + displayName: 'Build' + env: + __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) + - template: /.pipelines/templates/step/finalize.yml@self + +- job: sign_${{ parameters.buildArchitecture }} + displayName: Sign_macOS_${{ parameters.buildArchitecture }} + condition: succeeded() + dependsOn: build_macOS_${{ parameters.buildArchitecture }} + pool: + type: windows + variables: + - name: NugetSecurityAnalysisWarningLevel + value: none + - group: DotNetPrivateBuildAccess + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' + - name: ob_sdl_codeSignValidation_enabled + value: true + - name: ob_sdl_tsa_configFile + value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json + - name: ob_sdl_credscan_suppressionsFile + value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json + - name: BuildArchitecture + value: ${{ parameters.buildArchitecture }} + - name: ob_sdl_codeql_compiled_enabled + value: false + - name: ob_sdl_sbom_packageName + value: 'Microsoft.Powershell.Windows.${{parameters.buildArchitecture}}' + + steps: + - checkout: self + clean: true + env: + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase + + - template: /.pipelines/templates/SetVersionVariables.yml@self + parameters: + ReleaseTagVar: $(ReleaseTagVar) + + - template: /.pipelines/templates/cloneToOfficialPath.yml@self + + - task: DownloadPipelineArtifact@2 + inputs: + artifact: 'macosBinResults' + path: '$(Pipeline.Workspace)\Symbols' + displayName: Download build + + - pwsh: | + Get-ChildItem "$(Pipeline.Workspace)\*" -Recurse + displayName: 'Capture Downloaded Artifacts' + # Diagnostics is not critical it passes every time it runs + continueOnError: true + + - pwsh: | + $runtime = '$(BuildArchitecture)' + Write-Host "sending.. vso[task.setvariable variable=Runtime]$runtime" + Write-Host "##vso[task.setvariable variable=Runtime]$runtime" + + $zipPath = Get-Item '$(Pipeline.Workspace)\Symbols\*symbol*${{ parameters.buildArchitecture }}*.zip' -Verbose + Write-Verbose -Verbose "Zip Path: $zipPath" + + $expandedFolder = $zipPath.BaseName + Expand-Archive -Path $zipPath -Destination "$(Pipeline.Workspace)\$expandedFolder" -Force + $rootPath = "$(Pipeline.Workspace)\$expandedFolder" + Write-Verbose -Verbose "Setting vso[task.setvariable variable=DropRootPath]$rootPath" + Write-Host "##vso[task.setvariable variable=DropRootPath]$rootPath" + displayName: Expand symbols zip + + - template: /.pipelines/templates/obp-file-signing.yml@self + parameters: + binPath: $(DropRootPath) + + - template: /.pipelines/templates/step/finalize.yml@self diff --git a/.pipelines/templates/obp-file-signing.yml b/.pipelines/templates/obp-file-signing.yml new file mode 100644 index 00000000000..06cd46dec29 --- /dev/null +++ b/.pipelines/templates/obp-file-signing.yml @@ -0,0 +1,152 @@ +parameters: + binPath: '$(ob_outputDirectory)' + +steps: +- pwsh: | + $fullSymbolsFolder = '${{ parameters.binPath }}' + Write-Verbose -Verbose "fullSymbolsFolder == $fullSymbolsFolder" + Get-ChildItem -Recurse $fullSymbolsFolder | Select-Object -ExpandProperty FullName | Write-Verbose -Verbose + $filesToSignDirectory = "$(Pipeline.Workspace)/toBeSigned" + if ((Test-Path -Path $filesToSignDirectory)) { + Remove-Item -Path $filesToSignDirectory -Recurse -Force + } + $null = New-Item -ItemType Directory -Path $filesToSignDirectory -Force + + $itemsToCopyWithRecurse = @( + "$($fullSymbolsFolder)/*.ps1" + "$($fullSymbolsFolder)/Microsoft.PowerShell*.dll" + ) + $itemsToCopy = @{ + "$($fullSymbolsFolder)/*.ps1" = "" + "$($fullSymbolsFolder)/Modules/Microsoft.PowerShell.Host/Microsoft.PowerShell.Host.psd1" = "Modules/Microsoft.PowerShell.Host" + "$($fullSymbolsFolder)/Modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1" = "Modules/Microsoft.PowerShell.Management" + "$($fullSymbolsFolder)/Modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1" = "Modules/Microsoft.PowerShell.Security" + "$($fullSymbolsFolder)/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1" = "Modules/Microsoft.PowerShell.Utility" + "$($fullSymbolsFolder)/pwsh.dll" = "" + "$($fullSymbolsFolder)/System.Management.Automation.dll" = "" + } + ## Windows only modules + if('$(ArtifactPlatform)' -eq 'windows') { + $itemsToCopy += @{ + "$($fullSymbolsFolder)/pwsh.exe" = "" + "$($fullSymbolsFolder)/Microsoft.Management.Infrastructure.CimCmdlets.dll" = "" + "$($fullSymbolsFolder)/Microsoft.WSMan.*.dll" = "" + "$($fullSymbolsFolder)/Modules/CimCmdlets/CimCmdlets.psd1" = "Modules/CimCmdlets" + "$($fullSymbolsFolder)/Modules/Microsoft.PowerShell.Diagnostics/Diagnostics.format.ps1xml" = "Modules/Microsoft.PowerShell.Diagnostics" + "$($fullSymbolsFolder)/Modules/Microsoft.PowerShell.Diagnostics/Event.format.ps1xml" = "Modules/Microsoft.PowerShell.Diagnostics" + "$($fullSymbolsFolder)/Modules/Microsoft.PowerShell.Diagnostics/GetEvent.types.ps1xml" = "Modules/Microsoft.PowerShell.Diagnostics" + "$($fullSymbolsFolder)/Modules/Microsoft.PowerShell.Security/Security.types.ps1xml" = "Modules/Microsoft.PowerShell.Security" + "$($fullSymbolsFolder)/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1" = "Modules/Microsoft.PowerShell.Diagnostics" + "$($fullSymbolsFolder)/Modules/Microsoft.WSMan.Management/Microsoft.WSMan.Management.psd1" = "Modules/Microsoft.WSMan.Management" + "$($fullSymbolsFolder)/Modules/Microsoft.WSMan.Management/WSMan.format.ps1xml" = "Modules/Microsoft.WSMan.Management" + "$($fullSymbolsFolder)/Modules/PSDiagnostics/PSDiagnostics.ps?1" = "Modules/PSDiagnostics" + } + } + + $itemsToExclude = @( + # This package is retrieved from https://www.github.com/powershell/MarkdownRender + "$($fullSymbolsFolder)/Microsoft.PowerShell.MarkdownRender.dll" + ) + + if('$(ArtifactPlatform)' -eq 'linux' -or '$(ArtifactPlatform)' -eq 'macos') { + $itemsToExclude += "$($fullSymbolsFolder)/pwsh" + } + + Write-Verbose -verbose "recursively copying $($itemsToCopyWithRecurse | out-string) to $filesToSignDirectory" + Copy-Item -Path $itemsToCopyWithRecurse -Destination $filesToSignDirectory -Recurse -verbose -exclude $itemsToExclude + Write-Verbose -verbose "recursive copy done." + + foreach($pattern in $itemsToCopy.Keys) { + $destinationFolder = Join-Path $filesToSignDirectory -ChildPath $itemsToCopy.$pattern + $null = New-Item -ItemType Directory -Path $destinationFolder -Force + Write-Verbose -verbose "copying $pattern to $destinationFolder" + + if (-not (Test-Path -Path $pattern)) { + Write-Verbose -verbose "No files found for pattern $pattern" + continue + } + + Copy-Item -Path $pattern -Destination $destinationFolder -Recurse -verbose + } + + Write-Verbose -verbose "copying done." + Write-Verbose -verbose "Files to be signed at: $filesToSignDirectory" + + Get-ChildItem -Recurse -File $filesToSignDirectory | Select-Object -Property FullName + displayName: 'Prepare files to be signed' + +- task: onebranch.pipeline.signing@1 + displayName: Sign 1st party files + inputs: + command: 'sign' + signing_profile: external_distribution + files_to_sign: '**\*.psd1;**\*.psm1;**\*.ps1xml;**\*.ps1;**\*.dll;**\*.exe;**\pwsh' + search_root: $(Pipeline.Workspace)/toBeSigned + +- pwsh : | + Get-ChildItem -Path env: + displayName: Capture environment + +- pwsh: | + Import-Module $(PowerShellRoot)/build.psm1 -Force + Import-Module $(PowerShellRoot)/tools/packaging -Force + + $BuildPath = (Get-Item '${{ parameters.binPath }}').FullName + Write-Verbose -Verbose -Message "BuildPath: $BuildPath" + + ## copy all files to be signed to build folder + Update-PSSignedBuildFolder -BuildPath $BuildPath -SignedFilesPath '$(Pipeline.Workspace)/toBeSigned' + + $dlls = Get-ChildItem $BuildPath/*.dll, $BuildPath/*.exe -Recurse + $signatures = $dlls | Get-AuthenticodeSignature + $missingSignatures = $signatures | Where-Object { $_.status -eq 'notsigned' -or $_.SignerCertificate.Issuer -notmatch '^CN=Microsoft.*'}| select-object -ExpandProperty Path + + Write-Verbose -verbose "to be signed:`r`n $($missingSignatures | Out-String)" + + $filesToSignDirectory = "$(Pipeline.Workspace)/thirdPartyToBeSigned" + if (Test-Path $filesToSignDirectory) { + Remove-Item -Path $filesToSignDirectory -Recurse -Force + } + $null = New-Item -ItemType Directory -Path $filesToSignDirectory -Force -Verbose + + $missingSignatures | ForEach-Object { + $pathWithoutLeaf = Split-Path $_ + $relativePath = $pathWithoutLeaf.replace($BuildPath,'') + Write-Verbose -Verbose -Message "relativePath: $relativePath" + $targetDirectory = Join-Path -Path $filesToSignDirectory -ChildPath $relativePath + Write-Verbose -Verbose -Message "targetDirectory: $targetDirectory" + if(!(Test-Path $targetDirectory)) + { + $null = New-Item -ItemType Directory -Path $targetDirectory -Force -Verbose + } + Copy-Item -Path $_ -Destination $targetDirectory + } + displayName: Create ThirdParty Signing Folder + +- task: onebranch.pipeline.signing@1 + displayName: Sign 3rd Party files + inputs: + command: 'sign' + signing_profile: 135020002 + files_to_sign: '**\*.dll;**\*.exe' + search_root: $(Pipeline.Workspace)/thirdPartyToBeSigned + +- pwsh: | + Get-ChildItem '$(Pipeline.Workspace)/thirdPartyToBeSigned/*' + displayName: Capture ThirdParty Signed files + +- pwsh: | + Import-Module '$(PowerShellRoot)/build.psm1' -Force + Import-Module '$(PowerShellRoot)/tools/packaging' -Force + $pathForUpload = New-Item -ItemType Directory -Path '$(ob_outputDirectory)/Signed-$(Runtime)' -Force + Write-Verbose -Verbose -Message "pathForUpload: $pathForUpload" + Copy-Item -Path '${{ parameters.binPath }}\*' -Destination $pathForUpload -Recurse -Force -Verbose + Write-Verbose -Verbose -Message "Files copied to $pathForUpload" + + Write-Verbose "Copying third party signed files to the build folder" + $thirdPartySignedFilesPath = (Get-Item '$(Pipeline.Workspace)/thirdPartyToBeSigned').FullName + Update-PSSignedBuildFolder -BuildPath $pathForUpload -SignedFilesPath $thirdPartySignedFilesPath + + displayName: 'Copy signed files for upload' + +- template: /.pipelines/templates/step/finalize.yml@self diff --git a/.pipelines/templates/shouldSign.yml b/.pipelines/templates/shouldSign.yml new file mode 100644 index 00000000000..3f024898945 --- /dev/null +++ b/.pipelines/templates/shouldSign.yml @@ -0,0 +1,23 @@ +steps: +- powershell: | + $shouldSign = $true + $authenticodeCert = 'CP-230012' + $msixCert = 'CP-230012' + if($env:IS_DAILY -eq 'true') + { + $authenticodeCert = 'CP-460906' + } + if($env:SKIP_SIGNING -eq 'Yes') + { + $shouldSign = $false + } + $vstsCommandString = "vso[task.setvariable variable=SHOULD_SIGN]$($shouldSign.ToString().ToLowerInvariant())" + Write-Host "sending " + $vstsCommandString + Write-Host "##$vstsCommandString" + $vstsCommandString = "vso[task.setvariable variable=MSIX_CERT]$($msixCert)" + Write-Host "sending " + $vstsCommandString + Write-Host "##$vstsCommandString" + $vstsCommandString = "vso[task.setvariable variable=AUTHENTICODE_CERT]$($authenticodeCert)" + Write-Host "sending " + $vstsCommandString + Write-Host "##$vstsCommandString" + displayName: 'Set SHOULD_SIGN Variable' diff --git a/.pipelines/templates/step/finalize.yml b/.pipelines/templates/step/finalize.yml new file mode 100644 index 00000000000..78e0341c829 --- /dev/null +++ b/.pipelines/templates/step/finalize.yml @@ -0,0 +1,6 @@ +# This was used before migrating to OneBranch to deal with one of the SDL taks from failing with a warning instead of an error. +steps: +- pwsh: | + throw "Jobs with an Issue will not work for release. Please fix the issue and try again." + displayName: Check for SucceededWithIssues + condition: eq(variables['Agent.JobStatus'],'SucceededWithIssues') diff --git a/.pipelines/templates/testartifacts.yml b/.pipelines/templates/testartifacts.yml new file mode 100644 index 00000000000..883d3cd21c6 --- /dev/null +++ b/.pipelines/templates/testartifacts.yml @@ -0,0 +1,108 @@ +jobs: +- job: build_testartifacts_win + variables: + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none + - group: DotNetPrivateBuildAccess + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' + - name: ob_sdl_tsa_configFile + value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json + - name: ob_sdl_credscan_suppressionsFile + value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json + displayName: Build windows test artifacts + condition: succeeded() + pool: + type: windows + steps: + - checkout: self + clean: true + - template: /.pipelines/templates/insert-nuget-config-azfeed.yml@self + parameters: + repoRoot: $(Build.SourcesDirectory) + - pwsh: | + Import-Module $(Build.SourcesDirectory)/PowerShell/build.psm1 + Start-PSBootstrap + displayName: Bootstrap + env: + __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) + - pwsh: | + Import-Module $(Build.SourcesDirectory)/PowerShell/build.psm1 + function BuildTestPackage([string] $runtime) + { + Write-Verbose -Verbose "Starting to build package for $runtime" + New-TestPackage -Destination $(System.ArtifactsDirectory) -Runtime $runtime + if (-not (Test-Path $(System.ArtifactsDirectory)/TestPackage.zip)) + { + throw "Test Package was not found at: $(System.ArtifactsDirectory)" + } + switch ($runtime) + { + win7-x64 { $packageName = "TestPackage-win-x64.zip" } + win7-x86 { $packageName = "TestPackage-win-x86.zip" } + win-arm64 { $packageName = "TestPackage-win-arm64.zip" } + } + Rename-Item $(System.ArtifactsDirectory)/TestPackage.zip $packageName + Write-Host "##vso[artifact.upload containerfolder=testArtifacts;artifactname=testArtifacts]$(System.ArtifactsDirectory)/$packageName" + } + BuildTestPackage -runtime win7-x64 + BuildTestPackage -runtime win7-x86 + BuildTestPackage -runtime win-arm64 + displayName: Build test package and upload + retryCountOnTaskFailure: 1 +- job: build_testartifacts_nonwin + variables: + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none + - group: DotNetPrivateBuildAccess + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' + displayName: Build non-windows test artifacts + condition: succeeded() + pool: + type: linux + steps: + - checkout: self + clean: true + - template: /.pipelines/templates/insert-nuget-config-azfeed.yml@self + parameters: + repoRoot: $(Build.SourcesDirectory) + - pwsh: | + Import-Module $(Build.SourcesDirectory)/PowerShell/build.psm1 + Start-PSBootstrap + displayName: Bootstrap + env: + __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) + - pwsh: | + Import-Module $(Build.SourcesDirectory)/PowerShell/build.psm1 + function BuildTestPackage([string] $runtime) + { + Write-Verbose -Verbose "Starting to build package for $runtime" + New-TestPackage -Destination $(System.ArtifactsDirectory) -Runtime $runtime + if (-not (Test-Path $(System.ArtifactsDirectory)/TestPackage.zip)) + { + throw "Test Package was not found at: $(System.ArtifactsDirectory)" + } + switch ($runtime) + { + linux-x64 { $packageName = "TestPackage-linux-x64.zip" } + linux-arm { $packageName = "TestPackage-linux-arm.zip" } + linux-arm64 { $packageName = "TestPackage-linux-arm64.zip" } + osx-x64 { $packageName = "TestPackage-macOS.zip" } + linux-musl-x64 { $packageName = "TestPackage-alpine-x64.zip"} + } + Rename-Item $(System.ArtifactsDirectory)/TestPackage.zip $packageName + Write-Host "##vso[artifact.upload containerfolder=testArtifacts;artifactname=testArtifacts]$(System.ArtifactsDirectory)/$packageName" + } + BuildTestPackage -runtime linux-x64 + BuildTestPackage -runtime linux-arm + BuildTestPackage -runtime linux-arm64 + BuildTestPackage -runtime osx-x64 + BuildTestPackage -runtime linux-musl-x64 + displayName: Build test package and upload + retryCountOnTaskFailure: 1 + - template: /.pipelines/templates/step/finalize.yml@self diff --git a/.pipelines/templates/windows-hosted-build.yml b/.pipelines/templates/windows-hosted-build.yml new file mode 100644 index 00000000000..1f100783a20 --- /dev/null +++ b/.pipelines/templates/windows-hosted-build.yml @@ -0,0 +1,126 @@ +parameters: + Architecture: 'x64' + BuildConfiguration: 'release' + JobName: 'build_windows' + +jobs: +- job: build_windows_${{ parameters.Architecture }}_${{ parameters.BuildConfiguration }} + displayName: Build_Windows_${{ parameters.Architecture }}_${{ parameters.BuildConfiguration }} + condition: succeeded() + pool: + type: windows + variables: + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none + - name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE + value: 1 + - group: DotNetPrivateBuildAccess + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' + - name: ob_sdl_codeSignValidation_enabled + value: false + - name: ob_sdl_binskim_enabled + value: true + - name: ob_sdl_tsa_configFile + value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json + - name: ob_sdl_credscan_suppressionsFile + value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json + - name: Architecture + value: ${{ parameters.Architecture }} + - name: BuildConfiguration + value: ${{ parameters.BuildConfiguration }} + - name: ob_sdl_sbom_packageName + value: 'Microsoft.Powershell.Windows.${{ parameters.Architecture }}' + - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}: + - name: ob_sdl_codeql_compiled_enabled + value: true + + steps: + - checkout: self + clean: true + env: + ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase + + - template: /.pipelines/templates/SetVersionVariables.yml@self + parameters: + ReleaseTagVar: $(ReleaseTagVar) + + - template: /.pipelines/templates/cloneToOfficialPath.yml@self + + - template: /.pipelines/templates/insert-nuget-config-azfeed.yml@self + parameters: + repoRoot: $(PowerShellRoot) + + - task: CodeQL3000Init@0 # Add CodeQL Init task right before your 'Build' step. + condition: eq(variables['Build.SourceBranch'], 'refs/heads/master') + env: + ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + inputs: + Enabled: true + AnalyzeInPipeline: true + Language: csharp + + - pwsh: | + $runtime = switch ($env:Architecture) + { + "x64" { "win7-x64" } + "x86" { "win7-x86" } + "arm64" { "win-arm64" } + "fxdependent" { "fxdependent" } + "fxdependentWinDesktop" { "fxdependent-win-desktop" } + } + + $params = @{} + if ($env:BuildConfiguration -eq 'minSize') { + $params['ForMinimalSize'] = $true + } + + $vstsCommandString = "vso[task.setvariable variable=Runtime]$runtime" + Write-Host ("sending " + $vstsCommandString) + Write-Host "##$vstsCommandString" + + Write-Verbose -Message "Building PowerShell with Runtime: $runtime for '$env:BuildConfiguration' configuration" + Import-Module -Name $(PowerShellRoot)/build.psm1 -Force + $buildWithSymbolsPath = New-Item -ItemType Directory -Path $(Pipeline.Workspace)/Symbols_$(Architecture) -Force + + Start-PSBootstrap -Package + $null = New-Item -ItemType Directory -Path $buildWithSymbolsPath -Force -Verbose + Start-PSBuild -Runtime $runtime -Configuration Release -Output $buildWithSymbolsPath -Clean -PSModuleRestore @params + + Write-Verbose -Verbose "Verifying pdbs exist in build folder" + $pdbs = Get-ChildItem -Path $buildWithSymbolsPath -Recurse -Filter *.pdb + if ($pdbs.Count -eq 0) { + Write-Error -Message "No pdbs found in build folder" + } + else { + Write-Verbose -Verbose "Found $($pdbs.Count) pdbs in build folder" + $pdbs | ForEach-Object { + Write-Verbose -Verbose "Pdb: $($_.FullName)" + } + } + + Write-Verbose -Verbose "Completed building PowerShell for '$env:BuildConfiguration' configuration" + displayName: 'Build Windows Universal - $(Architecture)-$(BuildConfiguration) Symbols folder' + env: + __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) + ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + + - task: CodeQL3000Finalize@0 # Add CodeQL Finalize task right after your 'Build' step. + condition: eq(variables['Build.SourceBranch'], 'refs/heads/master') + env: + ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + + - pwsh: | + $platform = 'windows' + $vstsCommandString = "vso[task.setvariable variable=ArtifactPlatform]$platform" + Write-Host ("sending " + $vstsCommandString) + Write-Host "##$vstsCommandString" + displayName: Set artifact platform + + - template: /.pipelines/templates/obp-file-signing.yml@self + parameters: + binPath: '$(Pipeline.Workspace)/Symbols_$(Architecture)' + + - template: /.pipelines/templates/step/finalize.yml@self diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index a6575088090..9f78972f72e 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -889,17 +889,54 @@ function Update-PSSignedBuildFolder [string[]] $RemoveFilter = ('*.pdb', '*.zip', '*.r2rmap') ) + $BuildPathNormalized = (Get-Item $BuildPath).FullName + $SignedFilesPathNormalized = (Get-Item $SignedFilesPath).FullName + + Write-Verbose -Verbose "BuildPath = $BuildPathNormalized" + Write-Verbose -Verbose "SignedFilesPath = $signedFilesPath" + # Replace unsigned binaries with signed - $signedFilesFilter = Join-Path -Path $SignedFilesPath -ChildPath '*' + $signedFilesFilter = Join-Path -Path $SignedFilesPathNormalized -ChildPath '*' + Write-Verbose -Verbose "signedFilesFilter = $signedFilesFilter" + Get-ChildItem -Path $signedFilesFilter -Recurse -File | Select-Object -ExpandProperty FullName | ForEach-Object -Process { - $relativePath = $_.ToLowerInvariant().Replace($SignedFilesPath.ToLowerInvariant(),'') - $destination = Join-Path -Path $BuildPath -ChildPath $relativePath + Write-Verbose -Verbose "Processing $_" + + # Agents seems to be on a case sensitive file system + if ($IsLinux) { + $relativePath = $_.Replace($SignedFilesPathNormalized, '') + } else { + $relativePath = $_.ToLowerInvariant().Replace($SignedFilesPathNormalized.ToLowerInvariant(), '') + } + + Write-Verbose -Verbose "relativePath = $relativePath" + $destination = (Get-Item (Join-Path -Path $BuildPathNormalized -ChildPath $relativePath)).FullName + Write-Verbose -Verbose "destination = $destination" Write-Log "replacing $destination with $_" + + if (-not (Test-Path $destination)) { + $parent = Split-Path -Path $destination -Parent + $exists = Test-Path -Path $parent + + if ($exists) { + Write-Verbose -Verbose "Parent:" + Get-ChildItem -Path $parent | Select-Object -ExpandProperty FullName | Write-Verbose -Verbose + } + + Write-Error "File not found: $destination, parent - $parent exists: $exists" + } + + $signature = Get-AuthenticodeSignature -FilePath $_ + + if ($signature.Status -ne 'Valid') { + Write-Error "Invalid signature for $_" + } + Copy-Item -Path $_ -Destination $destination -Force } foreach($filter in $RemoveFilter) { - $removePath = Join-Path -Path $BuildPath -ChildPath $filter + $removePath = Join-Path -Path $BuildPathNormalized -ChildPath $filter Remove-Item -Path $removePath -Recurse -Force } } diff --git a/tools/releaseBuild/setReleaseTag.ps1 b/tools/releaseBuild/setReleaseTag.ps1 index 8d6a8c3eefe..60af8c4d749 100644 --- a/tools/releaseBuild/setReleaseTag.ps1 +++ b/tools/releaseBuild/setReleaseTag.ps1 @@ -48,7 +48,14 @@ function New-BuildInfoJson { Write-Verbose -Message "$vstsCommandString" -Verbose Write-Host -Object "##$vstsCommandString" + if (-not (Test-Path $env:ob_outputDirectory)) { + $null = New-Item -Path $env:ob_outputDirectory -ItemType Directory -Force -Verbose + } + + # Upload for ADO pipelines Write-Host "##vso[artifact.upload containerfolder=BuildInfoJson;artifactname=BuildInfoJson]$resolvedPath" + # Copy to location where OneBranch Pipelines uploads from + Copy-Item $resolvedPath -Destination $env:ob_outputDirectory -Force -Verbose } # Script to set the release tag based on the branch name if it is not set or it is "fromBranch" From 6b10aa21b8de6c597e5751da40a6bd227166b1c2 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 4 Apr 2024 18:24:04 -0400 Subject: [PATCH 09/18] [release/v7.4.2] Update `PSReadLine` to `v2.3.5` for the next `v7.4.x` servicing release (#21414) (#21427) --- src/Modules/PSGalleryModules.csproj | 2 +- tools/packaging/boms/windows.json | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Modules/PSGalleryModules.csproj b/src/Modules/PSGalleryModules.csproj index 0dd1a39c68f..2af1ab9175b 100644 --- a/src/Modules/PSGalleryModules.csproj +++ b/src/Modules/PSGalleryModules.csproj @@ -15,7 +15,7 @@ - + diff --git a/tools/packaging/boms/windows.json b/tools/packaging/boms/windows.json index 4ec63b872c2..e172397c1bb 100644 --- a/tools/packaging/boms/windows.json +++ b/tools/packaging/boms/windows.json @@ -907,6 +907,10 @@ "Pattern": "Modules\\PSReadLine\\_manifest\\spdx_2.2\\manifest.cat", "FileType": "NonProduct" }, + { + "Pattern": "Modules\\PSReadLine\\.signature.p7s", + "FileType": "NonProduct" + }, { "Pattern": "mscordaccore_*.dll", "FileType": "NonProduct" From c16cfe8f87253db9f2eb9aeb6c20a4ce2214a445 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 4 Apr 2024 18:24:35 -0400 Subject: [PATCH 10/18] [release/v7.4.2] Fix regression -Tail 0 -Wait (#20734) (#21418) --- .../commands/management/GetContentCommand.cs | 4 ++-- .../Get-Content.Tests.ps1 | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetContentCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetContentCommand.cs index 4e83eda905f..a9d8772a5fc 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetContentCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetContentCommand.cs @@ -87,7 +87,7 @@ protected override void ProcessRecord() return; } - if (TotalCount == 0 || Tail == 0) + if (TotalCount == 0) { // Don't read anything return; @@ -118,7 +118,7 @@ protected override void ProcessRecord() // as reading forwards. So we read forwards in this case. // If Tail is positive, we seek the right position. Or, if the seek failed // because of an unsupported encoding, we scan forward to get the tail content. - if (Tail > 0) + if (Tail >= 0) { bool seekSuccess = false; diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 index 5e8e258b85a..02b6f79fbc4 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 @@ -283,6 +283,16 @@ Describe "Get-Content" -Tags "CI" { Get-Content -Path $testPath -Tail 0 | Should -BeNullOrEmpty } + It "Should wait for content when using -Tail 0 and -Wait" { + $testValues = @(1,2,3) + $Job = Start-Job -ScriptBlock {Get-Content -Path $using:testPath -Tail 0 -Wait} + Start-Sleep -Seconds 3 + Add-Content -Value $testValues -Path $testPath + Start-Sleep -Seconds 3 + Compare-Object -ReferenceObject $testValues -DifferenceObject ($Job | Receive-Job) | Should -BeNullOrEmpty + $Job | Remove-Job -Force + } + It "Should throw TailAndHeadCannotCoexist when both -Tail and -TotalCount are used" { { Get-Content -Path $testPath -Tail 1 -TotalCount 1 -ErrorAction Stop From b0692c1f0789f786b09eedbab7b36bdf7178d8bd Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Fri, 5 Apr 2024 13:55:17 -0400 Subject: [PATCH 11/18] [release/v7.4.2] Revert "Adjust PUT method behavior to POST one for default content type in WebCmdlets" (#21049) (#21428) Co-authored-by: Steve Lee --- .../Common/WebRequestPSCmdlet.Common.cs | 2 +- .../WebCmdlets.Tests.ps1 | 21 ++++++------------- 2 files changed, 7 insertions(+), 16 deletions(-) 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 981bdd08fdd..eb1b0dccc1f 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 @@ -1172,7 +1172,7 @@ internal virtual void FillRequestStream(HttpRequestMessage request) { WebSession.ContentHeaders[HttpKnownHeaderNames.ContentType] = ContentType; } - else if (request.Method == HttpMethod.Post || request.Method == HttpMethod.Put) + else if (request.Method == HttpMethod.Post) { // Win8:545310 Invoke-WebRequest does not properly set MIME type for POST WebSession.ContentHeaders.TryGetValue(HttpKnownHeaderNames.ContentType, out string contentType); diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index cd356071b48..7fac6fad324 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -795,14 +795,9 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" { ($result.Output.Content | ConvertFrom-Json).method | Should -Be "TEST" } - It "Validate Invoke-WebRequest default ContentType for CustomMethod " -TestCases @( - @{method = "POST"} - @{method = "PUT"} - ) { - param($method) - - $uri = Get-WebListenerUrl -Test $method - $command = "Invoke-WebRequest -Uri '$uri' -CustomMethod $method -Body 'testparam=testvalue'" + It "Validate Invoke-WebRequest default ContentType for CustomMethod POST" { + $uri = Get-WebListenerUrl -Test 'Post' + $command = "Invoke-WebRequest -Uri '$uri' -CustomMethod POST -Body 'testparam=testvalue'" $result = ExecuteWebCommand -command $command $jsonResult = $result.Output.Content | ConvertFrom-Json $jsonResult.form.testparam | Should -Be "testvalue" @@ -2858,13 +2853,9 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" { $result.Output.method | Should -Be "TEST" } - It "Validate Invoke-RestMethod default ContentType for CustomMethod " -TestCases @( - @{method = "POST"} - @{method = "PUT"} - ) { - param($method) - $uri = Get-WebListenerUrl -Test $method - $command = "Invoke-RestMethod -Uri '$uri' -CustomMethod $method -Body 'testparam=testvalue'" + It "Validate Invoke-RestMethod default ContentType for CustomMethod POST" { + $uri = Get-WebListenerUrl -Test 'Post' + $command = "Invoke-RestMethod -Uri '$uri' -CustomMethod POST -Body 'testparam=testvalue'" $result = ExecuteWebCommand -command $command $result.Output.form.testparam | Should -Be "testvalue" $result.Output.Headers.'Content-Type' | Should -Be "application/x-www-form-urlencoded" From 89c9bb64ef97c03a8ca9fd6e79572bbc195d399f Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Fri, 5 Apr 2024 19:47:03 +0000 Subject: [PATCH 12/18] Merged PR 30659: Backport #21238, #21239, #21408, #21415 - and update SDK + dependencies and cgmanifest --- .config/tsaoptions.json | 8 ++++++- ...werShell-Coordinated_Packages-Official.yml | 13 ++--------- .../templates/insert-nuget-config-azfeed.yml | 4 ++-- .pipelines/templates/linux.yml | 12 +++++++--- .pipelines/templates/mac.yml | 23 +++++++++++-------- .pipelines/templates/windows-hosted-build.yml | 5 ++++ build.psm1 | 1 + global.json | 2 +- ...crosoft.PowerShell.Commands.Utility.csproj | 2 +- .../Microsoft.PowerShell.SDK.csproj | 5 ++-- .../PSVersionInfoGenerator.csproj | 7 +++--- test/xUnit/xUnit.tests.csproj | 4 ++-- tools/cgmanifest.json | 12 +++++----- .../templates/compliance/apiscan.yml | 1 - 14 files changed, 56 insertions(+), 43 deletions(-) diff --git a/.config/tsaoptions.json b/.config/tsaoptions.json index 90d4db36755..bd2a6a00984 100644 --- a/.config/tsaoptions.json +++ b/.config/tsaoptions.json @@ -1,5 +1,11 @@ { "instanceUrl": "https://msazure.visualstudio.com", "projectName": "One", - "areaPath": "One\\MGMT\\Compute\\Powershell\\Powershell\\PowerShell Core" + "areaPath": "One\\MGMT\\Compute\\Powershell\\Powershell\\PowerShell Core", + "notificationAliases": [ + "adityap@microsoft.com", + "dongbow@microsoft.com", + "pmeinecke@microsoft.com", + "tplunk@microsoft.com" + ] } diff --git a/.pipelines/PowerShell-Coordinated_Packages-Official.yml b/.pipelines/PowerShell-Coordinated_Packages-Official.yml index 432a627b0d0..adc614f3284 100644 --- a/.pipelines/PowerShell-Coordinated_Packages-Official.yml +++ b/.pipelines/PowerShell-Coordinated_Packages-Official.yml @@ -1,14 +1,5 @@ name: UnifiedPackageBuild-$(Build.BuildId) -trigger: - branches: - include: - - master - - release* -pr: - branches: - include: - - master - - release* +trigger: none parameters: - name: ForceAzureBlobDelete @@ -194,7 +185,7 @@ extends: parameters: Architecture: x64 BuildConfiguration: minSize - JobName: build_windows_x64_minSize + JobName: build_windows_x64_minSize_release - template: /.pipelines/templates/windows-hosted-build.yml@self parameters: Architecture: x86 diff --git a/.pipelines/templates/insert-nuget-config-azfeed.yml b/.pipelines/templates/insert-nuget-config-azfeed.yml index 2279c4839aa..19884080e46 100644 --- a/.pipelines/templates/insert-nuget-config-azfeed.yml +++ b/.pipelines/templates/insert-nuget-config-azfeed.yml @@ -5,7 +5,7 @@ steps: - pwsh: | $configPath = "${env:NugetConfigDir}/nuget.config" Import-Module ${{ parameters.repoRoot }}/build.psm1 -Force - New-NugetConfigFile -NugetFeedUrl $(AzDevOpsFeed) -UserName $(AzDevOpsFeedUserName) -ClearTextPAT $(AzDevOpsFeedPAT2) -FeedName AzDevOpsFeed -Destination "${env:NugetConfigDir}" + New-NugetConfigFile -NugetFeedUrl $(PowerShellCore_PublicPackages) -UserName $(AzDevOpsFeedUserName) -ClearTextPAT $(AzDevOpsFeedUserName) -FeedName AzDevOpsFeed -Destination "${env:NugetConfigDir}" if(-not (Test-Path $configPath)) { throw "nuget.config is not created" @@ -20,7 +20,7 @@ steps: - pwsh: | $configPath = "${env:NugetConfigDir}/nuget.config" Import-Module ${{ parameters.repoRoot }}/build.psm1 -Force - New-NugetConfigFile -NugetFeedUrl $(PSInternalNugetFeed) -UserName $(PSInternalNugetFeedUserName) -ClearTextPAT $(PSInternalNugetFeedPAT) -FeedName AzDevOpsFeed -Destination "${env:NugetConfigDir}" + New-NugetConfigFile -NugetFeedUrl $(PowerShellCore_PublicPackages) -UserName $(AzDevOpsFeedUserName) -ClearTextPAT $(AzDevOpsFeedUserName) -FeedName AzDevOpsFeed -Destination "${env:NugetConfigDir}" if(-not (Test-Path $configPath)) { throw "nuget.config is not created" diff --git a/.pipelines/templates/linux.yml b/.pipelines/templates/linux.yml index 134d581833d..0ab4f54e4f1 100644 --- a/.pipelines/templates/linux.yml +++ b/.pipelines/templates/linux.yml @@ -27,7 +27,7 @@ jobs: value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json - name: ob_sdl_credscan_suppressionsFile value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json - - name: BuildConfiguration + - name: BUILDCONFIGURATION value: ${{ parameters.BuildConfiguration }} - name: Runtime value: ${{ parameters.Runtime }} @@ -66,7 +66,8 @@ jobs: $runtime = $env:RUNTIME $params = @{} - if ($env:BuildConfiguration -eq 'minSize') { + if ($env:BUILDCONFIGURATION -eq 'minSize') { + Write-Verbose -Message "Building for minimal size" $params['ForMinimalSize'] = $true } @@ -78,6 +79,11 @@ jobs: $null = New-Item -ItemType Directory -Path $buildWithSymbolsPath -Force -Verbose Start-PSBuild -Runtime $runtime -Configuration Release -Output $buildWithSymbolsPath @params -Clean -PSModuleRestore + $outputPath = Join-Path '$(ob_outputDirectory)' 'psoptions' + $null = New-Item -ItemType Directory -Path $outputPath -Force + $psOptPath = "$outputPath/psoptions.json" + Save-PSOptions -PSOptionsPath $psOptPath + Write-Verbose -Verbose "Verifying pdbs exist in build folder" $pdbs = Get-ChildItem -Path $buildWithSymbolsPath -Recurse -Filter *.pdb if ($pdbs.Count -eq 0) { @@ -90,7 +96,7 @@ jobs: } } - Write-Verbose -Verbose "Completed building PowerShell for '$env:BuildConfiguration' configuration" + Write-Verbose -Verbose "Completed building PowerShell for '$env:BUILDCONFIGURATION' configuration" displayName: 'Build Linux - $(Runtime)' env: __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) diff --git a/.pipelines/templates/mac.yml b/.pipelines/templates/mac.yml index 7542ffad4c1..4b46cfff466 100644 --- a/.pipelines/templates/mac.yml +++ b/.pipelines/templates/mac.yml @@ -54,7 +54,17 @@ jobs: $env:AzDevOpsFeedPAT2 = '$(AzDevOpsFeedPAT2)' # Add -SkipReleaseChecks as a mitigation to unblock release. # macos-10.15 does not allow creating a folder under root. Hence, moving the folder. - $(Build.SourcesDirectory)/tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 -ReleaseTag $(ReleaseTagVar) -Destination $(System.ArtifactsDirectory) -Symbols -location $(PowerShellRoot) -Build -ArtifactName macosBinResults -Runtime 'osx-${{ parameters.buildArchitecture }}' -SkipReleaseChecks + + Import-Module ./build.psm1 -Force + Start-PSBuild -Runtime 'osx-${{ parameters.buildArchitecture }}' -Configuration Release -PSModuleRestore -Clean -Output $(OB_OUTPUTDIRECTORY) + $artifactName = "macosBinResults-${{ parameters.buildArchitecture }}" + + $psOptPath = "$(OB_OUTPUTDIRECTORY)/psoptions.json" + Save-PSOptions -PSOptionsPath $psOptPath + + # Since we are using custom pool for macOS, we need to use artifact.upload to publish the artifacts + Write-Host "##vso[artifact.upload containerfolder=$artifactName;artifactname=$artifactName]$(OB_OUTPUTDIRECTORY)" + $env:AzDevOpsFeedPAT2 = $null displayName: 'Build' env: @@ -84,7 +94,7 @@ jobs: - name: ob_sdl_codeql_compiled_enabled value: false - name: ob_sdl_sbom_packageName - value: 'Microsoft.Powershell.Windows.${{parameters.buildArchitecture}}' + value: 'Microsoft.Powershell.MacOS.${{parameters.buildArchitecture}}' steps: - checkout: self @@ -100,7 +110,7 @@ jobs: - task: DownloadPipelineArtifact@2 inputs: - artifact: 'macosBinResults' + artifact: 'macosBinResults-$(BuildArchitecture)' path: '$(Pipeline.Workspace)\Symbols' displayName: Download build @@ -115,12 +125,7 @@ jobs: Write-Host "sending.. vso[task.setvariable variable=Runtime]$runtime" Write-Host "##vso[task.setvariable variable=Runtime]$runtime" - $zipPath = Get-Item '$(Pipeline.Workspace)\Symbols\*symbol*${{ parameters.buildArchitecture }}*.zip' -Verbose - Write-Verbose -Verbose "Zip Path: $zipPath" - - $expandedFolder = $zipPath.BaseName - Expand-Archive -Path $zipPath -Destination "$(Pipeline.Workspace)\$expandedFolder" -Force - $rootPath = "$(Pipeline.Workspace)\$expandedFolder" + $rootPath = "$(Pipeline.Workspace)\Symbols" Write-Verbose -Verbose "Setting vso[task.setvariable variable=DropRootPath]$rootPath" Write-Host "##vso[task.setvariable variable=DropRootPath]$rootPath" displayName: Expand symbols zip diff --git a/.pipelines/templates/windows-hosted-build.yml b/.pipelines/templates/windows-hosted-build.yml index 1f100783a20..15ca7e9c587 100644 --- a/.pipelines/templates/windows-hosted-build.yml +++ b/.pipelines/templates/windows-hosted-build.yml @@ -89,6 +89,11 @@ jobs: $null = New-Item -ItemType Directory -Path $buildWithSymbolsPath -Force -Verbose Start-PSBuild -Runtime $runtime -Configuration Release -Output $buildWithSymbolsPath -Clean -PSModuleRestore @params + $outputPath = Join-Path '$(ob_outputDirectory)' 'psoptions' + $null = New-Item -ItemType Directory -Path $outputPath -Force + $psOptPath = "$outputPath/psoptions.json" + Save-PSOptions -PSOptionsPath $psOptPath + Write-Verbose -Verbose "Verifying pdbs exist in build folder" $pdbs = Get-ChildItem -Path $buildWithSymbolsPath -Recurse -Filter *.pdb if ($pdbs.Count -eq 0) { diff --git a/build.psm1 b/build.psm1 index 55110cd9cf6..162a5a5ef5b 100644 --- a/build.psm1 +++ b/build.psm1 @@ -2238,6 +2238,7 @@ function Start-PSBootstrap { # Install [fpm](https://github.com/jordansissel/fpm) and [ronn](https://github.com/rtomayko/ronn) if ($Package) { + Install-GlobalGem -Sudo $sudo -GemName "dotenv" -GemVersion "2.8.1" Install-GlobalGem -Sudo $sudo -GemName "ffi" -GemVersion "1.12.0" Install-GlobalGem -Sudo $sudo -GemName "fpm" -GemVersion "1.11.0" Install-GlobalGem -Sudo $sudo -GemName "ronn" -GemVersion "0.7.3" diff --git a/global.json b/global.json index d54915e8d4d..1ee82c3759c 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "8.0.101" + "version": "8.0.203" } } 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 e582c08ab89..c11c53fa925 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj +++ b/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj @@ -34,7 +34,7 @@ - + diff --git a/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj b/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj index 5945b00b2b4..328a4854492 100644 --- a/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj +++ b/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj @@ -16,6 +16,8 @@ + + @@ -35,8 +37,7 @@ - - + diff --git a/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj b/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj index 3adf1cc62ed..addeac43ab5 100644 --- a/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj +++ b/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj @@ -10,12 +10,11 @@ 11.0 true true + RS1035 - - - - + + diff --git a/test/xUnit/xUnit.tests.csproj b/test/xUnit/xUnit.tests.csproj index f89d12a7d5d..f31a43583e9 100644 --- a/test/xUnit/xUnit.tests.csproj +++ b/test/xUnit/xUnit.tests.csproj @@ -25,8 +25,8 @@ - - + + diff --git a/tools/cgmanifest.json b/tools/cgmanifest.json index a87727198fe..d9a7a7390ba 100644 --- a/tools/cgmanifest.json +++ b/tools/cgmanifest.json @@ -1,5 +1,4 @@ { - "$schema": "https://json.schemastore.org/component-detection-manifest.json", "Registrations": [ { "Component": { @@ -86,7 +85,7 @@ "Type": "nuget", "Nuget": { "Name": "Microsoft.Bcl.AsyncInterfaces", - "Version": "5.0.0" + "Version": "8.0.0" } }, "DevelopmentDependency": false @@ -126,7 +125,7 @@ "Type": "nuget", "Nuget": { "Name": "Microsoft.Extensions.ObjectPool", - "Version": "5.0.17" + "Version": "8.0.3" } }, "DevelopmentDependency": false @@ -226,7 +225,7 @@ "Type": "nuget", "Nuget": { "Name": "Microsoft.Windows.Compatibility", - "Version": "8.0.1" + "Version": "8.0.3" } }, "DevelopmentDependency": false @@ -506,7 +505,7 @@ "Type": "nuget", "Nuget": { "Name": "System.Drawing.Common", - "Version": "8.0.1" + "Version": "8.0.3" } }, "DevelopmentDependency": false @@ -831,5 +830,6 @@ }, "DevelopmentDependency": false } - ] + ], + "$schema": "https://json.schemastore.org/component-detection-manifest.json" } diff --git a/tools/releaseBuild/azureDevOps/templates/compliance/apiscan.yml b/tools/releaseBuild/azureDevOps/templates/compliance/apiscan.yml index 232fc3fd374..8afe0101bfb 100644 --- a/tools/releaseBuild/azureDevOps/templates/compliance/apiscan.yml +++ b/tools/releaseBuild/azureDevOps/templates/compliance/apiscan.yml @@ -179,7 +179,6 @@ jobs: verbosityLevel: standard # write a status update every 5 minutes. Default is 1 minute statusUpdateInterval: '00:05:00' - surrogateConfigurationFolder : $(surrogateFilePath) env: AzureServicesAuthConnectionString: RunAs=App;AppId=$(APIScanClient);TenantId=$(APIScanTenant);AppKey=$(APIScanSecret) From cf51c564de0e7a59104a3e3281bae5125ffc6943 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Fri, 5 Apr 2024 20:14:39 +0000 Subject: [PATCH 13/18] Merged PR 30664: [release/v7.4.2] Verify environment variable for OneBranch before we try to copy (#21441) Backport #21441 --- tools/releaseBuild/setReleaseTag.ps1 | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/releaseBuild/setReleaseTag.ps1 b/tools/releaseBuild/setReleaseTag.ps1 index 60af8c4d749..3f501051c19 100644 --- a/tools/releaseBuild/setReleaseTag.ps1 +++ b/tools/releaseBuild/setReleaseTag.ps1 @@ -48,13 +48,20 @@ function New-BuildInfoJson { Write-Verbose -Message "$vstsCommandString" -Verbose Write-Host -Object "##$vstsCommandString" + # Upload for ADO pipelines + Write-Host "##vso[artifact.upload containerfolder=BuildInfoJson;artifactname=BuildInfoJson]$resolvedPath" + + # Copy to location where OneBranch Pipelines uploads from + + # if the environment variable does not exist, we are not in OneBranch. So just return. + if (-not $env:ob_outputDirectory) { + return + } + if (-not (Test-Path $env:ob_outputDirectory)) { $null = New-Item -Path $env:ob_outputDirectory -ItemType Directory -Force -Verbose } - # Upload for ADO pipelines - Write-Host "##vso[artifact.upload containerfolder=BuildInfoJson;artifactname=BuildInfoJson]$resolvedPath" - # Copy to location where OneBranch Pipelines uploads from Copy-Item $resolvedPath -Destination $env:ob_outputDirectory -Force -Verbose } From 4dfadc60363976e60152db7dfafcd8dd58999e22 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Fri, 5 Apr 2024 23:22:13 +0000 Subject: [PATCH 14/18] Merged PR 30672: [release/v7.4.2] Update PSResourceGet version from 1.0.2 to 1.0.4.1 (#21439) Backport #21439 --- src/Modules/PSGalleryModules.csproj | 2 +- tools/packaging/boms/windows.json | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Modules/PSGalleryModules.csproj b/src/Modules/PSGalleryModules.csproj index 2af1ab9175b..242d6fdf0ce 100644 --- a/src/Modules/PSGalleryModules.csproj +++ b/src/Modules/PSGalleryModules.csproj @@ -13,7 +13,7 @@ - + diff --git a/tools/packaging/boms/windows.json b/tools/packaging/boms/windows.json index e172397c1bb..5ded56d0c37 100644 --- a/tools/packaging/boms/windows.json +++ b/tools/packaging/boms/windows.json @@ -807,10 +807,6 @@ "Pattern": "Modules/Microsoft.PowerShell.Archive/*.ps?1", "FileType": "NonProduct" }, - { - "Pattern": "Modules/Microsoft.PowerShell.PSResourceGet/_manifest/spdx_2.2/manifest.cat", - "FileType": "NonProduct" - }, { "Pattern": "Modules/Microsoft.PowerShell.PSResourceGet/dependencies/*.dll", "FileType": "NonProduct" From e29d8bffe15a001a8054aa7a463f05648557e343 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Sat, 6 Apr 2024 00:15:10 +0000 Subject: [PATCH 15/18] Merged PR 30677: Revert changes to packaging.psm1 Merged PR 30675: Revert changes to packaging.psm1 Revert changes to packaging.psm1 --- tools/packaging/packaging.psm1 | 45 +++------------------------------- 1 file changed, 4 insertions(+), 41 deletions(-) diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index 9f78972f72e..a6575088090 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -889,54 +889,17 @@ function Update-PSSignedBuildFolder [string[]] $RemoveFilter = ('*.pdb', '*.zip', '*.r2rmap') ) - $BuildPathNormalized = (Get-Item $BuildPath).FullName - $SignedFilesPathNormalized = (Get-Item $SignedFilesPath).FullName - - Write-Verbose -Verbose "BuildPath = $BuildPathNormalized" - Write-Verbose -Verbose "SignedFilesPath = $signedFilesPath" - # Replace unsigned binaries with signed - $signedFilesFilter = Join-Path -Path $SignedFilesPathNormalized -ChildPath '*' - Write-Verbose -Verbose "signedFilesFilter = $signedFilesFilter" - + $signedFilesFilter = Join-Path -Path $SignedFilesPath -ChildPath '*' Get-ChildItem -Path $signedFilesFilter -Recurse -File | Select-Object -ExpandProperty FullName | ForEach-Object -Process { - Write-Verbose -Verbose "Processing $_" - - # Agents seems to be on a case sensitive file system - if ($IsLinux) { - $relativePath = $_.Replace($SignedFilesPathNormalized, '') - } else { - $relativePath = $_.ToLowerInvariant().Replace($SignedFilesPathNormalized.ToLowerInvariant(), '') - } - - Write-Verbose -Verbose "relativePath = $relativePath" - $destination = (Get-Item (Join-Path -Path $BuildPathNormalized -ChildPath $relativePath)).FullName - Write-Verbose -Verbose "destination = $destination" + $relativePath = $_.ToLowerInvariant().Replace($SignedFilesPath.ToLowerInvariant(),'') + $destination = Join-Path -Path $BuildPath -ChildPath $relativePath Write-Log "replacing $destination with $_" - - if (-not (Test-Path $destination)) { - $parent = Split-Path -Path $destination -Parent - $exists = Test-Path -Path $parent - - if ($exists) { - Write-Verbose -Verbose "Parent:" - Get-ChildItem -Path $parent | Select-Object -ExpandProperty FullName | Write-Verbose -Verbose - } - - Write-Error "File not found: $destination, parent - $parent exists: $exists" - } - - $signature = Get-AuthenticodeSignature -FilePath $_ - - if ($signature.Status -ne 'Valid') { - Write-Error "Invalid signature for $_" - } - Copy-Item -Path $_ -Destination $destination -Force } foreach($filter in $RemoveFilter) { - $removePath = Join-Path -Path $BuildPathNormalized -ChildPath $filter + $removePath = Join-Path -Path $BuildPath -ChildPath $filter Remove-Item -Path $removePath -Recurse -Force } } From b84ec75459ac99bcaa654b799dfb2b3e54ad972e Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Tue, 9 Apr 2024 21:17:41 +0000 Subject: [PATCH 16/18] Merged PR 30710: Update SDK, deps and cgmanifest for 7.4.2 --- global.json | 2 +- .../Microsoft.PowerShell.Commands.Utility.csproj | 2 +- .../Microsoft.PowerShell.SDK.csproj | 4 ++-- .../System.Management.Automation.csproj | 8 +++----- tools/cgmanifest.json | 10 +++++----- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/global.json b/global.json index 1ee82c3759c..1658e45125b 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "8.0.203" + "version": "8.0.204" } } 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 c11c53fa925..ff4e5d18f02 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj +++ b/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj @@ -34,7 +34,7 @@ - + diff --git a/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj b/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj index 328a4854492..588ed9cb9d1 100644 --- a/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj +++ b/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj @@ -17,7 +17,7 @@ - + @@ -37,7 +37,7 @@ - + diff --git a/src/System.Management.Automation/System.Management.Automation.csproj b/src/System.Management.Automation/System.Management.Automation.csproj index 12247e78313..eb37762d21f 100644 --- a/src/System.Management.Automation/System.Management.Automation.csproj +++ b/src/System.Management.Automation/System.Management.Automation.csproj @@ -19,9 +19,7 @@ - + @@ -36,11 +34,11 @@ - + - + diff --git a/tools/cgmanifest.json b/tools/cgmanifest.json index d9a7a7390ba..c5ab5a24c94 100644 --- a/tools/cgmanifest.json +++ b/tools/cgmanifest.json @@ -125,7 +125,7 @@ "Type": "nuget", "Nuget": { "Name": "Microsoft.Extensions.ObjectPool", - "Version": "8.0.3" + "Version": "8.0.4" } }, "DevelopmentDependency": false @@ -225,7 +225,7 @@ "Type": "nuget", "Nuget": { "Name": "Microsoft.Windows.Compatibility", - "Version": "8.0.3" + "Version": "8.0.4" } }, "DevelopmentDependency": false @@ -445,7 +445,7 @@ "Type": "nuget", "Nuget": { "Name": "System.Diagnostics.DiagnosticSource", - "Version": "8.0.0" + "Version": "8.0.1" } }, "DevelopmentDependency": false @@ -505,7 +505,7 @@ "Type": "nuget", "Nuget": { "Name": "System.Drawing.Common", - "Version": "8.0.3" + "Version": "8.0.4" } }, "DevelopmentDependency": false @@ -635,7 +635,7 @@ "Type": "nuget", "Nuget": { "Name": "System.Security.AccessControl", - "Version": "6.0.0" + "Version": "6.0.1" } }, "DevelopmentDependency": false From e7617c4c98d94a0c8ccf989d046bd386bcef3e71 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Tue, 9 Apr 2024 22:34:39 +0000 Subject: [PATCH 17/18] Merged PR 30713: [7.4.2] Revert analyzer package back to stable Beta version was pulled in from a backport. Reverting to how it was prior. I did run `dotnet outdated` again just to be sure not to miss something. --- .../PSVersionInfoGenerator/PSVersionInfoGenerator.csproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj b/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj index addeac43ab5..828bd16a907 100644 --- a/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj +++ b/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj @@ -15,6 +15,8 @@ - + + + From 8ea1598964590b7551ffacda2d2007b94da1e5fa Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 11 Apr 2024 18:38:22 +0000 Subject: [PATCH 18/18] Merged PR 30731: [release/v7.4.2] Update `CHANGELOG` --- CHANGELOG/7.4.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/CHANGELOG/7.4.md b/CHANGELOG/7.4.md index 1d62bb6f61f..3f84bb7adc6 100644 --- a/CHANGELOG/7.4.md +++ b/CHANGELOG/7.4.md @@ -1,5 +1,50 @@ # 7.4 Changelog +## [7.4.2] - 2024-04-11 + +### General Cmdlet Updates and Fixes + +- Revert "Adjust PUT method behavior to POST one for default content type in WebCmdlets" (#21049) +- Fix regression with `Get-Content` when `-Tail 0` and `-Wait` are both used (#20734) (Thanks @CarloToso!) +- Fix `Get-Error` serialization of array values (#21085) (Thanks @jborean93!) +- Fix a regression in `Format-Table` when header label is empty (#21156) + +### Engine Updates and Fixes + +- Revert the PR #17856 (Do not preserve temporary results when no need to do so) (#21368) +- Make sure the assembly/library resolvers are registered at early stage (#21361) +- Handle the case that `Runspace.DefaultRunspace` is `null` when logging for WDAC Audit (#21344) +- Fix PowerShell class to support deriving from an abstract class with abstract properties (#21331) +- Fix the regression when doing type inference for `$_` (#21223) (Thanks @MartinGC94!) + +### Build and Packaging Improvements + +
+ + + +

Bump to .NET 8.0.4

+ +
+ +
    +
  • Revert analyzer package back to stable
  • +
  • Update SDK, deps and cgmanifest for 7.4.2
  • +
  • Revert changes to packaging.psm1
  • +
  • Update PSResourceGet version from 1.0.2 to 1.0.4.1 (#21439)
  • +
  • Verify environment variable for OneBranch before we try to copy (#21441)
  • +
  • Remove surrogateFile setting of APIScan (#21238)
  • +
  • Add dotenv install as latest version does not work with current Ruby version (#21239)
  • +
  • Multiple fixes in official build pipeline (#21408)
  • +
  • Add back 2 transitive dependency packages (#21415)
  • +
  • Update PSReadLine to v2.3.5 for the next v7.4.x servicing release (#21414)
  • +
  • PowerShell co-ordinated build OneBranch pipeline (#21364)
  • +
+ +
+ +[7.4.2]: https://github.com/PowerShell/PowerShell/compare/v7.4.1...v7.4.2 + ## [7.4.1] - 2024-01-11 ### General Cmdlet Updates and Fixes