Training
Module
Publish reusable Bicep code by using GitHub Actions - Training
Build GitHub Actions deployment workflows for template specs and Bicep modules. Lint your Bicep code, apply versioning, and publish it to Azure or to a Bicep registry.
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
This article describes recommended steps used by Microsoft teams to ensure the packages published to the PowerShell Gallery will be widely adopted and provide high value to users, based on how the PowerShell Gallery handles manifest data and on feedback from large numbers of PowerShell Gallery users. Packages that are published following these guidelines will be more likely to be installed, trusted, and attract more users.
Included below are guidelines for what makes a good PowerShell Gallery package, what optional Manifest settings are most important, improving your code with feedback from initial reviewers and Powershell Script Analyzer, versioning your module, documentation, tests and examples for how to use what you have shared. Much of this documentation follows the guidelines for publishing High Quality DSC Resource Modules.
For the mechanics of publishing a package to the PowerShell Gallery, see Creating and Publishing a Package.
Feedback on these guidelines is welcomed. If you do have feedback, please open issues in our GitHub documentation repository.
The following best practices are what the users of PowerShell Gallery items say is important, and are listed in nominal priority order. Packages that follow these guidelines are far more likely to be downloaded and adopted by others.
Each of these is covered briefly in the sections below.
PSScriptAnalyzer is a free static code analysis tool that works on PowerShell code. PSScriptAnalyzer will identify the most common issues seen in PowerShell code, and often a recommendation for how to fix the issue. The tool is easy to use, and categorizes the issues as Errors (severe, must be addressed), Warning (need to be reviewed and should be addressed), and Information (worth checking out for best practices). All packages published to the PowerShell Gallery will be scanned using PSScriptAnalyzer, and any errors will be reported back to the owner and must be addressed.
The best practice is to run Invoke-ScriptAnalyzer
with -Recurse
and -Severity
Warning.
Review the results, and ensure that:
Users who download packages from the PowerShell Gallery are strongly encouraged to run PSScriptAnalyzer and evaluate all Errors and Warnings. Users are very likely to contact package owners if they see that there's an error reported by PSScriptAnalyzer. If there's a compelling reason for your package to keep code that is flagged as an error, add that information to your documentation to avoid having to answer the same question many times.
Documentation and examples are the best way to ensure users can take advantage of any shared code.
Documentation is the most helpful thing to include in packages published to the PowerShell Gallery. Users will generally bypass packages without documentation, as the alternative is to read the code to understand what the package is and how to use it. There are several articles available about how to provide documentation with PowerShell packages, including:
Examples show users how the package is intended to be used. Many developers will say that they look at examples before documentation to understand how to use something. The best types of examples show basic use, plus a simulated realistic use case, and the code is well-commented. Examples for modules published to the PowerShell Gallery should be in an Examples folder under the module root.
A good pattern for examples can be found in the PSDscResource module
under the Examples\RegistryResource
folder. There are four sample use cases with a brief
description at the top of each file that documents what is being demonstrated.
It's important to specify modules that your module is dependent on in the Module Manifest. This allows the end user to not have to worry about installing the proper versions of modules that yours take a dependency on. To specify dependent modules, you should use the required module field in the module manifest. This will load any listed modules into the global environment prior to importing your module unless they've already been loaded. For example, some modules may already be loaded by a different module. It's also possible to specify a specific version to load using the RequiredVersion field rather than the ModuleVersion field. When using ModuleVersion, it will load the newest version available with a minimum of the version specified. When not using the RequiredVersion field, to specify a specific version it's important to monitor version updates to the required module. It's especially important to be aware of any breaking changes that could affect the user experience with your module.
Example: RequiredModules = @(@{ModuleName="myDependentModule"; ModuleVersion="2.0"; Guid="cfc45206-1e49-459d-a8ad-5b571ef94857"})
Example: RequiredModules = @(@{ModuleName="myDependentModule"; RequiredVersion="1.5"; Guid="cfc45206-1e49-459d-a8ad-5b571ef94857"})
Package owners who respond properly to feedback are highly valued by the community. Users who provide constructive feedback are important to respond to, as they're interested enough in the package to try to help improve it.
There is one feedback method available in the PowerShell Gallery:
Owners who respond to feedback constructively are appreciated by the community. Use the opportunity in the report to request more information. If needed, provide a workaround, or identify if an update fixes a problem.
If there's inappropriate behavior observed from either of these communication channels, use the Report Abuse feature of the PowerShell Gallery to contact the Gallery Administrators.
Sharing a script with other users is great, and provides others with examples of how to solve problems they may have. The issue is that scripts in the PowerShell Gallery are single files without separate documentation, examples, and tests.
PowerShell Modules have a folder structure that allows multiple folders and files to be included with the package. The module structure enables including the other packages we list as best practices: cmdlet help, documentation, examples, and tests. The biggest disadvantage is that a script inside a module must be exposed and used as a function. For information on how to create a module, see Writing a Windows PowerShell Module.
There are situations where a script provides a better experience for the user, particularly with DSC
configurations. The best practice for DSC configurations is to publish the configuration as a script
with an accompanying module that contains the docs, examples, and tests. The script lists the
accompanying module using RequiredModules = @(Name of the Module)
. This approach can be used with
any script.
Standalone scripts that follow the other best practices provide real value to other users. Providing comment-based documentation and a link to a Project Site are highly recommended when publishing a script to the PowerShell Gallery.
A Project Site is where a publisher can interact directly with the users of their PowerShell Gallery packages. Users prefer packages that provide this, as it allows them to get information about the package more easily. Many packages in the PowerShell Gallery are developed in GitHub, others are provided by organizations with a dedicated web presence. Each of these can be considered a project site.
Adding a link is done by including ProjectURI in the PSData section of the manifest as follows:
# A URL to the main website for this project.
ProjectUri = 'https://github.com/powershell/powershell'
When a ProjectURI is provided, the PowerShell Gallery will include a link to the Project Site on the left side of the package page.
Use the following tags to demonstrate to users which packages will work well with their environment:
By tagging your package with the compatible platform(s) it will be included in the Gallery search
filters on the left pane of the search results. If you host your package on GitHub, when you tag
your package, you can also take advantage of our
PowerShell Gallery compatibility shields
.
Including tests with open-source code is important to users, as it gives them assurance about what you validate, and provides information on how your code works. It also allows users to ensure they don't break your original functionality if they modify your code to fit their environment.
It's strongly recommended that tests be written to take advantage of the Pester test framework, which has been designed specifically for PowerShell. Pester is available in GitHub, the PowerShell Gallery, and ships in Windows 10, Windows Server 2016, WMF 5.0 and WMF 5.1.
The Pester project site in GitHub includes good documentation on writing Pester tests, from getting started to best practices.
The targets for test coverage are called out in the High Quality Resource Module documentation, with 70% unit test code coverage recommended.
All packages published to the PowerShell Gallery must specify the license terms, or be bound by the license included in the Terms of Use under Exhibit A. The best approach to specifying a different license is to provide a link to the license using the LicenseURI in PSData. For more information, see Packages manifest and Gallery UI.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
Tags = @('.net','acl','active-directory')
# A URL to the license for this module.
LicenseUri = 'http://www.apache.org/licenses/LICENSE-2.0'
Code signing provides users with the highest level of assurance for who published the package, and that the copy of the code they acquire is exactly what the publisher released. To learn more about code signing generally, see Introduction to Code Signing. PowerShell supports validation of code signing through two primary approaches:
Signing PowerShell files is a well-established approach to ensuring that the code being executed was
produced by a reliable source, and hasn't been modified. Details on how to sign PowerShell script
files is covered in the
About Signing article. In
overview, a signature can be added to any .PS1
file that PowerShell validates when the script is
loaded. PowerShell can be constrained using the
Execution Policy
cmdlets to ensure use of signed scripts.
Catalog signing modules is a feature added to PowerShell in version 5.1. How to sign a module is covered in the Catalog Cmdlets article. In overview, catalog signing is done by creating a catalog file, which contains a hash value for every file in the module, and then signing that file.
The PowerShellGet Publish-Module
, Install-Module
, and Update-Module
cmdlets will check the
signature to ensure it's valid, then confirm that the hash value for each package matches what is in
the catalog. Save-Module
doesn't validate a signature. If a previous version of the module is
installed on the system, Install-Module
will confirm that the signing authority for the new
version matches what was previously installed. Install-Module
and Update-Module
will use the
signature on a .PSD1
file if the package isn't catalog signed. Catalog signing works with, but
doesn't replace signing script files. PowerShell doesn't validate catalog signatures at module load
time.
SemVer is a public convention that describes how to structure and change a version to allow easy interpretation of changes. The version for your package must be included in the manifest data.
0.1.1
or
4.11.192
.0
indicate that the package isn't yet production ready, and the first
number should only begin with 0
if that's the only number used.1.9.9999
to 2.0.0
) indicate major and breaking changes between
the versions.1.1
to 1.2
) indicate feature-level changes, such as adding new
cmdlets to a module.1.01.0
will be treated
as greater than 1.001.0
.PowerShell was created before SemVer was published, so it provides support for most but not all elements of SemVer, specifically:
1.0.0
. This will
be supported in a future release of the PowerShell Gallery and PowerShellGet cmdlets.5.1.14393.1066
). From a versioning
standpoint, these differences are ignored.The PowerShell Gallery isn't designed to be a target for testing the publishing process. The best way to test out the end-to-end process of publishing to the PowerShell Gallery is to set up and use your own local repository. This can be done in a few ways, including:
With any of these solutions, use Register-PSRepository
to define a new repository, which you
use in the -Repository
parameter for Publish-Module
.
One additional point about test publishing: any package you publish to the PowerShell Gallery can't be deleted without help from the operations team, who will confirm that nothing is dependent upon the package you wish to publish. For that reason, we don't support the PowerShell Gallery as a testing target, and will contact any publisher who does so.
It's strongly recommended that publishers use the Publish-Module
and Publish-Script
cmdlets when
working with the PowerShell Gallery. PowerShellGet was created to help you avoid remembering
important details about installing from and publishing to the PowerShell Gallery. On occasion,
publishers have chosen to skip PowerShellGet and use the NuGet client, or
PackageManagement cmdlets, instead of Publish-Module
. There are a number of details that are
easily missed, which results in a variety of support requests.
If there's a reason that you can't use Publish-Module
or Publish-Script
, please let us know.
File an issue in the PowerShellGet GitHub repo, and provide the details that cause you to choose
NuGet or PackageManagement.
The most successful approach we have found for packages published to the PowerShell Gallery is this:
1.0.0
version
to the PowerShell Gallery.PowerShell Gallery feedback
PowerShell Gallery is an open source project. Select a link to provide feedback:
Training
Module
Publish reusable Bicep code by using GitHub Actions - Training
Build GitHub Actions deployment workflows for template specs and Bicep modules. Lint your Bicep code, apply versioning, and publish it to Azure or to a Bicep registry.