You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds an opt-in Resolve PSDependAction. A supporting DependencyScript queries its source and returns one exact PSDepend.ResolvedDependency without installing. Implemented for PSGalleryModule, PSResourceGet, PSGalleryNuget, Nuget, Chocolatey, and Npm.
Update-PSDependLock resolves one version per DependencyType::Name, intersects constraints from every parent, re-resolves invalidated children, and writes <name>.lock.json next to the DependencyFile.
Resolution is deliberately greedy: it does not backtrack to an older parent version. Narrow the parent range when an older parent is required for a valid graph.
Gallery, NuGet, and Chocolatey dependencies accept NuGet ranges. Npm accepts npm semver ranges and rejects NuGet range syntax; npm's own package-lock.json governs its subtree.
Get-Dependency / Invoke-PSDepend honor a neighboring lock automatically. Roots are pinned and transitive packages become Prerequisites so children run first. -IgnoreLock opts out. -Test tests locked root and transitive versions.
Types without Resolve are recorded for drift detection and install as declared.
Review hardening
Validates the complete JSON shape, package references, package names, root resolved keys, and exact versions before consuming a lock. This prevents lock entries from redirecting a root or passing URL/git/file specs to npm as a version.
Fingerprints resolution Source and DependencyScript Parameters; changing either makes the lock stale without writing their values into the lock.
Rejects a lock after every Dependency is removed from its DependencyFile.
Materializes shared transitive packages once per root installation context, so roots with different Targets each receive their children. Duplicate names receive a stable #RootName suffix.
Detects repeated resolver states and reduces the absolute resolution bound; the error now explains that no parent backtracking was attempted.
Keeps Resolve side-effect free: PSGalleryModule no longer bootstraps a package provider during Resolve.
Requires HTTPS when Chocolatey Resolve sends credentials, escapes OData string literals, and passes npm package specs after --.
Excludes prereleases consistently from NuGet/PSGalleryNuget range resolution.
Records the model and tradeoffs in adr/0002-lock-resolution-model.md.
cspell: clean for source, tests, tracked docs, and ADRs.
Known limitations
Install-Module/Save-Module still run PowerShellGet's own dependency handling. Locked children are installed first; Save-Module can additionally save its own picks beside them.
Resolution uses platform filtering. A Windows-only DependencyType is not locked when the update runs on Linux.
Chocolatey/Nuget Resolve requires a NuGet v2 HTTP(S) feed URL; local folders and named sources are not queried. Credentialed Chocolatey feeds must use HTTPS.
Add Update-PSDependLock, which resolves every dependency and its transitive
dependencies to exact versions and writes <name>.lock.json next to the
DependencyFile. One version is locked per DependencyType::Name across the
file, constraints from every parent are intersected (Join-VersionRange), and
conflicts fail the update.
Get-Dependency and Invoke-PSDepend honour an existing lock automatically:
locked dependencies are pinned, locked transitive packages are materialised as
Name@Version dependencies that install first, and a lock that no longer
matches its DependencyFile is an error (-IgnoreLock opts out).
New Resolve PSDependAction on PSGalleryModule, PSResourceGet, PSGalleryNuget,
Nuget, Chocolatey and Npm queries the source without installing. Npm pins only
the declared package; npm's package-lock.json governs its subtree.
Also fix Invoke-DependencyScript ignoring -PSDependTypePath.
Filtering prereleases before matching also removes an explicitly requested exact prerelease such as 2.9.0-beta1, even though the existing install path passes exact versions to NuGet and lock validation accepts semantic prerelease versions. Keep prereleases available for exact requests while continuing to exclude them for latest and range resolution.
Exact prerelease requests are filtered out
PSDepend/PSDependScripts/PSGalleryNuget.ps1:96
Filtering prereleases before matching also removes an explicitly requested exact prerelease such as 2.9.0-beta1, although this handler's install path supports exact versions and the lock format accepts semantic prerelease versions. Keep prereleases available for exact requests while continuing to exclude them for latest and range resolution.
Silently keeping the first duplicate package ID makes the lock depend on nuspec target-framework group order. If Foo has different ranges for net45 and netstandard, the recorded range can be invalid for the machine that consumes the lock, allowing native NuGet resolution to diverge from the locked graph. Select a target framework explicitly, combine compatible duplicate constraints, or reject differing framework-specific ranges instead of discarding them.
NuGet resolution ignores paginated feed results
PSDepend/Private/Find-NugetPackage.ps1:35
The new Resolve implementations treat this branch as a complete version catalogue, but NuGet v2/OData feeds can return server-paged results. A single Invoke-RestMethod request can omit later (including newer) versions, causing the lock to select a lower version or report no match. Follow the feed's next-page links until exhausted before resolving the highest version.
Reuse check mishandles constraints and highest-version resolution
PSDepend/Private/Resolve-PSDependLock.ps1:130
This reuse check is neither syntax-agnostic nor sufficient for highest-version resolution. For npm ranges such as ^1.2.0, Test-VersionInRange treats the range as an exact NuGet-style string; three roots with the same npm range can therefore re-resolve once and then hit the repeated-state error. Conversely, when a NuGet child constraint broadens after its parent is re-resolved, an older selected version still satisfies the new range and is retained even though a higher version is now available. Cache the combined constraint used for the current resolution and reuse only when that constraint is unchanged; otherwise call the DependencyScript again.
Addressed the five findings from the latest Copilot review in d1eb4fc:
exact prerelease versions remain eligible in Nuget and PSGalleryNuget, while latest/ranges still exclude prereleases
conflicting framework-specific NuGet dependency ranges are rejected instead of depending on nuspec group order
NuGet v2 version catalogues are paged to exhaustion
resolver reuse is keyed by the exact combined constraint, so changed/broadened constraints re-resolve to the highest version
identical native constraints are deduplicated before generic NuGet intersection, preserving npm-style syntax
Added focused regression coverage, updated the ADR/changelog, ran the live PowerShell Gallery feed lookup, and passed the full local suite (540 passed, 66 platform-skipped).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds npm-style locks so every machine installs the same resolved versions, including transitive dependencies.
How it works
ResolvePSDependAction. A supporting DependencyScript queries its source and returns one exactPSDepend.ResolvedDependencywithout installing. Implemented forPSGalleryModule,PSResourceGet,PSGalleryNuget,Nuget,Chocolatey, andNpm.Update-PSDependLockresolves one version perDependencyType::Name, intersects constraints from every parent, re-resolves invalidated children, and writes<name>.lock.jsonnext to the DependencyFile.package-lock.jsongoverns its subtree.Get-Dependency/Invoke-PSDependhonor a neighboring lock automatically. Roots are pinned and transitive packages become Prerequisites so children run first.-IgnoreLockopts out.-Testtests locked root and transitive versions.Review hardening
resolvedkeys, and exact versions before consuming a lock. This prevents lock entries from redirecting a root or passing URL/git/file specs to npm as a version.Sourceand DependencyScriptParameters; changing either makes the lock stale without writing their values into the lock.#RootNamesuffix.PSGalleryModuleno longer bootstraps a package provider during Resolve.--.adr/0002-lock-resolution-model.md.Lock format (
lockfileVersion: 1){ "lockfileVersion": 1, "dependencies": { "PowerShellBuild": { "dependencyType": "PSGalleryModule", "name": "PowerShellBuild", "requested": "[0.5.0,0.7.0)", "contextHash": "<sha256>", "resolved": "PSGalleryModule::PowerShellBuild" } }, "packages": { "PSGalleryModule::PowerShellBuild": { "version": "0.6.2", "dependencies": { "psake": "[4.9.0,)" } } } }Format version 1 validates exact versions but does not contain artifact content hashes. Lock changes should be reviewed like code.
Also
Invoke-DependencyScriptignoring-PSDependTypePath.about_PSDepend, generated docs, CHANGELOG, domain vocabulary, and DependencyScript author guidance.Verification
./build.ps1 StageFiles-Test,-WhatIf, and folder recursion all exercised through the public commands.>=1.0.0 <2.0.0confirmed the npm semver command shape.Known limitations
Install-Module/Save-Modulestill run PowerShellGet's own dependency handling. Locked children are installed first;Save-Modulecan additionally save its own picks beside them.