-
Notifications
You must be signed in to change notification settings - Fork 38
S⚠️ ◾ Automated Package Update #823
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
bf58d05
9dbe45f
f8ad6fe
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) : '')) | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
Comment on lines
+173
to
+174
|
||||||||||||||||||||
| Write-Host ("Searching for package: {0} {1}" -f $PackageId, ($MajorVersion ? ('(major version {0}.*)' -f $MajorVersion) : '')) | |
| $majorVersionMessage = '' | |
| if ($MajorVersion) { | |
| $majorVersionMessage = '(major version {0}.*)' -f $MajorVersion | |
| } | |
| Write-Host ("Searching for package: {0} {1}" -f $PackageId, $majorVersionMessage) | |
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.
Building a command string and running it with Invoke-Expression makes the execution harder to reason about and can become an injection vector if the package id or other inputs ever contain unexpected characters. Prefer invoking dotnet directly with an argument array/call operator and passing --configfile as a normal argument (no string evaluation).
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 script falls back to
NuGet.config, but the repo root file is namedNuGet.Config(capital C). On case-sensitive file systems this fallback will never be found, which can break package lookups whenNuGet-GitHub.Configisn’t present. Update the fallback filename and related log/warning text to use the correct casing.