A module with helper functions to build and publish PowerShell modules to the PSGallery.
Install-Module PSModuleUtilsFollow The PowerShell Best Practices and Style Guide as much as possible, with the following rules being the most important:
- Use Approved Verbs for commands so that PowerShell's built-in ability to autocomplete un-imported functions works.
- Add help comments to all functions because each module's wiki is auto-generated from them.
Use the following additional guidelines:
- Modules are built with ModuleBuilder via
Build-PSModule. There is no source.psm1: ModuleBuilder concatenates every.ps1under the configured source directories into a single built.psm1. - The manifest template is hand-authored and treated as a source file, not a generated one. By default,
Build-PSModulederives the module name from the manifest filename and uses itsModuleVersionandPrereleasevalues. Use-Versiononly for an explicit build override. ModuleBuilder updatesFunctionsToExportandAliasesToExport, while PSModuleUtils stamps git-derived fields (Author,CompanyName,Copyright,ProjectUri,ReleaseNotes). Everything else you author (GUID,Description,RequiredModules,PrivateData.PSData.Tags, etc.) is preserved as-is. Pre-declarePrivateData.PSData.PrereleaseandPrivateData.PSData.ReleaseNotesin the template (empty strings are fine). RunNew-PSModuleManifestto scaffold or migrate a compatible template. - Ideally, each module and each of its functions should have a set of Pester unit/integration tests. At the least, any new functions or functionality should have an associated test.
- Create all functions as single
.ps1files with the same name and withoutExport-ModuleMemberstatements.- The files should be in an appropriate nested
Publicfolder that corresponds to its API category. - Functions that are used by other functions should be put in either
UtilsorPrivate, depending on their usage.
- The files should be in an appropriate nested
- Tests must live in a top-level
tests/folder, never insidePublic/Private. ModuleBuilder inlines every.ps1it finds in those folders with no exclusion, so a co-located*.Tests.ps1leaksDescribe/Itblocks into the built module and its exports. - Keep packaged assets outside the configured source directories.
Build-PSModulecopies every other source-root item automatically, preserving directories such asAssemblies,bin,Settings,Schemas,Templates,Resources, and culture names such asen-US. Use-CopyPathsonly for additional files or directories outside that automatic set. - Declare files that PowerShell loads as part of module import in the manifest. Use
RequiredAssembliesfor prerequisite DLLs,FormatsToProcessfor formatting files, andTypesToProcessfor type extensions. UseFileListonly as package inventory. Other runtime assets can be resolved relative to$PSScriptRoot; seeGet-PSModuleAnalyzerSettingsPathfor handling source and built layouts.
The folder structure should be maintained like the example below:
\MODULEREPODIRECTORY
├───.github
│ └───workflows
├───.gitignore
├───LICENSE
├───README.md
├───build.ps1
│
├───src
│ ├───ModuleName.psd1
│ │
│ ├───Public
│ │ └───functionalArea
│ │ └───Verb-Noun.ps1
│ │
│ ├───Private
│ │ └───Verb-Noun.ps1
│ │
│ ├───Assemblies
│ │ └───Dependency.dll
│ │
│ └───Resources
│ └───Template.json
│
└───tests
├───ModuleName.Module.Tests.ps1
└───Verb-Noun.Tests.ps1