From ac840d15bb3dd4af248ea7f36d4ed02df819d08a Mon Sep 17 00:00:00 2001 From: "Travis Plunk (HE/HIM)" Date: Wed, 5 Nov 2025 16:44:29 -0800 Subject: [PATCH 1/3] Add rebuild branch support with conditional MSIX signing Enables rebuild branches to skip LTS packaging and conditionally sign MSIX packages. --- .../ServiceGroupRoot/Shell/Run/Run.ps1 | 6 ++- ...werShell-Coordinated_Packages-Official.yml | 13 ++++- .pipelines/PowerShell-Packages-Official.yml | 2 + .pipelines/templates/channelSelection.yml | 22 +++++++-- .pipelines/templates/linux-package-build.yml | 18 ++++++- .pipelines/templates/mac-package-build.yml | 18 ++++++- .pipelines/templates/package-create-msix.yml | 48 ++++++++++++++----- .../templates/packaging/windows/package.yml | 18 ++++++- .pipelines/templates/rebuild-branch-check.yml | 17 +++++++ 9 files changed, 141 insertions(+), 21 deletions(-) create mode 100644 .pipelines/templates/rebuild-branch-check.yml diff --git a/.pipelines/EV2Specs/ServiceGroupRoot/Shell/Run/Run.ps1 b/.pipelines/EV2Specs/ServiceGroupRoot/Shell/Run/Run.ps1 index 25a5686b33e..23f91c1bff2 100644 --- a/.pipelines/EV2Specs/ServiceGroupRoot/Shell/Run/Run.ps1 +++ b/.pipelines/EV2Specs/ServiceGroupRoot/Shell/Run/Run.ps1 @@ -354,6 +354,9 @@ try { $skipPublish = $metadataContent.SkipPublish $lts = $metadataContent.LTS + # Check if this is a rebuild version (e.g., 7.4.13-rebuild.5) + $isRebuild = $releaseVersion -match '-rebuild\.' + if ($releaseVersion.Contains('-')) { $channel = 'preview' $packageNames = @('powershell-preview') @@ -363,7 +366,8 @@ try { $packageNames = @('powershell') } - if ($lts) { + # Only add LTS package if not a rebuild branch + if ($lts -and -not $isRebuild) { $packageNames += @('powershell-lts') } diff --git a/.pipelines/PowerShell-Coordinated_Packages-Official.yml b/.pipelines/PowerShell-Coordinated_Packages-Official.yml index f36eeadf298..e4de1fe5c21 100644 --- a/.pipelines/PowerShell-Coordinated_Packages-Official.yml +++ b/.pipelines/PowerShell-Coordinated_Packages-Official.yml @@ -296,9 +296,20 @@ extends: - template: /.pipelines/templates/SetVersionVariables.yml@self parameters: ReleaseTagVar: $(ReleaseTagVar) + - template: /.pipelines/templates/rebuild-branch-check.yml@self - powershell: | $metadata = Get-Content '$(Build.SourcesDirectory)/PowerShell/tools/metadata.json' -Raw | ConvertFrom-Json - $LTS = $metadata.LTSRelease.Package + + # Use the rebuild branch check from the template + $isRebuildBranch = '$(RebuildBranchCheck.IsRebuildBranch)' -eq 'true' + + # Don't mark as LTS release for rebuild branches + $LTS = $metadata.LTSRelease.Package -and -not $isRebuildBranch + + if ($isRebuildBranch) { + Write-Verbose -Message "Rebuild branch detected, not marking as LTS release" -Verbose + } + @{ ReleaseVersion = "$(Version)"; LTSRelease = $LTS } | ConvertTo-Json | Out-File "$(Build.StagingDirectory)\release.json" Get-Content "$(Build.StagingDirectory)\release.json" diff --git a/.pipelines/PowerShell-Packages-Official.yml b/.pipelines/PowerShell-Packages-Official.yml index 8e06be1cc64..ad8e996dd79 100644 --- a/.pipelines/PowerShell-Packages-Official.yml +++ b/.pipelines/PowerShell-Packages-Official.yml @@ -293,6 +293,8 @@ extends: dependsOn: [windows_package_build] # Only depends on unsigned packages jobs: - template: /.pipelines/templates/package-create-msix.yml@self + parameters: + OfficialBuild: ${{ parameters.OfficialBuild }} - stage: upload displayName: 'Upload' diff --git a/.pipelines/templates/channelSelection.yml b/.pipelines/templates/channelSelection.yml index 3d1f445c559..ffc8d83f324 100644 --- a/.pipelines/templates/channelSelection.yml +++ b/.pipelines/templates/channelSelection.yml @@ -2,13 +2,27 @@ steps: - pwsh: | # Determine LTS, Preview, or Stable $metadata = Get-Content "$(Build.SourcesDirectory)/PowerShell/tools/metadata.json" -Raw | ConvertFrom-Json + $releaseTag = '$(OutputReleaseTag.releaseTag)' + + # Rebuild branches should be treated as preview builds + $isRebuildBranch = '$(Build.SourceBranch)' -match 'refs/heads/rebuild/.*-rebuild\.' + $LTS = $metadata.LTSRelease.Latest $Stable = $metadata.StableRelease.Latest - $isPreview = '$(OutputReleaseTag.releaseTag)' -match '-' + $isPreview = $releaseTag -match '-' - $IsLTS = [bool]$LTS - $IsStable = [bool]$Stable - $IsPreview = [bool]$isPreview + # If this is a rebuild branch, force preview mode and ignore LTS metadata + if ($isRebuildBranch) { + $IsLTS = $false + $IsStable = $false + $IsPreview = $true + Write-Verbose -Message "Rebuild branch detected, forcing Preview channel" -Verbose + } + else { + $IsLTS = [bool]$LTS + $IsStable = [bool]$Stable + $IsPreview = [bool]$isPreview + } $channelVars = @{ IsLTS = $IsLTS diff --git a/.pipelines/templates/linux-package-build.yml b/.pipelines/templates/linux-package-build.yml index b1c170eaed5..a28628798b2 100644 --- a/.pipelines/templates/linux-package-build.yml +++ b/.pipelines/templates/linux-package-build.yml @@ -62,6 +62,8 @@ jobs: parameters: nativePathRoot: '$(Agent.TempDirectory)' + - template: rebuild-branch-check.yml@self + - download: CoOrdinatedBuildPipeline artifact: ${{ parameters.unsignedDrop }} displayName: 'Download unsigned artifacts' @@ -139,7 +141,21 @@ jobs: } $metadata = Get-Content "$repoRoot/tools/metadata.json" -Raw | ConvertFrom-Json - $LTS = $metadata.LTSRelease.Package + + Write-Verbose -Verbose "metadata:" + $metadata | Out-String | Write-Verbose -Verbose + + # Use the rebuild branch check from the template + $isRebuildBranch = '$(RebuildBranchCheck.IsRebuildBranch)' -eq 'true' + + # Don't build LTS packages for rebuild branches + $LTS = ($metadata.LTSRelease.Package -eq 'True') -and -not $isRebuildBranch + + if ($isRebuildBranch) { + Write-Verbose -Message "Rebuild branch detected, skipping LTS package build" -Verbose + } + + Write-Verbose -Verbose "LTS: $LTS" if ($LTS) { Write-Verbose -Message "LTS Release: $LTS" diff --git a/.pipelines/templates/mac-package-build.yml b/.pipelines/templates/mac-package-build.yml index 1abb1722398..28d50ef38e6 100644 --- a/.pipelines/templates/mac-package-build.yml +++ b/.pipelines/templates/mac-package-build.yml @@ -60,6 +60,8 @@ jobs: parameters: nativePathRoot: '$(Agent.TempDirectory)' + - template: rebuild-branch-check.yml@self + - download: CoOrdinatedBuildPipeline artifact: macosBinResults-${{ parameters.buildArchitecture }} @@ -103,7 +105,21 @@ jobs: Get-PSOptions | Write-Verbose -Verbose $metadata = Get-Content "$repoRoot/tools/metadata.json" -Raw | ConvertFrom-Json - $LTS = $metadata.LTSRelease.Package + + Write-Verbose -Verbose "metadata:" + $metadata | Out-String | Write-Verbose -Verbose + + # Use the rebuild branch check from the template + $isRebuildBranch = '$(RebuildBranchCheck.IsRebuildBranch)' -eq 'true' + + # Don't build LTS packages for rebuild branches + $LTS = ($metadata.LTSRelease.Package -eq 'True') -and -not $isRebuildBranch + + if ($isRebuildBranch) { + Write-Verbose -Message "Rebuild branch detected, skipping LTS package build" -Verbose + } + + Write-Verbose -Verbose "LTS: $LTS" if ($LTS) { Write-Verbose -Message "LTS Release: $LTS" diff --git a/.pipelines/templates/package-create-msix.yml b/.pipelines/templates/package-create-msix.yml index ed0217b2940..2b32aa4d0bb 100644 --- a/.pipelines/templates/package-create-msix.yml +++ b/.pipelines/templates/package-create-msix.yml @@ -1,3 +1,8 @@ +parameters: + - name: OfficialBuild + type: boolean + default: false + jobs: - job: CreateMSIXBundle displayName: Create .msixbundle file @@ -49,7 +54,7 @@ jobs: **/*.msix targetPath: '$(Build.ArtifactStagingDirectory)/downloads' displayName: Download windows x86 packages - + # Finds the makeappx tool on the machine with image: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest' - pwsh: | $cmd = Get-Command makeappx.exe -ErrorAction Ignore @@ -99,12 +104,13 @@ jobs: - task: onebranch.pipeline.signing@1 displayName: Sign MsixBundle + condition: eq('${{ parameters.OfficialBuild }}', 'true') inputs: command: 'sign' signing_profile: $(MSIXProfile) files_to_sign: '**/*.msixbundle' search_root: '$(BundleDir)' - + - pwsh: | $signedBundle = Get-ChildItem -Path $(BundleDir) -Filter "*.msixbundle" -File Write-Verbose -Verbose "Signed bundle: $signedBundle" @@ -126,12 +132,12 @@ jobs: Get-ChildItem -Path $(System.DefaultWorkingDirectory) -Recurse | Select-Object -ExpandProperty FullName Test-Path -Path '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDP-Private.xml' | Write-Verbose -Verbose displayName: Output Pipeline.Workspace and System.DefaultWorkingDirectory - + - template: channelSelection.yml@self - pwsh: | $IsLTS = '$(ChannelSelection.IsLTS)' -eq 'true' - $IsStable = '$(ChannelSelection.IsStable)' -eq 'true' + $IsStable = '$(ChannelSelection.IsStable)' -eq 'true' $IsPreview = '$(ChannelSelection.IsPreview)' -eq 'true' Write-Verbose -Verbose "Channel Selection - LTS: $IsLTS, Stable: $IsStable, Preview: $IsPreview" @@ -161,11 +167,11 @@ jobs: $currentChannel = if ($IsLTS) { 'LTS' } elseif ($IsStable) { 'Stable' } elseif ($IsPreview) { 'Preview' } - else { + else { Write-Error "No valid channel detected" exit 1 } - + $config = $channelConfigs[$currentChannel] Write-Verbose -Verbose "Selected channel: $currentChannel" Write-Verbose -Verbose "App Store Name: $($config.AppStoreName)" @@ -181,7 +187,7 @@ jobs: # Create namespace manager for XML with default namespace $nsManager = New-Object System.Xml.XmlNamespaceManager($pdpXml.NameTable) $nsManager.AddNamespace("pd", "http://schemas.microsoft.com/appx/2012/ProductDescription") - + $appStoreNameElement = $pdpXml.SelectSingleNode("//pd:AppStoreName", $nsManager) if ($appStoreNameElement) { $appStoreNameElement.SetAttribute("_locID", $config.AppStoreName) @@ -220,12 +226,30 @@ jobs: Write-Host "##vso[task.setvariable variable=SBConfigPath]$($sbConfigPath)" # These variables are used in the next tasks to determine which ServiceEndpoint to use - Write-Host "##vso[task.setvariable variable=LTS]$($IsLTS.ToString().ToLower())" - Write-Host "##vso[task.setvariable variable=STABLE]$($IsStable.ToString().ToLower())" - Write-Host "##vso[task.setvariable variable=PREVIEW]$($IsPreview.ToString().ToLower())" + $ltsValue = $IsLTS.ToString().ToLower() + $stableValue = $IsStable.ToString().ToLower() + $previewValue = $IsPreview.ToString().ToLower() + + Write-Verbose -Verbose "About to set variables:" + Write-Verbose -Verbose " LTS=$ltsValue" + Write-Verbose -Verbose " STABLE=$stableValue" + Write-Verbose -Verbose " PREVIEW=$previewValue" + + Write-Host "##vso[task.setvariable variable=LTS]$ltsValue" + Write-Host "##vso[task.setvariable variable=STABLE]$stableValue" + Write-Host "##vso[task.setvariable variable=PREVIEW]$previewValue" + + Write-Verbose -Verbose "Variables set successfully" name: UpdateConfigs displayName: Update PDPs and SBConfig.json + - pwsh: | + Write-Verbose -Verbose "Checking variables after UpdateConfigs:" + Write-Verbose -Verbose "LTS=$(LTS)" + Write-Verbose -Verbose "STABLE=$(STABLE)" + Write-Verbose -Verbose "PREVIEW=$(PREVIEW)" + displayName: Debug - Check Variables + - task: MS-RDX-MRO.windows-store-publish.package-task.store-package@3 displayName: 'Create StoreBroker Package (Preview)' condition: eq('$(PREVIEW)', 'true') @@ -260,14 +284,14 @@ jobs: $submissionPackageDir = "$(System.DefaultWorkingDirectory)/SBOutDir" $jsonFile = "$submissionPackageDir/PowerShellStorePackage.json" $zipFile = "$submissionPackageDir/PowerShellStorePackage.zip" - + if ((Test-Path $jsonFile) -and (Test-Path $zipFile)) { Write-Verbose -Verbose "Uploading StoreBroker Package files:" Write-Verbose -Verbose "JSON File: $jsonFile" Write-Verbose -Verbose "ZIP File: $zipFile" Copy-Item -Path $submissionPackageDir -Destination "$(ob_outputDirectory)" -Verbose -Recurse - } + } else { Write-Error "Required files not found in $submissionPackageDir" diff --git a/.pipelines/templates/packaging/windows/package.yml b/.pipelines/templates/packaging/windows/package.yml index 9a8be4b18fe..4e38db3e826 100644 --- a/.pipelines/templates/packaging/windows/package.yml +++ b/.pipelines/templates/packaging/windows/package.yml @@ -60,6 +60,8 @@ jobs: nativePathRoot: '$(Agent.TempDirectory)' ob_restore_phase: false + - template: rebuild-branch-check.yml@self + - download: CoOrdinatedBuildPipeline artifact: drop_windows_build_windows_${{ parameters.runtime }}_release displayName: Download signed artifacts @@ -127,7 +129,21 @@ jobs: Get-PSOptions | Write-Verbose -Verbose $metadata = Get-Content "$repoRoot/tools/metadata.json" -Raw | ConvertFrom-Json - $LTS = $metadata.LTSRelease.Package + + Write-Verbose -Verbose "metadata:" + $metadata | Out-String | Write-Verbose -Verbose + + # Use the rebuild branch check from the template + $isRebuildBranch = '$(RebuildBranchCheck.IsRebuildBranch)' -eq 'true' + + # Don't build LTS packages for rebuild branches + $LTS = ($metadata.LTSRelease.Package -eq 'True') -and -not $isRebuildBranch + + if ($isRebuildBranch) { + Write-Verbose -Message "Rebuild branch detected, skipping LTS package build" -Verbose + } + + Write-Verbose -Verbose "LTS: $LTS" if ($LTS) { Write-Verbose -Message "LTS Release: $LTS" diff --git a/.pipelines/templates/rebuild-branch-check.yml b/.pipelines/templates/rebuild-branch-check.yml new file mode 100644 index 00000000000..a4b546a0dc6 --- /dev/null +++ b/.pipelines/templates/rebuild-branch-check.yml @@ -0,0 +1,17 @@ +# This template checks if the current branch is a rebuild branch +# and sets an output variable IsRebuildBranch that can be used by other templates +steps: +- pwsh: | + # Check if this is a rebuild branch (e.g., rebuild/v7.4.13-rebuild.5) + $isRebuildBranch = '$(Build.SourceBranch)' -match 'refs/heads/rebuild/.*-rebuild\.' + + $value = if ($isRebuildBranch) { 'true' } else { 'false' } + Write-Verbose -Message "IsRebuildBranch: $value" -Verbose + + if ($isRebuildBranch) { + Write-Verbose -Message "Rebuild branch detected: $(Build.SourceBranch)" -Verbose + } + + Write-Host "##vso[task.setvariable variable=IsRebuildBranch;isOutput=true]$value" + name: RebuildBranchCheck + displayName: Check if Rebuild Branch From 82ace59b07ca0b046456dd05e391358507b17207 Mon Sep 17 00:00:00 2001 From: Travis Plunk Date: Mon, 10 Nov 2025 13:56:59 -0800 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .pipelines/templates/linux-package-build.yml | 2 +- .pipelines/templates/mac-package-build.yml | 2 +- .pipelines/templates/packaging/windows/package.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pipelines/templates/linux-package-build.yml b/.pipelines/templates/linux-package-build.yml index a28628798b2..bcf332b3778 100644 --- a/.pipelines/templates/linux-package-build.yml +++ b/.pipelines/templates/linux-package-build.yml @@ -149,7 +149,7 @@ jobs: $isRebuildBranch = '$(RebuildBranchCheck.IsRebuildBranch)' -eq 'true' # Don't build LTS packages for rebuild branches - $LTS = ($metadata.LTSRelease.Package -eq 'True') -and -not $isRebuildBranch + $LTS = $metadata.LTSRelease.Package -and -not $isRebuildBranch if ($isRebuildBranch) { Write-Verbose -Message "Rebuild branch detected, skipping LTS package build" -Verbose diff --git a/.pipelines/templates/mac-package-build.yml b/.pipelines/templates/mac-package-build.yml index 28d50ef38e6..4e7040d4acc 100644 --- a/.pipelines/templates/mac-package-build.yml +++ b/.pipelines/templates/mac-package-build.yml @@ -113,7 +113,7 @@ jobs: $isRebuildBranch = '$(RebuildBranchCheck.IsRebuildBranch)' -eq 'true' # Don't build LTS packages for rebuild branches - $LTS = ($metadata.LTSRelease.Package -eq 'True') -and -not $isRebuildBranch + $LTS = $metadata.LTSRelease.Package -and -not $isRebuildBranch if ($isRebuildBranch) { Write-Verbose -Message "Rebuild branch detected, skipping LTS package build" -Verbose diff --git a/.pipelines/templates/packaging/windows/package.yml b/.pipelines/templates/packaging/windows/package.yml index 4e38db3e826..83cdf730b53 100644 --- a/.pipelines/templates/packaging/windows/package.yml +++ b/.pipelines/templates/packaging/windows/package.yml @@ -137,7 +137,7 @@ jobs: $isRebuildBranch = '$(RebuildBranchCheck.IsRebuildBranch)' -eq 'true' # Don't build LTS packages for rebuild branches - $LTS = ($metadata.LTSRelease.Package -eq 'True') -and -not $isRebuildBranch + $LTS = $metadata.LTSRelease.Package -and -not $isRebuildBranch if ($isRebuildBranch) { Write-Verbose -Message "Rebuild branch detected, skipping LTS package build" -Verbose From bd1d63b41a2090f104702ab530bfb3e9d00a1eb5 Mon Sep 17 00:00:00 2001 From: Travis Plunk Date: Mon, 10 Nov 2025 13:57:29 -0800 Subject: [PATCH 3/3] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .pipelines/templates/channelSelection.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.pipelines/templates/channelSelection.yml b/.pipelines/templates/channelSelection.yml index ffc8d83f324..9dd0f3fb216 100644 --- a/.pipelines/templates/channelSelection.yml +++ b/.pipelines/templates/channelSelection.yml @@ -5,6 +5,10 @@ steps: $releaseTag = '$(OutputReleaseTag.releaseTag)' # Rebuild branches should be treated as preview builds + # NOTE: The following regex is duplicated from rebuild-branch-check.yml. + # This duplication is necessary because channelSelection.yml does not call rebuild-branch-check.yml, + # and is used in contexts where that check may not have run. + # If you update this regex, also update it in rebuild-branch-check.yml to keep them in sync. $isRebuildBranch = '$(Build.SourceBranch)' -match 'refs/heads/rebuild/.*-rebuild\.' $LTS = $metadata.LTSRelease.Latest