From bd2c094f854c3ef53b4496aa773906ab7a36df78 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Wed, 18 Mar 2026 14:48:07 -0500 Subject: [PATCH 1/5] Create infrastructure to create two msix's and msixbundles for LTS and Stable --- .pipelines/templates/package-create-msix.yml | 78 +++++++++-- .../templates/packaging/windows/package.yml | 8 ++ docs/PSContentPath-flow.md | 121 ++++++++++++++++++ tools/packaging/packaging.psm1 | 5 + 4 files changed, 199 insertions(+), 13 deletions(-) create mode 100644 docs/PSContentPath-flow.md diff --git a/.pipelines/templates/package-create-msix.yml b/.pipelines/templates/package-create-msix.yml index 255915ab02c..65a0a0bd583 100644 --- a/.pipelines/templates/package-create-msix.yml +++ b/.pipelines/templates/package-create-msix.yml @@ -85,17 +85,44 @@ jobs: $null = Copy-Item -Path $msixFile.FullName -Destination $sourceDir -Force -Verbose } - $file = Get-ChildItem $sourceDir | Select-Object -First 1 - $prefix = ($file.BaseName -split "-win")[0] - $pkgName = "$prefix.msixbundle" - Write-Verbose -Verbose "Creating $pkgName" - $makeappx = '$(MakeAppxPath)' $outputDir = "$sourceDir\output" New-Item $outputDir -Type Directory -Force > $null - & $makeappx bundle /d $sourceDir /p "$outputDir\$pkgName" - Get-ChildItem -Path $sourceDir -Recurse + # Separate LTS and Stable/Preview MSIX files by filename convention + $ltsMsix = @(Get-ChildItem $sourceDir -Filter '*.msix' | Where-Object { $_.BaseName -match '-lts-' }) + $stableMsix = @(Get-ChildItem $sourceDir -Filter '*.msix' | Where-Object { $_.BaseName -notmatch '-lts-' }) + + Write-Verbose -Verbose "Stable/Preview MSIX files: $($stableMsix.Name -join ', ')" + Write-Verbose -Verbose "LTS MSIX files: $($ltsMsix.Name -join ', ')" + + # Create Stable/Preview bundle + if ($stableMsix.Count -gt 0) { + $stableDir = "$sourceDir\stable" + New-Item $stableDir -Type Directory -Force > $null + $stableMsix | Copy-Item -Destination $stableDir -Force + $file = $stableMsix | Select-Object -First 1 + $prefix = ($file.BaseName -split "-win")[0] + $stableBundleName = "$prefix.msixbundle" + Write-Verbose -Verbose "Creating Stable/Preview bundle: $stableBundleName" + & $makeappx bundle /d $stableDir /p "$outputDir\$stableBundleName" + } + + # Create LTS bundle + if ($ltsMsix.Count -gt 0) { + $ltsDir = "$sourceDir\lts" + New-Item $ltsDir -Type Directory -Force > $null + $ltsMsix | Copy-Item -Destination $ltsDir -Force + $file = $ltsMsix | Select-Object -First 1 + $prefix = ($file.BaseName -split "-win")[0] + $ltsBundleName = "$prefix.msixbundle" + Write-Verbose -Verbose "Creating LTS bundle: $ltsBundleName" + & $makeappx bundle /d $ltsDir /p "$outputDir\$ltsBundleName" + } + + Write-Verbose -Verbose "Created bundles:" + Get-ChildItem -Path $outputDir -Recurse + $vstsCommandString = "vso[task.setvariable variable=BundleDir]$outputDir" Write-Host "sending " + $vstsCommandString Write-Host "##$vstsCommandString" @@ -112,16 +139,18 @@ jobs: search_root: '$(BundleDir)' - pwsh: | - $signedBundle = Get-ChildItem -Path $(BundleDir) -Filter "*.msixbundle" -File - Write-Verbose -Verbose "Signed bundle: $signedBundle" + $signedBundles = @(Get-ChildItem -Path $(BundleDir) -Filter "*.msixbundle" -File) + Write-Verbose -Verbose "Signed bundles: $($signedBundles.Name -join ', ')" if (-not (Test-Path $(ob_outputDirectory))) { New-Item -ItemType Directory -Path $(ob_outputDirectory) -Force } - Copy-Item -Path $signedBundle.FullName -Destination "$(ob_outputDirectory)" -Verbose + foreach ($bundle in $signedBundles) { + Copy-Item -Path $bundle.FullName -Destination "$(ob_outputDirectory)" -Verbose + } - Write-Verbose -Verbose "Uploaded Bundle:" + Write-Verbose -Verbose "Uploaded Bundles:" Get-ChildItem -Path $(ob_outputDirectory) | Write-Verbose -Verbose displayName: Upload msixbundle to Artifacts @@ -225,6 +254,29 @@ jobs: Write-Host "##vso[task.setvariable variable=ServiceConnection]$($config.ServiceEndpoint)" Write-Host "##vso[task.setvariable variable=SBConfigPath]$($sbConfigPath)" + # Select the correct bundle based on channel + $bundleFiles = @(Get-ChildItem -Path '$(BundleDir)' -Filter '*.msixbundle') + Write-Verbose -Verbose "Available bundles: $($bundleFiles.Name -join ', ')" + + if ($IsLTS) { + $bundleFile = $bundleFiles | Where-Object { $_.Name -match '-lts\.msixbundle$' } + } else { + # Catches Stable or Preview + $bundleFile = $bundleFiles | Where-Object { $_.Name -notmatch '-lts\.msixbundle$' } + } + + if (-not $bundleFile) { + Write-Error "No matching bundle found for channel '$currentChannel'. Available bundles: $($bundleFiles.Name -join ', ')" + exit 1 + } + + # Copy the selected bundle to a dedicated directory for store packaging + $storeBundleDir = '$(Pipeline.Workspace)\releasePipeline\msix\store-bundle' + New-Item $storeBundleDir -Type Directory -Force > $null + Copy-Item -Path $bundleFile.FullName -Destination $storeBundleDir -Force -Verbose + Write-Host "##vso[task.setvariable variable=StoreBundleDir]$storeBundleDir" + Write-Verbose -Verbose "Selected bundle for store packaging: $($bundleFile.Name)" + # These variables are used in the next tasks to determine which ServiceEndpoint to use $ltsValue = $IsLTS.ToString().ToLower() $stableValue = $IsStable.ToString().ToLower() @@ -256,7 +308,7 @@ jobs: inputs: serviceEndpoint: 'StoreAppPublish-Preview' sbConfigPath: '$(SBConfigPath)' - sourceFolder: '$(BundleDir)' + sourceFolder: '$(StoreBundleDir)' contents: '*.msixBundle' outSBName: 'PowerShellStorePackage' pdpPath: '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDP/PDP' @@ -268,7 +320,7 @@ jobs: inputs: serviceEndpoint: 'StoreAppPublish-Stable' sbConfigPath: '$(SBConfigPath)' - sourceFolder: '$(BundleDir)' + sourceFolder: '$(StoreBundleDir)' contents: '*.msixBundle' outSBName: 'PowerShellStorePackage' pdpPath: '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDP/PDP' diff --git a/.pipelines/templates/packaging/windows/package.yml b/.pipelines/templates/packaging/windows/package.yml index 1f03d65ab21..92926e6aa59 100644 --- a/.pipelines/templates/packaging/windows/package.yml +++ b/.pipelines/templates/packaging/windows/package.yml @@ -136,12 +136,14 @@ jobs: # Don't build LTS packages for rebuild branches $LTS = $metadata.LTSRelease.Package -and -not $isRebuildBranch + $Stable = [bool]$metadata.StableRelease.Package if ($isRebuildBranch) { Write-Verbose -Message "Rebuild branch detected, skipping LTS package build" -Verbose } Write-Verbose -Verbose "LTS: $LTS" + Write-Verbose -Verbose "Stable: $Stable" if ($LTS) { Write-Verbose -Message "LTS Release: $LTS" @@ -175,6 +177,12 @@ jobs: Start-PSPackage -Type $packageTypes -SkipReleaseChecks -WindowsRuntime $WindowsRuntime -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath -LTS:$LTS + # When both LTS and Stable are requested, also build the Stable MSIX + if ($packageTypes -contains 'msix' -and $LTS -and $Stable) { + Write-Verbose -Verbose "Both LTS and Stable packages requested. Building additional Stable MSIX." + Start-PSPackage -Type msix -SkipReleaseChecks -WindowsRuntime $WindowsRuntime -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath + } + displayName: 'Build Packages (Unsigned)' env: __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY) diff --git a/docs/PSContentPath-flow.md b/docs/PSContentPath-flow.md new file mode 100644 index 00000000000..98945ed6276 --- /dev/null +++ b/docs/PSContentPath-flow.md @@ -0,0 +1,121 @@ +# PSContentPath Resolution & Configuration Flow + +## Config File Location — Startup Resolution (Windows) + +```mermaid +flowchart TD + A["PowerShellConfig
initialization"] --> B{"Config file exists in
LocalAppData?
%LOCALAPPDATA%\\PowerShell\\
powershell.config.json"} + B -->|Yes| C["Use LocalAppData
as config directory"] + B -->|No| D{"Config file exists in
Documents / OneDrive?
%PERSONAL%\\PowerShell\\
powershell.config.json"} + D -->|Yes| E["Use Documents path
(backwards compatibility)"] + E --> F["Send telemetry
(UserConfigLocation:Documents)"] + D -->|No| G["Default to LocalAppData
for new config files"] + + C --> H["perUserConfigFile set"] + F --> H + G --> H + + style C fill:#d4edda + style E fill:#fff3cd + style G fill:#d4edda +``` + +> **Note:** On Unix/macOS, both locations resolve to the same XDG data directory (`~/.local/share/powershell`), so there is no fallback chain. + +## GetPSContentPath — Resolution Flow + +```mermaid +flowchart TD + A["Caller invokes
Utils.GetPSContentPath()"] --> B["PowerShellConfig.Instance
.GetPSContentPath()"] + B --> C{"Read PSUserContentPath
from powershell.config.json
(CurrentUser scope)"} + C -->|"Key found &
non-empty"| D["Expand environment
variables in path"] + D --> E["Send telemetry flag
(CustomPSContentPath)"] + E --> F["Return custom path"] + C -->|"Key missing
or empty"| G{"Platform?"} + G -->|Windows| H["Platform.DefaultPSContentDirectory
= Documents\\PowerShell"] + G -->|Unix / macOS| I["Platform.DefaultPSContentDirectory
= ~/.local/share/powershell"] + H --> J["Return platform default"] + I --> J +``` + +## Set-PSContentPath — Configuration Flow + +```mermaid +flowchart TD + A["User runs
Set-PSContentPath"] --> B{"Parameter set?"} + B -->|"-Path <string>"| C["Expand environment
variables in path"] + B -->|"-Default"| K["path = null
(reset to default)"] + + C --> D{"Validate path"} + D -->|"Invalid chars or
not rooted"| E["Throw terminating
error"] + D -->|"Valid"| F{"Directory
exists?"} + F -->|No| G["Write warning
(non-terminating)"] + F -->|Yes| H["Continue"] + G --> H + + K --> L["PowerShellConfig.Instance
.SetPSContentPath(null)"] + L --> M["RemoveValueFromFile
(CurrentUser scope)"] + M --> N["Update cached JObject"] + + H --> O["ShouldProcess
confirmation
(ConfirmImpact=High)"] + O -->|Denied| Z["No-op"] + O -->|Confirmed| P["PowerShellConfig.Instance
.SetPSContentPath(path)"] + P --> Q["WriteValueToFile
(CurrentUser scope)"] + Q --> R["Acquire write lock"] + R --> S["Open FileStream
(FileShare.None)"] + S --> T["Read existing JSON,
modify key, write back"] + T --> U["Update cached JObject"] + + N --> V["UpdatePSUserContentPath
Variable(newPath)"] + U --> V + V --> W["Set $PSUserContentPath
in global scope"] + W --> X["Set $env:PSUserContentPath
for child process
inheritance"] +``` + +## Consumers — How Paths Derive from PSContentPath + +```mermaid +flowchart LR + CP["Utils.GetPSContentPath()"] --> MOD["Modules
PSContentPath\\Modules"] + CP --> PROF["Profiles
PSContentPath\\profile.ps1"] + CP --> HELP["Help
PSContentPath\\Help"] + CP --> SCRIPTS["Scripts
PSContentPath\\Scripts"] + + MOD --> LEGACY{"PSContentPath ≠
Documents\\PowerShell?"} + LEGACY -->|Yes| FALLBACK["Legacy path added
to $env:PSModulePath
(Documents\\PowerShell\\Modules)"] + LEGACY -->|No| NOFALLBACK["No extra path
needed"] +``` + +## Config File I/O — Thread Safety + +```mermaid +sequenceDiagram + participant Caller + participant Config as PowerShellConfig + participant Lock as ReaderWriterLockSlim + participant Cache as JObject Cache + participant File as powershell.config.json + + Note over Caller,File: READ PATH (concurrent reads allowed) + Caller->>Config: GetPSContentPath() + Config->>Lock: Acquire read lock + Lock-->>Config: Granted + Config->>Cache: Check configRoots[CurrentUser] + alt Cache miss (first read) + Config->>File: Read & parse JSON + Config->>Cache: Store via InterlockedCompareExchange + end + Cache-->>Config: Return JObject + Config->>Lock: Release read lock + Config-->>Caller: Return path value + + Note over Caller,File: WRITE PATH (exclusive lock) + Caller->>Config: SetPSContentPath(path) + Config->>Lock: Acquire write lock (exclusive) + Lock-->>Config: Granted + Config->>File: Open FileStream (FileShare.None) + Config->>File: Read → modify → write back + Config->>Cache: Update cached JObject + Config->>Lock: Release write lock + Config-->>Caller: Done +``` diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index 53d895bc49b..a0b14864c82 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -4281,6 +4281,11 @@ function New-MSIXPackage $ProductNameSuffix = 'Private' } + # Add LTS suffix to filename so both Stable and LTS MSIXs can coexist + if ($LTS -and -not $Private) { + $packageName += "-lts" + } + if ($ProductNameSuffix) { $packageName += "-$ProductNameSuffix" } From 30e5abe4db2b3a997bb65b365fe1cde6523cd79a Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Wed, 18 Mar 2026 14:49:46 -0500 Subject: [PATCH 2/5] remove extra diagram --- docs/PSContentPath-flow.md | 121 ------------------------------------- 1 file changed, 121 deletions(-) delete mode 100644 docs/PSContentPath-flow.md diff --git a/docs/PSContentPath-flow.md b/docs/PSContentPath-flow.md deleted file mode 100644 index 98945ed6276..00000000000 --- a/docs/PSContentPath-flow.md +++ /dev/null @@ -1,121 +0,0 @@ -# PSContentPath Resolution & Configuration Flow - -## Config File Location — Startup Resolution (Windows) - -```mermaid -flowchart TD - A["PowerShellConfig
initialization"] --> B{"Config file exists in
LocalAppData?
%LOCALAPPDATA%\\PowerShell\\
powershell.config.json"} - B -->|Yes| C["Use LocalAppData
as config directory"] - B -->|No| D{"Config file exists in
Documents / OneDrive?
%PERSONAL%\\PowerShell\\
powershell.config.json"} - D -->|Yes| E["Use Documents path
(backwards compatibility)"] - E --> F["Send telemetry
(UserConfigLocation:Documents)"] - D -->|No| G["Default to LocalAppData
for new config files"] - - C --> H["perUserConfigFile set"] - F --> H - G --> H - - style C fill:#d4edda - style E fill:#fff3cd - style G fill:#d4edda -``` - -> **Note:** On Unix/macOS, both locations resolve to the same XDG data directory (`~/.local/share/powershell`), so there is no fallback chain. - -## GetPSContentPath — Resolution Flow - -```mermaid -flowchart TD - A["Caller invokes
Utils.GetPSContentPath()"] --> B["PowerShellConfig.Instance
.GetPSContentPath()"] - B --> C{"Read PSUserContentPath
from powershell.config.json
(CurrentUser scope)"} - C -->|"Key found &
non-empty"| D["Expand environment
variables in path"] - D --> E["Send telemetry flag
(CustomPSContentPath)"] - E --> F["Return custom path"] - C -->|"Key missing
or empty"| G{"Platform?"} - G -->|Windows| H["Platform.DefaultPSContentDirectory
= Documents\\PowerShell"] - G -->|Unix / macOS| I["Platform.DefaultPSContentDirectory
= ~/.local/share/powershell"] - H --> J["Return platform default"] - I --> J -``` - -## Set-PSContentPath — Configuration Flow - -```mermaid -flowchart TD - A["User runs
Set-PSContentPath"] --> B{"Parameter set?"} - B -->|"-Path <string>"| C["Expand environment
variables in path"] - B -->|"-Default"| K["path = null
(reset to default)"] - - C --> D{"Validate path"} - D -->|"Invalid chars or
not rooted"| E["Throw terminating
error"] - D -->|"Valid"| F{"Directory
exists?"} - F -->|No| G["Write warning
(non-terminating)"] - F -->|Yes| H["Continue"] - G --> H - - K --> L["PowerShellConfig.Instance
.SetPSContentPath(null)"] - L --> M["RemoveValueFromFile
(CurrentUser scope)"] - M --> N["Update cached JObject"] - - H --> O["ShouldProcess
confirmation
(ConfirmImpact=High)"] - O -->|Denied| Z["No-op"] - O -->|Confirmed| P["PowerShellConfig.Instance
.SetPSContentPath(path)"] - P --> Q["WriteValueToFile
(CurrentUser scope)"] - Q --> R["Acquire write lock"] - R --> S["Open FileStream
(FileShare.None)"] - S --> T["Read existing JSON,
modify key, write back"] - T --> U["Update cached JObject"] - - N --> V["UpdatePSUserContentPath
Variable(newPath)"] - U --> V - V --> W["Set $PSUserContentPath
in global scope"] - W --> X["Set $env:PSUserContentPath
for child process
inheritance"] -``` - -## Consumers — How Paths Derive from PSContentPath - -```mermaid -flowchart LR - CP["Utils.GetPSContentPath()"] --> MOD["Modules
PSContentPath\\Modules"] - CP --> PROF["Profiles
PSContentPath\\profile.ps1"] - CP --> HELP["Help
PSContentPath\\Help"] - CP --> SCRIPTS["Scripts
PSContentPath\\Scripts"] - - MOD --> LEGACY{"PSContentPath ≠
Documents\\PowerShell?"} - LEGACY -->|Yes| FALLBACK["Legacy path added
to $env:PSModulePath
(Documents\\PowerShell\\Modules)"] - LEGACY -->|No| NOFALLBACK["No extra path
needed"] -``` - -## Config File I/O — Thread Safety - -```mermaid -sequenceDiagram - participant Caller - participant Config as PowerShellConfig - participant Lock as ReaderWriterLockSlim - participant Cache as JObject Cache - participant File as powershell.config.json - - Note over Caller,File: READ PATH (concurrent reads allowed) - Caller->>Config: GetPSContentPath() - Config->>Lock: Acquire read lock - Lock-->>Config: Granted - Config->>Cache: Check configRoots[CurrentUser] - alt Cache miss (first read) - Config->>File: Read & parse JSON - Config->>Cache: Store via InterlockedCompareExchange - end - Cache-->>Config: Return JObject - Config->>Lock: Release read lock - Config-->>Caller: Return path value - - Note over Caller,File: WRITE PATH (exclusive lock) - Caller->>Config: SetPSContentPath(path) - Config->>Lock: Acquire write lock (exclusive) - Lock-->>Config: Granted - Config->>File: Open FileStream (FileShare.None) - Config->>File: Read → modify → write back - Config->>Cache: Update cached JObject - Config->>Lock: Release write lock - Config-->>Caller: Done -``` From a6ff8946379314a95875b6b9a0dead4323d57c13 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Thu, 19 Mar 2026 12:31:54 -0500 Subject: [PATCH 3/5] changepackage name to product name then architecture --- .pipelines/templates/package-create-msix.yml | 8 +++--- tools/packaging/packaging.psm1 | 27 ++++++++------------ 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/.pipelines/templates/package-create-msix.yml b/.pipelines/templates/package-create-msix.yml index 65a0a0bd583..e461bb6efd9 100644 --- a/.pipelines/templates/package-create-msix.yml +++ b/.pipelines/templates/package-create-msix.yml @@ -90,8 +90,8 @@ jobs: New-Item $outputDir -Type Directory -Force > $null # Separate LTS and Stable/Preview MSIX files by filename convention - $ltsMsix = @(Get-ChildItem $sourceDir -Filter '*.msix' | Where-Object { $_.BaseName -match '-lts-' }) - $stableMsix = @(Get-ChildItem $sourceDir -Filter '*.msix' | Where-Object { $_.BaseName -notmatch '-lts-' }) + $ltsMsix = @(Get-ChildItem $sourceDir -Filter '*.msix' | Where-Object { $_.BaseName -match '-LTS-' }) + $stableMsix = @(Get-ChildItem $sourceDir -Filter '*.msix' | Where-Object { $_.BaseName -notmatch '-LTS-' }) Write-Verbose -Verbose "Stable/Preview MSIX files: $($stableMsix.Name -join ', ')" Write-Verbose -Verbose "LTS MSIX files: $($ltsMsix.Name -join ', ')" @@ -259,10 +259,10 @@ jobs: Write-Verbose -Verbose "Available bundles: $($bundleFiles.Name -join ', ')" if ($IsLTS) { - $bundleFile = $bundleFiles | Where-Object { $_.Name -match '-lts\.msixbundle$' } + $bundleFile = $bundleFiles | Where-Object { $_.Name -match '-LTS-' } } else { # Catches Stable or Preview - $bundleFile = $bundleFiles | Where-Object { $_.Name -notmatch '-lts\.msixbundle$' } + $bundleFile = $bundleFiles | Where-Object { $_.Name -notmatch '-LTS-' } } if (-not $bundleFile) { diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index a0b14864c82..148ca812acc 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -4274,23 +4274,8 @@ function New-MSIXPackage $makepri = Get-Item (Join-Path $makeappx.Directory "makepri.exe") -ErrorAction Stop + $displayName = $ProductName $ProductSemanticVersion = Get-PackageSemanticVersion -Version $ProductVersion - $productSemanticVersionWithName = $ProductName + '-' + $ProductSemanticVersion - $packageName = $productSemanticVersionWithName - if ($Private) { - $ProductNameSuffix = 'Private' - } - - # Add LTS suffix to filename so both Stable and LTS MSIXs can coexist - if ($LTS -and -not $Private) { - $packageName += "-lts" - } - - if ($ProductNameSuffix) { - $packageName += "-$ProductNameSuffix" - } - - $displayName = $productName if ($Private) { $ProductName = 'PowerShell-Private' @@ -4306,6 +4291,16 @@ function New-MSIXPackage Write-Verbose -Verbose "ProductName: $productName" Write-Verbose -Verbose "DisplayName: $displayName" + $packageName = $ProductName + '-' + $ProductSemanticVersion + if ($Private) { + $ProductNameSuffix = 'Private' + } + + # Architecture needs to be in the name, Private scenario overrides + if ($ProductNameSuffix) { + $packageName += "-$ProductNameSuffix" + } + $ProductVersion = Get-WindowsVersion -PackageName $packageName # Any app that is submitted to the Store must have a PhoneIdentity in its appxmanifest. From 41c606619906039c95a679887f72812f5a562f7d Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Thu, 19 Mar 2026 13:36:27 -0500 Subject: [PATCH 4/5] Remove duplicate private --- tools/packaging/packaging.psm1 | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index 148ca812acc..a611c923e17 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -4291,12 +4291,7 @@ function New-MSIXPackage Write-Verbose -Verbose "ProductName: $productName" Write-Verbose -Verbose "DisplayName: $displayName" - $packageName = $ProductName + '-' + $ProductSemanticVersion - if ($Private) { - $ProductNameSuffix = 'Private' - } - - # Architecture needs to be in the name, Private scenario overrides + # Appends Architecture to the package name if ($ProductNameSuffix) { $packageName += "-$ProductNameSuffix" } From 35b7f6bc161a6db04a20c92def20aa22d9002ea2 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Thu, 19 Mar 2026 13:42:49 -0500 Subject: [PATCH 5/5] keep semantic version --- tools/packaging/packaging.psm1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index a611c923e17..baab911f60d 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -4291,6 +4291,8 @@ function New-MSIXPackage Write-Verbose -Verbose "ProductName: $productName" Write-Verbose -Verbose "DisplayName: $displayName" + $packageName = $ProductName + '-' + $ProductSemanticVersion + # Appends Architecture to the package name if ($ProductNameSuffix) { $packageName += "-$ProductNameSuffix"