Skip to content

feat: support NuGet version ranges for gallery dependency types#199

Open
HeyItsGilbert wants to merge 1 commit into
mainfrom
worktree-enumerated-mixing-hopper
Open

feat: support NuGet version ranges for gallery dependency types#199
HeyItsGilbert wants to merge 1 commit into
mainfrom
worktree-enumerated-mixing-hopper

Conversation

@HeyItsGilbert

Copy link
Copy Markdown
Member

Summary

Adds version-range support to the gallery dependency types, carried in the existing Version field using NuGet range syntax (e.g. '[2.2.3,3.0)', '[2.0,)', '(,3.0)').

  • A bare version ('3.2.1') still means that exact version — existing requirements files are unaffected.
  • A range installs the highest available version that satisfies it.
  • Works in both simple (@{ Pester = '[5.0,6.0)' }) and hash syntax.
  • No OR support (a range is a single contiguous interval).

Supported for PSGalleryModule, PSResourceGet, and PSGalleryNuget.

Design

A string is treated as a range only when it contains a delimiter ([ ] ( ) ,); otherwise it stays exact. See adr/0001-nuget-version-ranges.md for the rationale (NuGet syntax over named keys/operator strings; resolving to an exact version instead of Install-Module's inclusive-only native params).

Implementation

  • New private helpers: Compare-Version (IComparable ordering primitive, replaces the duplicated TryParse blocks), ConvertFrom-VersionRange (parser), Test-VersionInRange (shared satisfaction predicate). Test-VersionEquality reimplemented on Compare-Version.
  • PSResourceGet: pass-through — the range is handed straight to Install-PSResource -Version.
  • PSGalleryModule / PSGalleryNuget: find → filter → install-exact, since their installers cannot express exclusive bounds.

Tests

  • New unit suites for the three helpers; range Contexts added to all three gallery type tests.
  • Full suite green (helpers + gallery types + Meta/analyzer + core), 0 failures.

Closes #65
Closes #91

🤖 Generated with Claude Code

…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>
Copilot AI review requested due to automatic review settings June 15, 2026 16:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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; reimplemented Test-VersionEquality on top of Compare-Version.
  • Updated PSGalleryModule and PSGalleryNuget to resolve a range to the highest satisfying available version before installing (since their installers require exact versions); updated PSResourceGet to 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.

Comment on lines +203 to 211
# 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)
}
}
Comment on lines +73 to +76
# Neither type parses both: ordinal string comparison, clamped to -1/0/1.
return [Math]::Sign(
[string]::Compare($ReferenceVersion, $DifferenceVersion, [System.StringComparison]::OrdinalIgnoreCase)
)
Comment on lines +176 to +196
# 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
}
}
@github-actions

Copy link
Copy Markdown

Test Results

    3 files     75 suites   1m 38s ⏱️
1 059 tests 1 005 ✅ 54 💤 0 ❌
1 431 runs  1 367 ✅ 64 💤 0 ❌

Results for commit 72db206.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Minimum and Maximum Version for the Gallery Support version comparison operators

2 participants