October 9th, 2023

PSResourceGet is generally available

PSResourceGet is Generally Available

Microsoft.PowerShell.PSResourceGet is a continuation of the PowerShellGet 3.0 project. The module under this new name is now generally available on the PowerShell Gallery.

The documentation for PSResourceGet is also live.

How to install the module

To install from PSResourceGet (which is included since PowerShell 7.4 Preview 5)

Install-PSResource -Name Microsoft.PowerShell.PSResourceGet

To install from PowerShellGet 2.2.5

Install-Module -Name Microsoft.PowerShell.PSResourceGet

With this release we have also included an update to the PowerShell Gallery UI to add a tab in the installation options for PSResourceGet.

This module is supported on all supported versions of PowerShell including Windows PowerShell 5.1.

Updates from the release candidate

From the release candidate we addressed high priority low risk bugs, these included:

  • Fix RequiredResource silent failures
  • Fix Artifactory v2 and v3 endpoint failures
  • Fix ADO v2 feed installation failures
  • Automatically set the ApiVersion to v2 for repositories imported from PowerShellGet

What is PSResourceGet/what are the goals

PSResourceGet is a complete re-write of PowerShellGet, the package manager for PowerShell, with the following goals:

  • Create a more intuitive package manager: Make PowerShell resource management more intuitive and easier to use by removing unnecessary prompts when possible.
  • Address top customer issues: Many of the top customer issues in previous versions of the module have been challenging to resolve because of architecture decisions made early on in the development of PowerShellGet.
  • Allow for a smooth transition to a better experience: Transitioning from lower versions of PSResourceGet should be as painless as possible. With the help of our compatibility layer explained in more detail below, our goal is to enable users and scripts built on PowerShellGet 2.0 to move seamlessly to the PSResourceGet engine.
  • Improve maintainability of the codebase: This goal is addressed by removing the provider model that PowerShellGet was originally built on.

This means that PowerShellGet 3.0 does not take a dependency on OneGet, NuGet or any other package provider therefore simplifying the codebase.

Using the lessons learned from previous versions of PowerShellGet, along with a cleaner implementation and interface, we have improved efficiency, performance and quality, allowing us to more quickly address bugs as they arise and iterate on our vNext issues.

Why make a whole new module/why the rename

When we initially introduced the new project we introduced it as PowerShellGet v3, a major update to PowerShellGet. During this time we also introduced a new cmdlet interface (Install-PSResource vs Install-Module), this was done for two main reasons:

  1. To simplify the cmdlet interface
  2. The cmdlets now support more than just modules (scripts, nupkgs etc..)

In addition to this major breaking change, there were other smaller breaking changes to the cmdlet interface made to fix bugs or improve usability.

Given the many breaking changes when we made the decision to ship the new version in PowerShell 7.4, there was concern that we would break folks– especially those using PowerShellGet cmdlets in CI/CD or other automation. Through community collaboration we determined that the best path forward was to start fresh with a new module name, and to introduce PowerShellGet v3 as a compatibility layer to bridge the gap between the old cmdlet interface, and the new engine improvements. For more information on how this decision was made read this blog post. For more information on when to use which module or how to use PowerShellGet with the new engine via compat layer refer to the ‘When to use PowerShellGet v2/v3’ section below.

Shipping in PowerShell

PSResourceGet ships inbox in PowerShell 7.4, side by side with PowerShellGet 2.2.5. We have shipped the last few previews as well as the release candidate for PSResourceGet in 7.4 and this has been a great mechanism for usage and feedback.

We are currently exploring options for shipping PSResourceGet inbox in Windows PowerShell 5.1 if this is an important scenario for you please let us know in this GitHub issue.

New Features (compared to PowerShellGet v2)

In addition to addressing long standing bugs and performance, usability and supportability issues, we also added some new features in PSResourceGet 1.0.0. Some of these features include credential persistence, RequiredResource files, and support for more repositories (including nuget v3 repositories). For more information on supported repositories, refer to the section below.

Credential Persistence

This community contributed feature allows you to provide information about where a credential is stored when registering the PSResourceRepository using a -CredentialInfo parameter. This parameter takes a PSCredentialInfo object which takes a Vault name and Secret name. The secret will then be pulled to authenticate to the Repository on future calls. This feature takes advantage of SecretManagement, for more information on SecretManagement refer the documentation.

Requirements

  • Microsoft.PowerShell.SecretManagement
  • Any vault extension registered (for this example I will use Microsoft.PowerShell.SecretStore)
  • A repository to connect to (for this example I will use Artifactory)

Getting started

For this example I am going to be using SecretStore to store my credentials for an Artifactory repository. This can be repeated with any SecretManagement extension vault, and with any repository. First, I need to make sure I have a SecretManagement vault set up, with my credential stored.

PS C:\Users > Get-SecretInfo
Name          Type         VaultName
----          ----         ---------
jFrogCred     PSCredential SecretStore

Then I can create a PSCredentialInfo object to pass into my PSResourceRepository registration, to create this I pass in the name of the vault and the name of the secret.

$credentialInfo = New-Object Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo ("SecretStore", "jfrogCred")

Now I am ready to register the repository object, I will pass in a friendly name, a URI for the repository, and the CredentialInfo. I also use the -Trusted switch because I will be controlling what gets published to it.

Register-PSResourceRepository -Name artifactory `
-URI " https://<name>.jfrog.io/artifactory/api/nuget/v3/<Repository-Name>
-Trusted `
-CredentialInfo $credentialInfo `

Now I can run Get-PSResourceRepository to see my registered repositories

PS C:\Users > Get-PSResourceRepository

Name        Uri                                                                                     Trusted Priority
----        ---                                                                                     ------- --------
artifactory https://<name>.jfrog.io/artifactory/api/nuget/v3/<Repository-Name>                      True    50      
PSGallery   https://www.powershellgallery.com/api/v2                                                False   50  

If the repository is empty you are going to want to begin by publishing to it. I have saved my API key for publishing to the repository in my SecretStore.

Publish-PSResource -Path .\Get-Hello\ -Repository artifactory -ApiKey (Get-Secret jfrogPublish)

Now I can find and install PSResources from my repository without needing to provide a credential at each call.

PS C:\Users> Find-PSResource -Name Get-Hello -Repository artifactory

Name      Version Prerelease Repository  Description
----      ------- ---------- ----------  -----------
Get-Hello 0.0.2.0            artifactory test module

PS C:\Users> Install-PSResource Get-Hello

Using RequiredResources

Install-PSResource can accept a path to a psd1 or json file (using -RequiredResourceFile), or a hashtable or json (using -RequiredResource).

Getting Started

The -RequiredResource parameter can take either a hashtable or a json format string. The following example shows how to format these inputs.

Install-PSResource -RequiredResource @{
  'Configuration' = @{
    version = '[1.3.1,2.0]'
    repository = 'PSGallery'                        
   }
  'Pester'        = @{
    version = '[4.4.2,4.7.0]'
    repository = 'PSGallery'
    prerelease = $true
  }
}

In this case the modules named “Configuration”, and “Pester” will be installed. The json format will be the same as if this hashtable is passed to ConvertTo-Json:

"{
  'Pester': {
    'allowPrerelease': true,
    'version': '[4.4.2,4.7.0]',
    'repository': 'PSGallery'
  },
  'Configuration': {
    'version': '[1.3.1,2.0]',
    'repository': 'PSGallery'
  }
}"

The older System.Version four part version type will be supported to retain compatibility with existing published modules using that format. Declared dependencies are searched and installed using the same trust algorithm as for Install-PSResource.

The -RequiredResourceFile parameter can accept either a psd1 or a json file. The psd1 should use the same format as the hashtable above, the json file should use the same format as the json sting above.

Supported Repositories

In this release we made an effort to support repositories which previously worked with PowerShellGet as well as add support for new repositories.

  • NuGet.org
  • NuGet.Server feeds
  • Azure Artifacts (v2 and v3)
  • GitHub packages
  • Artifactory (v2 and v3 feeds)
  • MyGet.org
  • File-share-based

For more information on how to get started with these repositories, check out our documentation.

If a repository you use is not on this list, and does not work with your testing please file an issue and let us know. If issues asking for new repository support get enough community support we will consider adding support.

Expect to see new repositories and repository types added to this list in the future.

In order to import your repositories from PowerShellGet run the function Import-PSGetRepository.

Other handy features to know about

  • You can install to a local path by using Save-PSResource with the -IncludeXML parameter. Note that if you do this you will need to import the module manually or add the path to your PSModulePath environment variable so it can be detected by the PowerShell module import system.
  • You can use aliases for Install-PSResource, Find-PSResource, Update-PSResource, Publish-PSResource (‘isres’,’fdres’,’udres’,’pbres’). Get-PSResource’ is also an alias for ‘Get-InstalledPSResource’.
  • There is now prerelease dependency support. Modules can now take dependencies directly on prerelease modules in the psd1. This includes a change in both publish, and install (note this isn’t backwards compatible, in the sense that the change has not been also made to install-module).
  • There is now a -Force parameter to Register-PSResourceRepository cmdlet, to override an existing repositories. This allows you to remove a check from scripts to see if the repository already exists before attempting to register.
  • There are now priorities on repositories so that you can specify a preferred repository that a module will be installed from if a module if found in multiple registered repositories. Valid priority values range from 0 to 100. Lower values have a higher priority ranking. The default value is 50, and can be set at registration or later using the set cmdlet. Repositories are sorted by priority then by name. When searching for resources across multiple repositories, the PSResourceGet cmdlets search the repositories using this sort order.
  • We added a -TrustRepository switch on Install-PSResource if you know the repository is trusted for a particular call and do not want to be prompted without needing to set the entire repository to be trusted.

To explore the full cmdlet interface, and feature set check out the module documentation.

When to use PowerShellGet v2/v3

If you aren’t ready to update all of your scripts to the new cmdlets (that can be a big task), PowerShellGet, and the existing cmdlet interface, is still there for you to use.

In order to bridge the gap between PowerShellGet v2 (the current latest stable PowerShellGet is 2.2.5), and PSResourceGet we introduce a compatibility layer for PSResourceGet and are shipping it as PowerShellGet v3. This module is currently in a preview state and working towards a GA.

In the latest preview of PowerShellGet (3.0.22-beta22), the PowerShellGet syntax is the same, but it is actually a proxy function for PSResourceGet and uses the new engine. This is to allow users to take advantage of some of the bug fixes/performance improvements without needing to update their scripts, or have scripts unexpectedly break at module or PowerShell update time.

Given these three modules the current recommendation would be to use PSResourceGet for new scripts, or if you want to take advantage of new features and use the newest/most supported version of the module. If you are able to use prerelease versions, or are willing to test out PowerShellGet v3 (the compat layer), we really appreciate all testing for this so we can make changes before this reaches GA. Once PowerShellGet v3 reaches GA, this would be the recommended version for old scripts which you may not want to update, but may want to use a more supported module for (in terms of bug fixes from the team), and thereby take advantage of bug fixes/performance updates. Note that PowerShellGet v3 will be focused on backwards compatibility and not adoption of new features (although there may be incidental new features).

Finally, if everything is working totally great for you on PowerShellGet v2 you are free to continue to use it. Nothing has changed about the extent to which it is supported.

In PowerShell 7.5 expect to see PowerShellGet version incremented to a v3 version.

Future plans for PSResourceGet

We plan to continue to release updates to PSResourceGet beginning with a patch release including bug fixes that didn’t quite make the GA timeline and that are found after release. Look out for a feature release in the coming months.

To track progress towards these releases, and see what bugs/features are being worked on use the projects feature in the PSResourceGet repository.

How to give feedback and get support

We cannot overstate how useful user feedback has been in the development of this module.

In order to give feedback or get support please open issues in our GitHub repository.

Special thanks to those who made this release happen

The biggest thanks go to the developers who spent so much time on this module, and took so much care to make it an improved user experience:

  • Amber Erickson
  • Anam Navied
  • Aditya Patwardhan

Thank you to our engineering manager Steve Lee for his support along this whole journey.

Thank you also to both Steven Bucher and Michael Greene for taking over as PM during periods when I had to step away from work over the last four years.

Thank you to Sean Wheeler for his thoughtful testing, and his essential contributions to the module by writing the documentation.

Thank you to every community member who has tested this module over the years, and provided such valuable feedback to shape the design. In particular, a few community members contributions stand out for either contributing code or the sheer quality of issues they have opened, thank you to:

  • @ThomasNieto
  • @FriedrichWeinmann
  • @cansuerdogan
  • @fsackur
  • @hemisphera

This was a community effort– I look forward to seeing the bugs filed and to the next patch release, Sydney

Author

PM on the PowerShell team at Microsoft.

5 comments

Discussion is closed. Login to edit/delete existing comments.

  • Kaido Järvemets

    I tried using the Secret vault etc but I got the following message: Find-PSResource: Temporary folder for installation could not be created or set due to: Object reference not being set to an instance of an object.

  • László Zoltán Nagy

    > Currently this feature only supports the PSCredential secret type, however, we have an issue to track support for other types.
    This points to the old repo where there is no such issue id

      • László Zoltán Nagy

        Microsoft.PowerShell.PowerShellGet.UtilClasses.PSCredentialInfo is also incorrect

      • Niels de Groot

        In addition to the wrong link: the issue has been closed more than a year ago. So why would anyone work on it?
        You’ll need to create a new issue or reopen it, if you want to get something done about it.