-
Notifications
You must be signed in to change notification settings - Fork 38
S⚠️ ◾ Automated Package Update #818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5a23446
b7f8e53
c0d9eb7
bfb26c8
88eb82c
671dd97
1c56edc
4b27d31
8c3190a
287fbe0
c56db37
1a02929
1cf02c9
331b09d
07d2d47
0455764
1cbd892
3e92781
fc9b6c7
527230e
34493b9
f2afff8
f5431d8
cd5081d
852325b
40ba9dd
379cba4
55e1c51
5d69300
6f35d1d
bbc97ca
6137e99
e4ab9fa
929f317
bb4f02f
9a99f0b
92be031
a821e33
f897fe9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,350 @@ | ||||||||||||||||
| <# | ||||||||||||||||
| .SYNOPSIS | ||||||||||||||||
| Updates NuGet package versions in Directory.Packages.props file. | ||||||||||||||||
|
|
||||||||||||||||
| .DESCRIPTION | ||||||||||||||||
| Scans Directory.Packages.props for PackageVersion elements in ItemGroups labeled 'AutoUpdate', | ||||||||||||||||
| queries the latest available versions using 'dotnet package search', and updates the Version | ||||||||||||||||
| attributes accordingly. Respects PreserveMajor attribute and pre-release version detection. | ||||||||||||||||
|
|
||||||||||||||||
| .PARAMETER PropsFilePath | ||||||||||||||||
| Relative path to the Directory.Packages.props file from the source directory. | ||||||||||||||||
| Default: "Directory.Packages.props" | ||||||||||||||||
|
|
||||||||||||||||
| .PARAMETER SourcesDirectory | ||||||||||||||||
| The root source directory containing the props file. | ||||||||||||||||
| Default: $env:BUILD_SOURCESDIRECTORY (Azure Pipelines variable) | ||||||||||||||||
|
|
||||||||||||||||
| .PARAMETER FailOnError | ||||||||||||||||
| If $true, throws an exception on package lookup failures. If $false, logs warnings and continues. | ||||||||||||||||
| Default: $false | ||||||||||||||||
|
|
||||||||||||||||
| .NOTES | ||||||||||||||||
| Verbose logging is automatically enabled when Azure Pipelines System.Debug is set to 'true'. | ||||||||||||||||
| To enable verbose logging, set the system.debug variable in your pipeline or run with: | ||||||||||||||||
| variables: | ||||||||||||||||
| system.debug: true | ||||||||||||||||
|
|
||||||||||||||||
| .EXAMPLE | ||||||||||||||||
| .\Update-NuGetPackageVersions.ps1 | ||||||||||||||||
|
|
||||||||||||||||
| .EXAMPLE | ||||||||||||||||
| .\Update-NuGetPackageVersions.ps1 -PropsFilePath "Directory.Packages.props" -FailOnError $true | ||||||||||||||||
|
|
||||||||||||||||
| .EXAMPLE | ||||||||||||||||
| $env:SYSTEM_DEBUG = 'true'; .\Update-NuGetPackageVersions.ps1 | ||||||||||||||||
| #> | ||||||||||||||||
|
|
||||||||||||||||
| [CmdletBinding()] | ||||||||||||||||
| param( | ||||||||||||||||
| [Parameter(Mandatory = $false)] | ||||||||||||||||
| [string]$PropsFilePath = "Directory.Packages.props", | ||||||||||||||||
|
|
||||||||||||||||
| [Parameter(Mandatory = $false)] | ||||||||||||||||
| [string]$SourcesDirectory = $( | ||||||||||||||||
| if ($env:BUILD_SOURCESDIRECTORY) { | ||||||||||||||||
| $env:BUILD_SOURCESDIRECTORY | ||||||||||||||||
| } | ||||||||||||||||
| elseif ($env:GITHUB_WORKSPACE) { | ||||||||||||||||
| $env:GITHUB_WORKSPACE | ||||||||||||||||
| } | ||||||||||||||||
| else { | ||||||||||||||||
| (Get-Location).Path | ||||||||||||||||
| } | ||||||||||||||||
| ), | ||||||||||||||||
|
|
||||||||||||||||
| [Parameter(Mandatory = $false)] | ||||||||||||||||
| [bool]$FailOnError = $false | ||||||||||||||||
| ) | ||||||||||||||||
|
|
||||||||||||||||
| # Normalize and validate SourcesDirectory so it is always a valid root directory | ||||||||||||||||
| if ([string]::IsNullOrWhiteSpace($SourcesDirectory)) { | ||||||||||||||||
| # GitHub Actions default | ||||||||||||||||
| $SourcesDirectory = $env:GITHUB_WORKSPACE | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| if ([string]::IsNullOrWhiteSpace($SourcesDirectory)) { | ||||||||||||||||
| # Local or generic PowerShell fallback | ||||||||||||||||
| $SourcesDirectory = (Get-Location).Path | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| if (-not (Test-Path -LiteralPath $SourcesDirectory -PathType Container)) { | ||||||||||||||||
| throw "SourcesDirectory '$SourcesDirectory' does not exist or is not a directory. Specify a valid -SourcesDirectory path." | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| # Resolve to a fully qualified, normalized path | ||||||||||||||||
| $SourcesDirectory = (Resolve-Path -LiteralPath $SourcesDirectory).ProviderPath | ||||||||||||||||
| # Determine whether verbose logging should be enabled: | ||||||||||||||||
| # - Prefer the standard -Verbose common parameter when explicitly passed | ||||||||||||||||
| # - Fall back to Azure Pipelines System.Debug variable for backwards compatibility | ||||||||||||||||
| $isVerboseParameterSet = $PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters['Verbose'] | ||||||||||||||||
| $EnableVerboseLogging = $isVerboseParameterSet -or ($env:SYSTEM_DEBUG -eq 'true') -or ($env:SYSTEM_DEBUG -eq '1') | ||||||||||||||||
|
|
||||||||||||||||
| if ($EnableVerboseLogging) { | ||||||||||||||||
| $VerbosePreference = 'Continue' | ||||||||||||||||
| } | ||||||||||||||||
| $ErrorActionPreference = if ($FailOnError) { "Stop" } else { "Continue" } | ||||||||||||||||
|
|
||||||||||||||||
| # Helper function for version comparison (from VersionUtils.ps1) | ||||||||||||||||
| function Get-LatestVersionFromString { | ||||||||||||||||
| param ( | ||||||||||||||||
| [string]$First, | ||||||||||||||||
| [string]$Second | ||||||||||||||||
| ) | ||||||||||||||||
|
|
||||||||||||||||
| if (-not $First) { return $Second } | ||||||||||||||||
| if (-not $Second) { return $First } | ||||||||||||||||
|
|
||||||||||||||||
| function Get-VersionFromString { | ||||||||||||||||
| param ([string]$Value) | ||||||||||||||||
|
|
||||||||||||||||
| $splitIndex = $Value.IndexOf('-') | ||||||||||||||||
| if ($splitIndex -eq -1) { | ||||||||||||||||
| $versionString = $Value | ||||||||||||||||
| $suffix = '' | ||||||||||||||||
| } else { | ||||||||||||||||
| $versionString = $Value.Substring(0, $splitIndex) | ||||||||||||||||
| $suffix = $Value.Substring($splitIndex) | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| $version = $null | ||||||||||||||||
| if (-not [System.Version]::TryParse($versionString, [ref]$version)) { | ||||||||||||||||
| $version = $versionString | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| return [PSCustomObject]@{ Version = $version; Suffix = $suffix } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| $firstVersionObject = Get-VersionFromString $First | ||||||||||||||||
| $secondVersionObject = Get-VersionFromString $Second | ||||||||||||||||
|
|
||||||||||||||||
| if ($firstVersionObject.Version -eq $secondVersionObject.Version) { | ||||||||||||||||
| if (-not $firstVersionObject.Suffix) { return $First } | ||||||||||||||||
| if (-not $secondVersionObject.Suffix) { return $Second } | ||||||||||||||||
| if ($firstVersionObject.Suffix -lt $secondVersionObject.Suffix) { return $Second } | ||||||||||||||||
| return $First | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| if ($firstVersionObject.Version -lt $secondVersionObject.Version) { return $Second } | ||||||||||||||||
| return $First | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| function Test-PreReleaseVersion { | ||||||||||||||||
| param ([string]$Version) | ||||||||||||||||
| return $Version.Contains('-') | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| function Get-LatestPackageVersion { | ||||||||||||||||
| param ( | ||||||||||||||||
| [string]$PackageId, | ||||||||||||||||
| [bool]$IncludePrerelease, | ||||||||||||||||
| [string]$MajorVersion = "" | ||||||||||||||||
| ) | ||||||||||||||||
|
|
||||||||||||||||
| try { | ||||||||||||||||
| $prereleaseFlag = if ($IncludePrerelease) { "--prerelease" } else { "" } | ||||||||||||||||
|
|
||||||||||||||||
| # Prefer NuGet-GitHub.Config (used on GitHub runners) when present, otherwise fall back to NuGet.config | ||||||||||||||||
| $nugetGithubConfigPath = Join-Path $SourcesDirectory "NuGet-GitHub.Config" | ||||||||||||||||
| $nugetConfigPath = Join-Path $SourcesDirectory "NuGet.config" | ||||||||||||||||
| $configSourceFlag = "" | ||||||||||||||||
| if (Test-Path $nugetGithubConfigPath) { | ||||||||||||||||
| $configSourceFlag = "--configfile `"$nugetGithubConfigPath`"" | ||||||||||||||||
| if ($EnableVerboseLogging) { | ||||||||||||||||
| Write-Host " [VERBOSE] Using NuGet-GitHub.Config from: $nugetGithubConfigPath" | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| elseif (Test-Path $nugetConfigPath) { | ||||||||||||||||
| $configSourceFlag = "--configfile `"$nugetConfigPath`"" | ||||||||||||||||
| if ($EnableVerboseLogging) { | ||||||||||||||||
| Write-Host " [VERBOSE] Using NuGet.config from: $nugetConfigPath" | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| else { | ||||||||||||||||
| Write-Warning "NuGet-GitHub.Config or NuGet.config not found at: $SourcesDirectory - search may not find required feeds" | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| $searchCmd = "dotnet package search `"$PackageId`" --exact-match --format json $prereleaseFlag $configSourceFlag" | ||||||||||||||||
|
|
||||||||||||||||
| if ($EnableVerboseLogging) { | ||||||||||||||||
| Write-Host " [VERBOSE] Executing: $searchCmd" | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| Write-Host ("Searching for package: {0} {1}" -f $PackageId, ($MajorVersion ? ('(major version {0}.*)' -f $MajorVersion) : '')) | ||||||||||||||||
|
||||||||||||||||
| Write-Host ("Searching for package: {0} {1}" -f $PackageId, ($MajorVersion ? ('(major version {0}.*)' -f $MajorVersion) : '')) | |
| $majorVersionSuffix = "" | |
| if ($MajorVersion) { | |
| $majorVersionSuffix = '(major version {0}.*)' -f $MajorVersion | |
| } | |
| Write-Host ("Searching for package: {0} {1}" -f $PackageId, $majorVersionSuffix) |
Copilot
AI
Feb 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Saving via XmlDocument.Save() is reformatting the props file (BOM, attribute spacing, etc.), which makes automated PRs much noisier than necessary. Consider updating only the Version attribute values in-place without reserializing the full XML (or use an XML writer/settings approach that preserves the original formatting/encoding).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The repo root contains
NuGet.Config(capital C). This script falls back toNuGet.config, which will fail on case-sensitive filesystems (and won’t match the repo’s actual filename). Update the fallback path/message to useNuGet.Config.