feat: support NuGet version ranges for gallery dependency types#199
feat: support NuGet version ranges for gallery dependency types#199HeyItsGilbert wants to merge 1 commit into
Conversation
…91) Carry version ranges in the existing Version field using NuGet range syntax (e.g. '[2.2.3,3.0)', '[2.0,)', '(,3.0)') for PSGalleryModule, PSResourceGet, and PSGalleryNuget. A bare version still means an exact version; a range installs the highest available version that satisfies it. Add three private helpers: Compare-Version (IComparable ordering primitive that replaces the duplicated TryParse blocks), ConvertFrom-VersionRange (parser), and Test-VersionInRange (the shared satisfaction predicate). Test-VersionEquality is reimplemented on Compare-Version. PSResourceGet passes the range straight to Install-PSResource; the other two resolve the range to an exact version (find -> filter -> install) since their installers cannot express exclusive bounds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds NuGet-style version range support to PSDepend’s gallery-backed dependency types by allowing ranges to be expressed in the existing Version string field (while keeping bare versions as exact matches for backward compatibility). It centralizes version ordering and range evaluation in shared private helpers, and updates the PSGallery dependency scripts to resolve ranges to a concrete version where native installers can’t express exclusive bounds.
Changes:
- Added shared private helpers:
Compare-Version,ConvertFrom-VersionRange,Test-VersionInRange; reimplementedTest-VersionEqualityon top ofCompare-Version. - Updated
PSGalleryModuleandPSGalleryNugetto resolve a range to the highest satisfying available version before installing (since their installers require exact versions); updatedPSResourceGetto treat ranges as a pass-through for install and for “already satisfied” checks. - Added unit tests for the helpers and expanded type tests for the three affected dependency scripts; updated docs/ADR/changelog.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| PSDepend/PSDependScripts/PSGalleryModule.ps1 | Accepts ranges; resolves range to exact version before Install-Module; uses Test-VersionInRange for installed satisfaction checks |
| PSDepend/PSDependScripts/PSGalleryNuget.ps1 | Accepts ranges; resolves range to exact version before invoking nuget.exe; uses Test-VersionInRange for installed satisfaction checks |
| PSDepend/PSDependScripts/PSResourceGet.ps1 | Uses Test-VersionInRange for installed satisfaction checks; uses Compare-Version for “latest” up-to-date logic |
| PSDepend/Private/Compare-Version.ps1 | New shared ordering primitive for version strings (SemVer → System.Version → string fallback) |
| PSDepend/Private/ConvertFrom-VersionRange.ps1 | New NuGet range parser with exact-vs-range detection based on delimiters |
| PSDepend/Private/Test-VersionInRange.ps1 | New shared predicate for “does installed version satisfy exact or range?” |
| PSDepend/Private/Test-VersionEquality.ps1 | Reimplemented equality via Compare-Version |
| Tests/Compare-Version.Tests.ps1 | New unit tests for Compare-Version |
| Tests/ConvertFrom-VersionRange.Tests.ps1 | New unit tests for range parsing |
| Tests/Test-VersionInRange.Tests.ps1 | New unit tests for range satisfaction semantics |
| Tests/PSGalleryModule.Type.Tests.ps1 | Added range-resolution and satisfaction/skip behavior tests |
| Tests/PSGalleryNuget.Type.Tests.ps1 | Added range-resolution and “no satisfying version” behavior tests |
| Tests/PSResourceGet.Type.Tests.ps1 | Added range pass-through and satisfaction/skip behavior tests |
| CONTEXT.md | Documented the “VersionRange in Version field” concept |
| CHANGELOG.md | Added entry documenting version range support for the three types |
| adr/0001-nuget-version-ranges.md | Added ADR capturing rationale and constraints of NuGet range syntax + exact resolution |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Exact versions map straight to RequiredVersion. Ranges have no Install-Module | ||
| # parameter, so they are resolved to a concrete version just before install. | ||
| $versionRange = $null | ||
| if ($Version -and $Version -ne 'latest') { | ||
| $Params.add('RequiredVersion', $Version) | ||
| $versionRange = ConvertFrom-VersionRange -Version $Version | ||
| if ($versionRange -and $versionRange.IsExact) { | ||
| $Params.add('RequiredVersion', $versionRange.Exact) | ||
| } | ||
| } |
| # Neither type parses both: ordinal string comparison, clamped to -1/0/1. | ||
| return [Math]::Sign( | ||
| [string]::Compare($ReferenceVersion, $DifferenceVersion, [System.StringComparison]::OrdinalIgnoreCase) | ||
| ) |
| # Resolve a version range to the highest available version that satisfies it; | ||
| # nuget.exe -version takes an exact version, not a range. | ||
| $installVersion = $Version | ||
| if ($Version -and $Version -notlike 'latest') { | ||
| $range = ConvertFrom-VersionRange -Version $Version | ||
| if ($range -and -not $range.IsExact) { | ||
| $resolvedVersion = $null | ||
| foreach ($candidate in (Find-NugetPackage -Name $Name -PackageSourceUrl $Source -Credential $Credential)) { | ||
| if ((Test-VersionInRange -Version $candidate.Version -Required $Version) -and | ||
| ($null -eq $resolvedVersion -or (Compare-Version -ReferenceVersion $candidate.Version -DifferenceVersion $resolvedVersion) -gt 0)) { | ||
| $resolvedVersion = $candidate.Version | ||
| } | ||
| } | ||
| if (-not $resolvedVersion) { | ||
| Write-Error "No version of [$Name] at source [$Source] satisfies range [$Version]" | ||
| return | ||
| } | ||
| Write-Verbose "Resolved range [$Version] to version [$resolvedVersion] for [$Name]" | ||
| $installVersion = $resolvedVersion | ||
| } | ||
| } |
Test Results 3 files 75 suites 1m 38s ⏱️ Results for commit 72db206. |
Summary
Adds version-range support to the gallery dependency types, carried in the existing
Versionfield using NuGet range syntax (e.g.'[2.2.3,3.0)','[2.0,)','(,3.0)').'3.2.1') still means that exact version — existing requirements files are unaffected.@{ Pester = '[5.0,6.0)' }) and hash syntax.Supported for
PSGalleryModule,PSResourceGet, andPSGalleryNuget.Design
A string is treated as a range only when it contains a delimiter (
[ ] ( ) ,); otherwise it stays exact. Seeadr/0001-nuget-version-ranges.mdfor the rationale (NuGet syntax over named keys/operator strings; resolving to an exact version instead ofInstall-Module's inclusive-only native params).Implementation
Compare-Version(IComparable ordering primitive, replaces the duplicatedTryParseblocks),ConvertFrom-VersionRange(parser),Test-VersionInRange(shared satisfaction predicate).Test-VersionEqualityreimplemented onCompare-Version.Install-PSResource -Version.Tests
Closes #65
Closes #91
🤖 Generated with Claude Code