diff --git a/Actions/CheckForUpdates/CheckForUpdates.HelperFunctions.ps1 b/Actions/CheckForUpdates/CheckForUpdates.HelperFunctions.ps1 index 3482ce5d0c..29e6dbdb09 100644 --- a/Actions/CheckForUpdates/CheckForUpdates.HelperFunctions.ps1 +++ b/Actions/CheckForUpdates/CheckForUpdates.HelperFunctions.ps1 @@ -727,7 +727,10 @@ function GetModifiedSettingsContent { $dstSettings | Add-Member -MemberType NoteProperty -Name "$schemaKey" -Value $schemaValue -Force # Make sure the $schema property is the first property in the object - $dstSettings = $dstSettings | Select-Object @{ Name = '$schema'; Expression = { $_.'$schema' } }, * -ExcludeProperty '$schema' + # PS5-safe: explicitly list properties instead of using wildcard to avoid literal '*' being added + $otherProperties = @($dstSettings.PSObject.Properties.Name | Where-Object { $_ -ne $schemaKey }) + $selectProperties = @($schemaKey) + $otherProperties + $dstSettings = $dstSettings | Select-Object -Property $selectProperties } } diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 56acffead6..1683754409 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -4,6 +4,7 @@ Workspace compilation now finds altool both in the platform-specific subfolder ( ### Issues +- Issue 2285 - CheckForUpdates now handles settings file `$schema` reordering in a PowerShell 5-safe way to avoid writing invalid entries like `"*": null` to settings JSON files. - Fix "filename or extension is too long" error when validating settings on PS5.1 with large settings JSON - Retry downloading dependency artifacts from the current build up to 3 times (30 seconds between attempts) to tolerate transient network errors such as "Failed to GetSignedArtifactURL: Unable to make request: ETIMEDOUT" diff --git a/Tests/CheckForUpdates.Action.Test.ps1 b/Tests/CheckForUpdates.Action.Test.ps1 index be6cfa9b98..9f73255520 100644 --- a/Tests/CheckForUpdates.Action.Test.ps1 +++ b/Tests/CheckForUpdates.Action.Test.ps1 @@ -268,6 +268,21 @@ Describe "CheckForUpdates Action: CheckForUpdates.HelperFunctions.ps1" { $modifiedContent."srcSetting" | Should -Be "value1" $modifiedContent."`$schema" | Should -Be "someSchema" } + + It 'GetModifiedSettingsContent does not create a literal * property when destination only contains $schema' { + # Repro for PS5 behavior where Select-Object with wildcard can emit "*": null + @{ "`$schema" = "sourceSchema"; "srcSetting" = "value1" } | ConvertTo-Json -Depth 10 | Out-File -FilePath $tmpSrcFile -Force + @{ "`$schema" = "destinationSchema" } | ConvertTo-Json -Depth 10 | Out-File -FilePath $tmpDstFile -Force + + $modifiedContentJson = GetModifiedSettingsContent -srcSettingsFile $tmpSrcFile -dstSettingsFile $tmpDstFile + $modifiedContent = $modifiedContentJson | ConvertFrom-Json + + $modifiedContent | Should -Not -BeNullOrEmpty + @($modifiedContent.PSObject.Properties.Name) | Should -Not -Contain '*' + $modifiedContentJson | Should -Not -Match '"\*"\s*:' + @($modifiedContent.PSObject.Properties.Name).Count | Should -Be 1 + $modifiedContent."`$schema" | Should -Be "sourceSchema" + } } Describe "CheckForUpdates Action: ApplyWorkflowDefaultInputs Tests" {