PowerShell / PSResourceGet

PSResourceGet is the package manager for PowerShell
https://www.powershellgallery.com/packages/Microsoft.PowerShell.PSResourceGet
MIT License
483 stars 92 forks source link

`Install-PSResource`: Install wrong prerelease when passing `-Version` (range) together with `-Prerelease` #1678

Closed johlju closed 1 week ago

johlju commented 1 month ago

Prerequisites

Steps to reproduce

This must be reproduced using a module's major version where it also exist a higher major version with a prerelease. This command wrongly installs a 5.0 version of a module. Since we are excluding 5.0 with the version range, a prerelease of 5.0 I'm expecting should also be excluded.

Install-PSResource -Name 'Pester' -Version '[4.0,5.0)' -Prerelease

Expected behavior

PS> Install-PSResource -Name 'Pester' -Version '[4.0,5.0)' -Prerelease -PassThru

Name   Version Prerelease Repository Description
----   ------- ---------- ---------- -----------
Pester 4.10.2  beta1      PSGallery  Pester provides a framework for running BDD style Tests ...

Actual behavior

PS> Install-PSResource -Name 'Pester' -Version '[4.0,5.0)' -Prerelease -PassThru

Name   Version Prerelease Repository Description
----   ------- ---------- ---------- -----------
Pester 5.0.0   rc9        PSGallery  Pester provides a framework for running BDD style Tests ...

Error details

# No error

Environment data

ModuleType Version    PreRelease Name                                ExportedCommands
---------- -------    ---------- ----                                ----------------
Binary     1.0.5                 Microsoft.PowerShell.PSResourceGet  {Find-PSResource, Get-InstalledPSResource, Get-PSResourceRepository, Get-PSScri…

Name                           Value
----                           -----
PSVersion                      7.4.3
PSEdition                      Core
GitCommitId                    7.4.3
OS                             Microsoft Windows 10.0.22631
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

o-l-a-v commented 1 month ago

What version of PSResourceGet did you use? I can't reproduce with PSResourceGet v1.0.5.

Find-PSResource ```powershell PS > Find-PSResource -Repository 'PSGallery' -Name 'Pester' -Version '[4.0,5.0)' -Debug DEBUG: In FindPSResource::ProcessResourceNameParameterSet() DEBUG: Filtering package name(s) on wildcards DEBUG: Parsing package version DEBUG: In FindHelper::FindByResourceName() DEBUG: Parameters passed in >>> Name: 'Pester'; ResourceType: 'None'; VersionRange: '[4.0,5.0)'; NuGetVersion: ''; VersionType: 'VersionRange'; Version: '[4.0,5.0)'; Prerelease: 'False'; Tag: ''; Repository: 'PSGallery'; IncludeDependencies 'False' DEBUG: Searching through repository 'PSGallery' DEBUG: In FindHelper::SearchByNames() DEBUG: Version range and package name are specified DEBUG: In V2ServerAPICalls::FindVersionGlobbing() DEBUG: In V2ServerAPICalls::FindVersionGlobbing() DEBUG: In V2ServerAPICalls::HttpRequestCall() DEBUG: Request url is 'https://www.powershellgallery.com/api/v2/FindPackagesById()?$filter=NormalizedVersion+ge+%274.0.0%27+and+NormalizedVersion+lt+%275.0.0%27+and+IsPrerelease+eq+false+and+Id+eq+%27Pester%27&$inlinecount=allpages&$skip=0&$orderby=NormalizedVersion+desc&id=%27Pester%27' DEBUG: Found package 'Pester' version '4.9.0' DEBUG: Package 'Pester' returned from server DEBUG: Package 'Pester' was previously discovered and returned DEBUG: Found package 'Pester' version '4.8.1' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.8.0' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.7.3' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.7.2' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.7.1' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.7.0' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.6.0' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.5.0' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.4.4' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.4.3' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.4.2' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.4.1' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.4.0' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.3.1' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.2.0' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.10.1' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.10.0' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.1.1' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.1.0' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.0.8' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.0.7' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.0.6' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.0.5' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.0.4' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.0.3' DEBUG: Package 'Pester' returned from server DEBUG: Found package 'Pester' version '4.0.2' DEBUG: Package 'Pester' returned from server Name Version Prerelease Repository Description ---- ------- ---------- ---------- ----------- Pester 4.9.0 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.8.1 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.8.0 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.7.3 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.7.2 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.7.1 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.7.0 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.6.0 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.5.0 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.4.4 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.4.3 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.4.2 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.4.1 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.4.0 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.3.1 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.2.0 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.10.1 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.10.0 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.1.1 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.1.0 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.0.8 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.0.7 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.0.6 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.0.5 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.0.4 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.0.3 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… Pester 4.0.2 PSGallery Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerf… PS > ```
Save-PSResource ```powershell PS > $DebugPreference = 'Continue'; Save-PSResource -Repository 'PSGallery' -TrustRepository -Name 'Pester' -Version '[4.0,5.0)' -Path 'C:\Users\olavb\Desktop\Testin' DEBUG: In SavePSResource::ProcessSaveHelper() DEBUG: In InstallHelper::BeginInstallPackages() DEBUG: Parameters passed in >>> Name: 'Pester'; VersionRange: '[4.0,5.0)'; NuGetVersion: ''; VersionType: 'VersionRange'; Version: '[4.0,5.0)'; Prerelease: 'False'; Repository: 'PSGallery'; AcceptLicense: 'True'; Quiet: 'False'; Reinstall: 'True'; TrustRepository: 'True'; NoClobber: 'False'; AsNupkg: 'False'; IncludeXml 'False'; SavePackage 'True'; TemporaryPath ''; SkipDependencyCheck: 'False'; AuthenticodeCheck: 'False'; PathsToInstallPkg: 'C:\Users\olavb\Desktop\Testin'; Scope '' DEBUG: In InstallHelper::ProcessRepositories() DEBUG: In InstallHelper::InstallPackages() DEBUG: In InstallHelper::InstallPackage() DEBUG: In V2ServerAPICalls::FindVersionGlobbing() DEBUG: In V2ServerAPICalls::FindVersionGlobbing() DEBUG: In V2ServerAPICalls::HttpRequestCall() DEBUG: Request url is 'https://www.powershellgallery.com/api/v2/FindPackagesById()?$filter=NormalizedVersion+ge+%274.0.0%27+and+NormalizedVersion+lt+%275.0.0%27+and+IsPrerelease+eq+false+and+Id+eq+%27Pester%27&$inlinecount=allpages&$skip=0&$orderby=NormalizedVersion+desc&id=%27Pester%27' DEBUG: In V2ServerAPICalls::InstallVersion() DEBUG: In V2ServerAPICalls::HttpRequestCallForContent() DEBUG: Request url is 'https://www.powershellgallery.com/api/v2/package/Pester/4.9.0' DEBUG: In InstallHelper::TryInstallToTempPath() DEBUG: In InstallHelper::DeleteExtraneousFiles() DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\5e1fb9dd-f02b-4b91-baf6-87c6f7a29fb8\pester\4.9.0\Pester.nuspec' DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\5e1fb9dd-f02b-4b91-baf6-87c6f7a29fb8\pester\4.9.0\[Content_Types].xml' DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\5e1fb9dd-f02b-4b91-baf6-87c6f7a29fb8\pester\4.9.0\_rels' DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\5e1fb9dd-f02b-4b91-baf6-87c6f7a29fb8\pester\4.9.0\package' DEBUG: In InstallHelper::TryMoveInstallContent() DEBUG: In InstallHelper::MoveFilesIntoInstallPath() PS > ```
image
johlju commented 1 month ago

Used 1.0.5. Are trying to reproduce using Install-PSResource with the parameter -Prerelease?

o-l-a-v commented 1 month ago

Ah, sorry, I forgot to test with -Prerelease. 🤦‍♂️ I'm AFK for a few days so can't test again right now.

The API seems to work / give expected results with IsPrerelease eq true:

Edit: But -Prerelease only includes prerelease versions in the search results ( https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.psresourceget/save-psresource?view=powershellget-3.x#-prerelease ), latest versions aren't necessarily a prerelease, got it.

johlju commented 1 month ago

latest versions isn't necessarily a prerelease, got it.

It shouldn't even return a prerelease of 5.0. 🤔

In the refactor example in the issue description it is not excluding the 5.0 prerelease versions, we are saying with the range [4.0,5.0) to include a "version 4.0 or greater but a version less than 5.0", the later should also exclude 5.0 prereleases as well. 🤔 Install-PSResource returns the latest prerelease prior to the full release 5.0, so the bug must be that exclusion ranges does not handle prereleases correctly (and yes, it should also return the latest full release, that is less than 5.0, if such is the highest version in the range).

o-l-a-v commented 1 month ago

So Find-PSResource -Repository 'PSGallery' -Prerelease -Name 'Pester' -Version '[4.0,5.0)' -Debug actually gives url:

Notice NormalizedVersion lt '5.0.9'. Strange.

Edit: Which might be expected, as [semver]('5.0.0-rc2') -lt [semver]('5.0.0') is $true.

PS > [semver[]]('5.0.0','5.0.0-rc2','4.9.9') | Where-Object -FilterScript {$_ -lt [semver]('5.0.0')}

Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
5      0      0      rc2
4      9      9

PS >

To get 5.0.0 prereleases one must probably ask the NuGet v2 API for versions newer than 5.0.0, then filter out results that are not prereleases afterwards? Seems to be what PSResourceGet is doing, you get more results querying the API directly:

PS > (
    Invoke-RestMethod -Method 'Get' -Uri (
        'https://www.powershellgallery.com/api/v2/FindPackagesById()?$filter=NormalizedVersion+ge+%274.0.0%27+and+NormalizedVersion+lt+%275.0.9%27+and+Id+eq+%27Pester%27&$inlinecount=allpages&$skip=0&$orderby=NormalizedVersion+desc&id=%27Pester%27'
    )
).properties | Select-Object -Property (
    'Id',
    @{'Name'='Version';'Expression'={[semver]$_.'version'}},
    @{'Name'='NormalizedVersion';'Expression'={[semver]$_.'normalizedVersion'}},
    @{'Name'='IsPrerelease';'Expression'={[bool]::Parse($_.'isPrerelease'.'#text')}},
    @{'Name'='IsLatestVersion';'Expression'={[bool]::Parse($_.'isLatestVersion'.'#text')}},
    @{'Name'='IsAbsoluteLatestVersion';'Expression'={[bool]::Parse($_.'isAbsoluteLatestVersion'.'#text')}}
) | Sort-Object -Property 'Version' -Descending | Format-Table -AutoSize

Id     Version      NormalizedVersion IsPrerelease IsLatestVersion IsAbsoluteLatestVersion
--     -------      ----------------- ------------ --------------- -----------------------
Pester 5.0.5-beta1  5.0.5-beta1               True           False                   False
Pester 5.0.4        5.0.4                    False           False                   False
Pester 5.0.4-beta1  5.0.4-beta1               True           False                   False
Pester 5.0.3        5.0.3                    False           False                   False
Pester 5.0.2        5.0.2                    False           False                   False
Pester 5.0.1        5.0.1                    False           False                   False
Pester 5.0.0        5.0.0                    False           False                   False
Pester 5.0.0-rc9    5.0.0-rc9                 True           False                   False
Pester 5.0.0-rc8    5.0.0-rc8                 True           False                   False
Pester 5.0.0-rc7    5.0.0-rc7                 True           False                   False
Pester 5.0.0-rc6    5.0.0-rc6                 True           False                   False
Pester 5.0.0-rc5    5.0.0-rc5                 True           False                   False
Pester 5.0.0-rc4    5.0.0-rc4                 True           False                   False
Pester 5.0.0-rc3    5.0.0-rc3                 True           False                   False
Pester 5.0.0-rc2    5.0.0-rc2                 True           False                   False
Pester 5.0.0-rc1    5.0.0-rc1                 True           False                   False
Pester 5.0.0-beta   5.0.0-beta                True           False                   False
Pester 5.0.0-alpha4 5.0.0-alpha4              True           False                   False
Pester 5.0.0-alpha3 5.0.0-alpha3              True           False                   False
Pester 4.10.2-beta1 4.10.2-beta1              True           False                   False
Pester 4.10.1       4.10.1                   False           False                   False
Pester 4.10.0       4.10.0                   False           False                   False
Pester 4.9.0        4.9.0                    False           False                   False
Pester 4.8.1        4.8.1                    False           False                   False
Pester 4.8.0        4.8.0                    False           False                   False
Pester 4.7.3        4.7.3                    False           False                   False
Pester 4.7.2        4.7.2                    False           False                   False
Pester 4.7.1        4.7.1                    False           False                   False
Pester 4.7.0        4.7.0                    False           False                   False
Pester 4.7.0-beta1  4.7.0-beta1               True           False                   False
Pester 4.6.0        4.6.0                    False           False                   False
Pester 4.5.0        4.5.0                    False           False                   False
Pester 4.5.0-beta2  4.5.0-beta2               True           False                   False
Pester 4.5.0-beta1  4.5.0-beta1               True           False                   False
Pester 4.4.4        4.4.4                    False           False                   False
Pester 4.4.3        4.4.3                    False           False                   False
Pester 4.4.3-beta1  4.4.3-beta1               True           False                   False
Pester 4.4.2        4.4.2                    False           False                   False
Pester 4.4.1        4.4.1                    False           False                   False
Pester 4.4.0        4.4.0                    False           False                   False
Pester 4.4.0-beta2  4.4.0-beta2               True           False                   False
Pester 4.4.0-beta   4.4.0-beta                True           False                   False
Pester 4.3.1        4.3.1                    False           False                   False
Pester 4.3.0        4.3.0                    False           False                   False
Pester 4.2.0        4.2.0                    False           False                   False
Pester 4.2.0-alpha3 4.2.0-alpha3              True           False                   False
Pester 4.2.0-alpha2 4.2.0-alpha2              True           False                   False
Pester 4.2.0-alpha1 4.2.0-alpha1              True           False                   False
Pester 4.1.1        4.1.1                    False           False                   False
Pester 4.1.0        4.1.0                    False           False                   False
Pester 4.0.8        4.0.8                    False           False                   False
Pester 4.0.7        4.0.7                    False           False                   False
Pester 4.0.6        4.0.6                    False           False                   False
Pester 4.0.5        4.0.5                    False           False                   False
Pester 4.0.4        4.0.4                    False           False                   False
Pester 4.0.3        4.0.3                    False           False                   False
Pester 4.0.2        4.0.2                    False           False                   False
Pester 4.0.1        4.0.1                    False           False                   False
Pester 4.0.0        4.0.0                    False           False                   False

PS >

So my thinking right now is that this works as expected. 🤔

johlju commented 1 month ago

In my opinion if I ask for a nuget range [4.0,5.0) where 5.0 should not be included at all, then the prereleases in 5.0 should not be included either. Because a prereleases of 5.0 have the (breaking) changes that resulted in the bumping of major release which one want to avoid with that nuget range.

o-l-a-v commented 1 month ago

While I agree on your logic, that is not how versioning in dotnet and PowerShell seem to work (ref [semver]('5.0.0-rc2') -lt [semver]('5.0.0') is True), so you'll probably have to implement your own logic to get the latest v4 version. Example with PowerShell v7.4.4 which have [semver] built in, which 5.1 does not:

PS > Find-PSResource -Repository 'PSGallery' -Prerelease -Name 'Pester' -Version '[4.0,5.0)' |
Where-Object -Property 'Version' -Like '4.*' |
Sort-Object -Property @{'Expression'={[semver]$_.'AdditionalMetadata'.'NormalizedVersion'}} -Descending |
Select-Object -First 1 |
Format-List

AdditionalMetadata       : {[NormalizedVersion, 4.10.2-beta1]}
Author                   : Pester Team
CompanyName              : Pester
Copyright                : Copyright (c) 2019 by Pester Team, licensed under Apache 2.0 License.
Dependencies             : {}
Description              : Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell and offers a powerful set of M
                           ocking Functions that allow tests to mimic and mock the functionality of any command inside of a piece of PowerShell code being tested. Pester tests ca
                           n execute any command or script that is accessible to a pester test file. This can include functions, Cmdlets, Modules and scripts. Pester can be run i
                           n ad hoc style in a console or it can be integrated into the Build scripts of a Continuous Integration system.
IconUri                  : https://raw.githubusercontent.com/pester/Pester/master/images/pester.PNG
Includes                 : Microsoft.PowerShell.PSResourceGet.UtilClasses.ResourceIncludes
InstalledDate            :
InstalledLocation        :
IsPrerelease             : True
LicenseUri               : https://www.apache.org/licenses/LICENSE-2.0.html
Name                     : Pester
Prerelease               : beta1
ProjectUri               : https://github.com/Pester/Pester
PublishedDate            : 29.05.2021 12:32:18
ReleaseNotes             : https://github.com/pester/Pester/releases/tag/4.10.2-beta1
Repository               : PSGallery
RepositorySourceLocation : https://www.powershellgallery.com/api/v2
Tags                     : {powershell, unit_testing, bdd, tdd…}
Type                     : Module
UpdatedDate              :
Version                  : 4.10.2

PS >

Or do a version range "hack" like:

Find-PSResource -Repository 'PSGallery' -Prerelease -Name 'Pester' -Version '[4.0,4.999999)'

These are just my thoughts as a user, let's see if the maintainers of this repo has something to say about it.

SydneyhSmith commented 1 week ago

Thanks for the comments and feedback-- we use the nuget versioning api which considers a 5 preview to be less than 5.0