Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 65 additions & 13 deletions .pipelines/templates/package-create-msix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 ', ')"

Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bundling step succeeds even if no .msix files are present (both $stableMsix and $ltsMsix can be empty), which can let the job continue and later publish nothing. Consider explicitly validating that at least one .msix was found and failing the step early with a clear error message.

Suggested change
if (($stableMsix.Count + $ltsMsix.Count) -eq 0) {
throw "No .msix files were found in '$sourceDir'. Expected at least one .msix file to create an MSIX bundle."
}

Copilot uses AI. Check for mistakes.
# 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
Comment on lines 88 to +104
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this step has retryCountOnTaskFailure, a retry will re-use the same workspace, but New-Item -Force does not clear existing output, stable, or lts directories. That can leave stale bundles from the previous attempt and cause later steps to sign/upload the wrong set. Consider removing/cleaning these directories before creating bundles.

Copilot uses AI. Check for mistakes.
$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"
Expand All @@ -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
}
Comment on lines +142 to +151
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$signedBundles can be empty (e.g., bundle creation/signing failed or produced no output), but the script will still succeed and publish no artifacts. Add an explicit check that at least one .msixbundle exists in $(BundleDir) and fail the step if none are found.

Copilot uses AI. Check for mistakes.

Write-Verbose -Verbose "Uploaded Bundle:"
Write-Verbose -Verbose "Uploaded Bundles:"
Get-ChildItem -Path $(ob_outputDirectory) | Write-Verbose -Verbose
displayName: Upload msixbundle to Artifacts

Expand Down Expand Up @@ -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-' }
} else {
# Catches Stable or Preview
$bundleFile = $bundleFiles | Where-Object { $_.Name -notmatch '-LTS-' }
}

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"
Comment on lines +257 to +277
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bundle selection for store packaging can return multiple matches (e.g., if more than one bundle file matches -LTS- or -notmatch -LTS-). In that case, multiple bundles may be copied into StoreBundleDir and then submitted to StoreBroker. Consider enforcing that exactly one matching bundle is selected (and erroring otherwise), and use -File when enumerating bundles for extra safety.

Copilot uses AI. Check for mistakes.
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()
Expand Down Expand Up @@ -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'
Expand All @@ -268,7 +320,7 @@ jobs:
inputs:
serviceEndpoint: 'StoreAppPublish-Private'
sbConfigPath: '$(SBConfigPath)'
sourceFolder: '$(BundleDir)'
sourceFolder: '$(StoreBundleDir)'
contents: '*.msixBundle'
outSBName: 'PowerShellStorePackage'
pdpPath: '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDP/PDP'
Expand Down
8 changes: 8 additions & 0 deletions .pipelines/templates/packaging/windows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down
19 changes: 8 additions & 11 deletions tools/packaging/packaging.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -4257,18 +4257,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'
}

if ($ProductNameSuffix) {
$packageName += "-$ProductNameSuffix"
}

$displayName = $productName

if ($Private) {
$ProductName = 'PowerShell-Private'
Expand All @@ -4284,6 +4274,13 @@ function New-MSIXPackage
Write-Verbose -Verbose "ProductName: $productName"
Write-Verbose -Verbose "DisplayName: $displayName"

$packageName = $ProductName + '-' + $ProductSemanticVersion

# Appends Architecture to the package name
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says this appends the architecture, but $ProductNameSuffix here is a runtime/name suffix (e.g., win-x64, win-arm64) coming from Start-PSPackage. Updating the comment to reflect the actual value will avoid confusion for future maintainers.

Suggested change
# Appends Architecture to the package name
# Appends the product name/runtime suffix (for example, win-x64 or win-arm64) to the package name

Copilot uses AI. Check for mistakes.
if ($ProductNameSuffix) {
$packageName += "-$ProductNameSuffix"
}

$ProductVersion = Get-WindowsVersion -PackageName $packageName

# Any app that is submitted to the Store must have a PhoneIdentity in its appxmanifest.
Expand Down
Loading