mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 17:56:44 +02:00
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request This pull request introduces an "artifact-based" mode for consuming the Windows App SDK in CI pipelines, allowing builds to use NuGet packages directly from Azure DevOps pipeline artifacts instead of public/internal feeds. This is achieved by adding new parameters and logic to pipeline YAML and PowerShell scripts, supporting scenarios where packages are not yet published to a feed. The changes also improve robustness when updating package versions and add documentation for authentication requirements. These changes make the pipeline more flexible and robust, enabling builds to consume unreleased or pre-release packages directly from CI artifacts, which is especially useful for testing and validation scenarios. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] Closes: #xxx <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
601 lines
22 KiB
PowerShell
601 lines
22 KiB
PowerShell
Param(
|
|
# Using the default value of 1.7 for winAppSdkVersionNumber and useExperimentalVersion as false
|
|
[Parameter(Mandatory=$False,Position=1)]
|
|
[string]$winAppSdkVersionNumber = "1.8",
|
|
|
|
# When the pipeline calls the PS1 file, the passed parameters are converted to string type
|
|
[Parameter(Mandatory=$False,Position=2)]
|
|
[boolean]$useExperimentalVersion = $False,
|
|
|
|
# Root folder Path for processing
|
|
[Parameter(Mandatory=$False,Position=3)]
|
|
[string]$rootPath = $(Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)),
|
|
|
|
# Root folder Path for processing
|
|
[Parameter(Mandatory=$False,Position=4)]
|
|
[string]$sourceLink = "https://microsoft.pkgs.visualstudio.com/ProjectReunion/_packaging/Project.Reunion.nuget.internal/nuget/v3/index.json",
|
|
|
|
# Use Azure Pipeline artifact as source for metapackage
|
|
[Parameter(Mandatory=$False,Position=5)]
|
|
[boolean]$useArtifactSource = $False,
|
|
|
|
# Azure DevOps organization URL
|
|
[Parameter(Mandatory=$False,Position=6)]
|
|
[string]$azureDevOpsOrg = "https://dev.azure.com/microsoft",
|
|
|
|
# Azure DevOps project name
|
|
[Parameter(Mandatory=$False,Position=7)]
|
|
[string]$azureDevOpsProject = "ProjectReunion",
|
|
|
|
# Pipeline build ID (or "latest" for latest build)
|
|
[Parameter(Mandatory=$False,Position=8)]
|
|
[string]$buildId = "",
|
|
|
|
# Artifact name containing the NuGet packages
|
|
[Parameter(Mandatory=$False,Position=9)]
|
|
[string]$artifactName = "WindowsAppSDK_Nuget_And_MSIX",
|
|
|
|
# Metapackage name to look for in artifact
|
|
[Parameter(Mandatory=$False,Position=10)]
|
|
[string]$metaPackageName = "Microsoft.WindowsAppSDK"
|
|
)
|
|
|
|
# Script-level constants
|
|
$script:PackageVersionRegex = '^(.+?)\.(\d+\..*)$'
|
|
|
|
|
|
|
|
function Read-FileWithEncoding {
|
|
param (
|
|
[string]$Path
|
|
)
|
|
|
|
$reader = New-Object System.IO.StreamReader($Path, $true) # auto-detect encoding
|
|
$content = $reader.ReadToEnd()
|
|
$encoding = $reader.CurrentEncoding
|
|
$reader.Close()
|
|
|
|
return [PSCustomObject]@{
|
|
Content = $content
|
|
Encoding = $encoding
|
|
}
|
|
}
|
|
|
|
function Write-FileWithEncoding {
|
|
param (
|
|
[string]$Path,
|
|
[string]$Content,
|
|
[System.Text.Encoding]$Encoding
|
|
)
|
|
|
|
$writer = New-Object System.IO.StreamWriter($Path, $false, $Encoding)
|
|
$writer.Write($Content)
|
|
$writer.Close()
|
|
}
|
|
|
|
|
|
function Add-NuGetSourceAndMapping {
|
|
param (
|
|
[xml]$Xml,
|
|
[string]$Key,
|
|
[string]$Value,
|
|
[string[]]$Patterns
|
|
)
|
|
|
|
# Ensure packageSources exists
|
|
if (-not $Xml.configuration.packageSources) {
|
|
$null = $Xml.configuration.AppendChild($Xml.CreateElement("packageSources"))
|
|
}
|
|
$sources = $Xml.configuration.packageSources
|
|
|
|
# Add/Update Source
|
|
$sourceNode = $sources.SelectSingleNode("add[@key='$Key']")
|
|
if (-not $sourceNode) {
|
|
$sourceNode = $Xml.CreateElement("add")
|
|
$sourceNode.SetAttribute("key", $Key)
|
|
$null = $sources.AppendChild($sourceNode)
|
|
}
|
|
$sourceNode.SetAttribute("value", $Value)
|
|
|
|
# Ensure packageSourceMapping exists
|
|
if (-not $Xml.configuration.packageSourceMapping) {
|
|
$null = $Xml.configuration.AppendChild($Xml.CreateElement("packageSourceMapping"))
|
|
}
|
|
$mapping = $Xml.configuration.packageSourceMapping
|
|
|
|
# Remove invalid packageSource nodes (missing key or empty key)
|
|
$invalidNodes = $mapping.SelectNodes("packageSource[not(@key) or @key='']")
|
|
if ($invalidNodes) {
|
|
foreach ($node in $invalidNodes) {
|
|
$null = $mapping.RemoveChild($node)
|
|
}
|
|
}
|
|
|
|
# Add/Update Mapping Source
|
|
$mappingSource = $mapping.SelectSingleNode("packageSource[@key='$Key']")
|
|
if (-not $mappingSource) {
|
|
$mappingSource = $Xml.CreateElement("packageSource")
|
|
$mappingSource.SetAttribute("key", $Key)
|
|
# Insert at top for priority
|
|
if ($mapping.HasChildNodes) {
|
|
$null = $mapping.InsertBefore($mappingSource, $mapping.FirstChild)
|
|
} else {
|
|
$null = $mapping.AppendChild($mappingSource)
|
|
}
|
|
}
|
|
|
|
# Double check and force attribute
|
|
if (-not $mappingSource.HasAttribute("key")) {
|
|
$mappingSource.SetAttribute("key", $Key)
|
|
}
|
|
|
|
# Update Patterns
|
|
# RemoveAll() removes all child nodes AND attributes, so we must re-set the key afterwards
|
|
$mappingSource.RemoveAll()
|
|
$mappingSource.SetAttribute("key", $Key)
|
|
|
|
foreach ($pattern in $Patterns) {
|
|
$pkg = $Xml.CreateElement("package")
|
|
$pkg.SetAttribute("pattern", $pattern)
|
|
$null = $mappingSource.AppendChild($pkg)
|
|
}
|
|
}
|
|
|
|
function Download-ArtifactFromPipeline {
|
|
param (
|
|
[string]$Organization,
|
|
[string]$Project,
|
|
[string]$BuildId,
|
|
[string]$ArtifactName,
|
|
[string]$OutputDir
|
|
)
|
|
|
|
Write-Host "Downloading artifact '$ArtifactName' from build $BuildId..."
|
|
$null = New-Item -ItemType Directory -Path $OutputDir -Force
|
|
|
|
try {
|
|
# Authenticate with Azure DevOps using System Access Token (if available)
|
|
if ($env:SYSTEM_ACCESSTOKEN) {
|
|
Write-Host "Authenticating with Azure DevOps using System Access Token..."
|
|
$env:AZURE_DEVOPS_EXT_PAT = $env:SYSTEM_ACCESSTOKEN
|
|
} else {
|
|
Write-Host "No SYSTEM_ACCESSTOKEN found, assuming az CLI is already authenticated..."
|
|
}
|
|
|
|
# Use az CLI to download artifact
|
|
& az pipelines runs artifact download `
|
|
--organization $Organization `
|
|
--project $Project `
|
|
--run-id $BuildId `
|
|
--artifact-name $ArtifactName `
|
|
--path $OutputDir
|
|
|
|
if ($LASTEXITCODE -eq 0) {
|
|
Write-Host "Successfully downloaded artifact to $OutputDir"
|
|
return $true
|
|
} else {
|
|
Write-Warning "Failed to download artifact. Exit code: $LASTEXITCODE"
|
|
return $false
|
|
}
|
|
} catch {
|
|
Write-Warning "Error downloading artifact: $_"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Get-NuspecDependencies {
|
|
param (
|
|
[string]$NupkgPath,
|
|
[string]$TargetFramework = ""
|
|
)
|
|
|
|
$tempDir = Join-Path $env:TEMP "nuspec_parse_$(Get-Random)"
|
|
|
|
try {
|
|
# Extract .nupkg (it's a zip file)
|
|
# Workaround: Expand-Archive may not recognize .nupkg extension, so copy to .zip first
|
|
$tempZip = Join-Path $env:TEMP "temp_$(Get-Random).zip"
|
|
Copy-Item $NupkgPath -Destination $tempZip -Force
|
|
Expand-Archive -Path $tempZip -DestinationPath $tempDir -Force
|
|
Remove-Item $tempZip -Force -ErrorAction SilentlyContinue
|
|
|
|
# Find .nuspec file
|
|
$nuspecFile = Get-ChildItem -Path $tempDir -Filter "*.nuspec" -Recurse | Select-Object -First 1
|
|
|
|
if (-not $nuspecFile) {
|
|
Write-Warning "No .nuspec file found in $NupkgPath"
|
|
return @{}
|
|
}
|
|
|
|
[xml]$nuspec = Get-Content $nuspecFile.FullName
|
|
|
|
# Extract package info
|
|
$packageId = $nuspec.package.metadata.id
|
|
$version = $nuspec.package.metadata.version
|
|
Write-Host "Parsing $packageId version $version"
|
|
|
|
# Parse dependencies
|
|
$dependencies = @{}
|
|
$depGroups = $nuspec.package.metadata.dependencies.group
|
|
|
|
if ($depGroups) {
|
|
# Dependencies are grouped by target framework
|
|
foreach ($group in $depGroups) {
|
|
$fx = $group.targetFramework
|
|
Write-Host " Target Framework: $fx"
|
|
|
|
foreach ($dep in $group.dependency) {
|
|
$depId = $dep.id
|
|
$depVer = $dep.version
|
|
# Remove version range brackets if present (e.g., "[2.0.0]" -> "2.0.0")
|
|
$depVer = $depVer -replace '[\[\]]', ''
|
|
$dependencies[$depId] = $depVer
|
|
Write-Host " - ${depId} : ${depVer}"
|
|
}
|
|
}
|
|
} else {
|
|
# No grouping, direct dependencies
|
|
$deps = $nuspec.package.metadata.dependencies.dependency
|
|
if ($deps) {
|
|
foreach ($dep in $deps) {
|
|
$depId = $dep.id
|
|
$depVer = $dep.version
|
|
$depVer = $depVer -replace '[\[\]]', ''
|
|
$dependencies[$depId] = $depVer
|
|
Write-Host " - ${depId} : ${depVer}"
|
|
}
|
|
}
|
|
}
|
|
|
|
return $dependencies
|
|
}
|
|
catch {
|
|
Write-Warning "Failed to parse nuspec: $_"
|
|
return @{}
|
|
}
|
|
finally {
|
|
Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
|
|
function Resolve-ArtifactBasedDependencies {
|
|
param (
|
|
[string]$ArtifactDir,
|
|
[string]$MetaPackageName,
|
|
[string]$SourceUrl,
|
|
[string]$OutputDir
|
|
)
|
|
|
|
Write-Host "Resolving dependencies from artifact-based metapackage..."
|
|
$null = New-Item -ItemType Directory -Path $OutputDir -Force
|
|
|
|
# Find the metapackage in artifact
|
|
$metaNupkg = Get-ChildItem -Path $ArtifactDir -Recurse -Filter "$MetaPackageName.*.nupkg" |
|
|
Where-Object { $_.Name -notmatch "Runtime" } |
|
|
Select-Object -First 1
|
|
|
|
if (-not $metaNupkg) {
|
|
Write-Warning "Metapackage $MetaPackageName not found in artifact"
|
|
return @{}
|
|
}
|
|
|
|
# Extract version from filename
|
|
if ($metaNupkg.Name -match "$MetaPackageName\.(.+)\.nupkg") {
|
|
$metaVersion = $Matches[1]
|
|
Write-Host "Found metapackage: $MetaPackageName version $metaVersion"
|
|
} else {
|
|
Write-Warning "Could not extract version from $($metaNupkg.Name)"
|
|
return @{}
|
|
}
|
|
|
|
# Parse dependencies from metapackage
|
|
$dependencies = Get-NuspecDependencies -NupkgPath $metaNupkg.FullName
|
|
|
|
# Copy metapackage to output directory
|
|
Copy-Item $metaNupkg.FullName -Destination $OutputDir -Force
|
|
Write-Host "Copied metapackage to $OutputDir"
|
|
|
|
# Prepare package versions hashtable - initialize with metapackage version
|
|
$packageVersions = @{ $MetaPackageName = $metaVersion }
|
|
|
|
# Copy Runtime package from artifact (it's not in feed) and extract its version
|
|
$runtimeNupkg = Get-ChildItem -Path $ArtifactDir -Recurse -Filter "$MetaPackageName.Runtime.*.nupkg" | Select-Object -First 1
|
|
if ($runtimeNupkg) {
|
|
Copy-Item $runtimeNupkg.FullName -Destination $OutputDir -Force
|
|
Write-Host "Copied Runtime package to $OutputDir"
|
|
|
|
# Extract version from Runtime package filename
|
|
if ($runtimeNupkg.Name -match "$MetaPackageName\.Runtime\.(.+)\.nupkg") {
|
|
$runtimeVersion = $Matches[1]
|
|
$packageVersions["$MetaPackageName.Runtime"] = $runtimeVersion
|
|
Write-Host "Extracted Runtime package version: $runtimeVersion"
|
|
} else {
|
|
Write-Warning "Could not extract version from Runtime package: $($runtimeNupkg.Name)"
|
|
}
|
|
}
|
|
|
|
# Download other dependencies from feed (excluding Runtime as it's already copied)
|
|
# Create temp nuget.config that includes both local packages and remote feed
|
|
# This allows NuGet to find packages already copied from artifact
|
|
$tempConfig = Join-Path $env:TEMP "nuget_artifact_$(Get-Random).config"
|
|
$tempConfigContent = @"
|
|
<?xml version='1.0' encoding='utf-8'?>
|
|
<configuration>
|
|
<packageSources>
|
|
<clear />
|
|
<add key='LocalPackages' value='$OutputDir' />
|
|
<add key='RemoteFeed' value='$SourceUrl' />
|
|
</packageSources>
|
|
</configuration>
|
|
"@
|
|
Set-Content -Path $tempConfig -Value $tempConfigContent
|
|
|
|
try {
|
|
foreach ($depId in $dependencies.Keys) {
|
|
# Skip Runtime as it's already copied from artifact
|
|
if ($depId -like "*Runtime*") {
|
|
# Don't overwrite the version we extracted from the Runtime package filename
|
|
if (-not $packageVersions.ContainsKey($depId)) {
|
|
$packageVersions[$depId] = $dependencies[$depId]
|
|
}
|
|
Write-Host "Skipping $depId (already in artifact)"
|
|
continue
|
|
}
|
|
|
|
$depVersion = $dependencies[$depId]
|
|
Write-Host "Downloading dependency: $depId version $depVersion from feed..."
|
|
|
|
& nuget install $depId `
|
|
-Version $depVersion `
|
|
-ConfigFile $tempConfig `
|
|
-OutputDirectory $OutputDir `
|
|
-NonInteractive `
|
|
-NoCache `
|
|
| Out-Null
|
|
|
|
if ($LASTEXITCODE -eq 0) {
|
|
$packageVersions[$depId] = $depVersion
|
|
Write-Host " Successfully downloaded $depId"
|
|
} else {
|
|
Write-Warning " Failed to download $depId version $depVersion"
|
|
}
|
|
}
|
|
}
|
|
finally {
|
|
Remove-Item $tempConfig -Force -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
# Parse all downloaded packages to get actual versions
|
|
$directories = Get-ChildItem -Path $OutputDir -Directory
|
|
$allLocalPackages = @()
|
|
|
|
# Add metapackage and runtime to the list (they are .nupkg files, not directories)
|
|
$allLocalPackages += $MetaPackageName
|
|
if ($packageVersions.ContainsKey("$MetaPackageName.Runtime")) {
|
|
$allLocalPackages += "$MetaPackageName.Runtime"
|
|
}
|
|
|
|
foreach ($dir in $directories) {
|
|
if ($dir.Name -match $script:PackageVersionRegex) {
|
|
$pkgId = $Matches[1]
|
|
$pkgVer = $Matches[2]
|
|
$allLocalPackages += $pkgId
|
|
if (-not $packageVersions.ContainsKey($pkgId)) {
|
|
$packageVersions[$pkgId] = $pkgVer
|
|
}
|
|
}
|
|
}
|
|
|
|
# Update nuget.config dynamically during pipeline execution
|
|
# This modification is temporary and won't be committed back to the repo
|
|
$nugetConfig = Join-Path $rootPath "nuget.config"
|
|
$configData = Read-FileWithEncoding -Path $nugetConfig
|
|
[xml]$xml = $configData.Content
|
|
|
|
Add-NuGetSourceAndMapping -Xml $xml -Key "localpackages" -Value $OutputDir -Patterns $allLocalPackages
|
|
|
|
$xml.Save($nugetConfig)
|
|
Write-Host "Updated nuget.config with localpackages mapping (temporary, for pipeline execution only)."
|
|
|
|
return ,$packageVersions
|
|
}
|
|
|
|
function Resolve-WinAppSdkSplitDependencies {
|
|
Write-Host "Version $WinAppSDKVersion detected. Resolving split dependencies..."
|
|
$installDir = Join-Path $rootPath "localpackages\output"
|
|
$null = New-Item -ItemType Directory -Path $installDir -Force
|
|
|
|
# Create a temporary nuget.config to avoid interference from the repo's config
|
|
$tempConfig = Join-Path $env:TEMP "nuget_$(Get-Random).config"
|
|
Set-Content -Path $tempConfig -Value "<?xml version='1.0' encoding='utf-8'?><configuration><packageSources><clear /><add key='TempSource' value='$sourceLink' /></packageSources></configuration>"
|
|
|
|
try {
|
|
# Extract BuildTools version from Directory.Packages.props to ensure we have the required version
|
|
$dirPackagesProps = Join-Path $rootPath "Directory.Packages.props"
|
|
if (Test-Path $dirPackagesProps) {
|
|
$propsContent = Get-Content $dirPackagesProps -Raw
|
|
if ($propsContent -match '<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="([^"]+)"') {
|
|
$buildToolsVersion = $Matches[1]
|
|
Write-Host "Downloading Microsoft.Windows.SDK.BuildTools version $buildToolsVersion..."
|
|
& nuget install Microsoft.Windows.SDK.BuildTools `
|
|
-Version $buildToolsVersion `
|
|
-ConfigFile $tempConfig `
|
|
-OutputDirectory $installDir `
|
|
-NonInteractive `
|
|
-NoCache `
|
|
| Out-Null
|
|
}
|
|
}
|
|
|
|
# Download package to inspect nuspec and keep it for the build
|
|
& nuget install Microsoft.WindowsAppSDK `
|
|
-Version $WinAppSDKVersion `
|
|
-ConfigFile $tempConfig `
|
|
-OutputDirectory $installDir `
|
|
-NonInteractive `
|
|
-NoCache `
|
|
| Out-Null
|
|
|
|
# Parse dependencies from the installed folders
|
|
# Folder structure is typically {PackageId}.{Version}
|
|
$directories = Get-ChildItem -Path $installDir -Directory
|
|
$allLocalPackages = @()
|
|
foreach ($dir in $directories) {
|
|
# Match any package pattern: PackageId.Version
|
|
if ($dir.Name -match "^(.+?)\.(\d+\..*)$") {
|
|
$pkgId = $Matches[1]
|
|
$pkgVer = $Matches[2]
|
|
$allLocalPackages += $pkgId
|
|
|
|
$packageVersions[$pkgId] = $pkgVer
|
|
Write-Host "Found dependency: $pkgId = $pkgVer"
|
|
}
|
|
}
|
|
|
|
# Update repo's nuget.config to use localpackages
|
|
$nugetConfig = Join-Path $rootPath "nuget.config"
|
|
$configData = Read-FileWithEncoding -Path $nugetConfig
|
|
[xml]$xml = $configData.Content
|
|
|
|
Add-NuGetSourceAndMapping -Xml $xml -Key "localpackages" -Value $installDir -Patterns $allLocalPackages
|
|
|
|
$xml.Save($nugetConfig)
|
|
Write-Host "Updated nuget.config with localpackages mapping."
|
|
} catch {
|
|
Write-Warning "Failed to resolve dependencies: $_"
|
|
} finally {
|
|
Remove-Item $tempConfig -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
|
|
# Main logic: choose between artifact-based or feed-based approach
|
|
if ($useArtifactSource) {
|
|
Write-Host "=== Using Artifact-Based Source ===" -ForegroundColor Cyan
|
|
Write-Host "Organization: $azureDevOpsOrg"
|
|
Write-Host "Project: $azureDevOpsProject"
|
|
Write-Host "Build ID: $buildId"
|
|
Write-Host "Artifact: $artifactName"
|
|
|
|
if ([string]::IsNullOrEmpty($buildId) -or $buildId -eq 'N/A') {
|
|
Write-Error "buildId parameter is required when using artifact source. Please provide a valid Windows App SDK Build ID."
|
|
Write-Host "Tip: You can find the build ID from the Windows App SDK pipeline run in Azure DevOps."
|
|
exit 1
|
|
}
|
|
|
|
# Download artifact
|
|
$artifactDir = Join-Path $rootPath "localpackages\artifact"
|
|
$downloadSuccess = Download-ArtifactFromPipeline `
|
|
-Organization $azureDevOpsOrg `
|
|
-Project $azureDevOpsProject `
|
|
-BuildId $buildId `
|
|
-ArtifactName $artifactName `
|
|
-OutputDir $artifactDir
|
|
|
|
if (-not $downloadSuccess) {
|
|
Write-Host "Failed to download artifact"
|
|
exit 1
|
|
}
|
|
|
|
# Resolve dependencies from artifact
|
|
$installDir = Join-Path $rootPath "localpackages\output"
|
|
$packageVersions = Resolve-ArtifactBasedDependencies `
|
|
-ArtifactDir $artifactDir `
|
|
-MetaPackageName $metaPackageName `
|
|
-SourceUrl $sourceLink `
|
|
-OutputDir $installDir
|
|
|
|
if ($packageVersions.Count -eq 0) {
|
|
Write-Error "Failed to resolve dependencies from artifact"
|
|
exit 1
|
|
}
|
|
|
|
$WinAppSDKVersion = $packageVersions[$metaPackageName]
|
|
Write-Host "WinAppSDK Version: $WinAppSDKVersion"
|
|
Write-Host "##vso[task.setvariable variable=WinAppSDKVersion]$WinAppSDKVersion"
|
|
|
|
} else {
|
|
Write-Host "=== Using Feed-Based Source ===" -ForegroundColor Cyan
|
|
|
|
# Execute nuget list and capture the output
|
|
if ($useExperimentalVersion) {
|
|
# The nuget list for experimental versions will cost more time
|
|
# So, we will not use -AllVersions to wast time
|
|
# But it can only get the latest experimental version
|
|
Write-Host "Fetching WindowsAppSDK with experimental versions"
|
|
$nugetOutput = nuget list Microsoft.WindowsAppSDK `
|
|
-Source $sourceLink `
|
|
-Prerelease
|
|
# Filter versions based on the specified version prefix
|
|
$escapedVersionNumber = [regex]::Escape($winAppSdkVersionNumber)
|
|
$filteredVersions = $nugetOutput | Where-Object { $_ -match "Microsoft.WindowsAppSDK $escapedVersionNumber\." }
|
|
$latestVersions = $filteredVersions
|
|
} else {
|
|
Write-Host "Fetching stable WindowsAppSDK versions for $winAppSdkVersionNumber"
|
|
$nugetOutput = nuget list Microsoft.WindowsAppSDK `
|
|
-Source $sourceLink `
|
|
-AllVersions
|
|
# Filter versions based on the specified version prefix
|
|
$escapedVersionNumber = [regex]::Escape($winAppSdkVersionNumber)
|
|
$filteredVersions = $nugetOutput | Where-Object { $_ -match "Microsoft.WindowsAppSDK $escapedVersionNumber\." }
|
|
$latestVersions = $filteredVersions | Sort-Object { [version]($_ -split ' ')[1] } -Descending | Select-Object -First 1
|
|
}
|
|
|
|
Write-Host "Latest versions found: $latestVersions"
|
|
# Extract the latest version number from the output
|
|
$latestVersion = $latestVersions -split "`n" | `
|
|
Select-String -Pattern 'Microsoft.WindowsAppSDK\s*([0-9]+\.[0-9]+\.[0-9]+-*[a-zA-Z0-9]*)' | `
|
|
ForEach-Object { $_.Matches[0].Groups[1].Value } | `
|
|
Sort-Object -Descending | `
|
|
Select-Object -First 1
|
|
|
|
if ($latestVersion) {
|
|
$WinAppSDKVersion = $latestVersion
|
|
Write-Host "Extracted version: $WinAppSDKVersion"
|
|
Write-Host "##vso[task.setvariable variable=WinAppSDKVersion]$WinAppSDKVersion"
|
|
} else {
|
|
Write-Host "Failed to extract version number from nuget list output"
|
|
exit 1
|
|
}
|
|
|
|
# Resolve dependencies for 1.8+
|
|
$packageVersions = @{ "Microsoft.WindowsAppSDK" = $WinAppSDKVersion }
|
|
|
|
Resolve-WinAppSdkSplitDependencies
|
|
}
|
|
|
|
# Update Directory.Packages.props file
|
|
Get-ChildItem -Path $rootPath -Recurse "Directory.Packages.props" | ForEach-Object {
|
|
$file = Read-FileWithEncoding -Path $_.FullName
|
|
$content = $file.Content
|
|
$isModified = $false
|
|
|
|
foreach ($pkgId in $packageVersions.Keys) {
|
|
$ver = $packageVersions[$pkgId]
|
|
|
|
# Skip packages with empty versions to prevent corruption
|
|
if ([string]::IsNullOrWhiteSpace($ver)) {
|
|
Write-Warning "Skipping ${pkgId}: version is empty"
|
|
continue
|
|
}
|
|
|
|
# Escape dots in package ID for regex
|
|
$pkgIdRegex = $pkgId -replace '\.', '\.'
|
|
|
|
$newVersionString = "<PackageVersion Include=""$pkgId"" Version=""$ver"" />"
|
|
$oldVersionString = "<PackageVersion Include=""$pkgIdRegex"" Version=""[-.0-9a-zA-Z]*"" />"
|
|
|
|
if ($content -match "<PackageVersion Include=""$pkgIdRegex""") {
|
|
# Update existing package
|
|
if ($content -notmatch [regex]::Escape($newVersionString)) {
|
|
$content = $content -replace $oldVersionString, $newVersionString
|
|
$isModified = $true
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($isModified) {
|
|
Write-FileWithEncoding -Path $_.FullName -Content $content -Encoding $file.encoding
|
|
Write-Host "Modified " $_.FullName
|
|
}
|
|
}
|