Quickly making high quality PowerShell modules using Sampler


Have you ever spent time looking for the best way to set up your new PowerShell module?
Setting up proper folder structures, best way to load your functions, writing Pester tests and build pipelines.
Trying to follow all best practices can take a long time before you actually write your first line of actual code…

That’s where Sampler comes in handy!

Sampler is a PowerShell module created by Gael Colas that generates complete module templates.
Sampler helps scaffolding your module which, in development terms, means automatically creating the basic structure and files you need for a project - like having someone build the frame of a house so you can focus on the interior design instead of laying the foundation.

Sampler provides:

  • Module structure - Proper folder layouts following PowerShell best practices
  • Pester tests - Pre-configured unit tests to ensure your module quality
  • Build automation - Build scripts that help you get all the dependencies required for your module as well as updating the module manifests
  • CI/CD templates - Azure Pipelines or GitHub Actions templates for testing, building, and publishing your module
  • Multiple module types - Different templates for different needs

The beauty of Sampler is that it handles all the boring setup work, so you can jump straight into writing the functions that solve your problems.

First, let’s install Sampler from the PowerShell Gallery:

1
Install-Module -Name Sampler -Repository PSGallery -Scope CurrentUser

The simplest way to get started is using the SimpleModule template, which I personally use for most of my development work. This template gives you everything you need without overwhelming complexity:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Create a new module called "MyAwesomeModule"
$newSampleModuleParameters = @{
    DestinationPath   = 'C:\Demo\'
    ModuleType        = 'SimpleModule'
    ModuleName        = 'MyAwesomeModule'
    ModuleAuthor      = 'Robert Prüst'
    ModuleDescription = 'This module is Awesome!'
}

New-SampleModule @newSampleModuleParameters

And it will then ask you a few details concerning the module you want to make and will then create the entire structure:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Will you use Git for source control?
[Y] Yes  [N] No  [?] Help (default is "N"): y
Name of your default branch (y): main
Do you want to add configuration for GitVersion to handle automatic versioning for your project?
[Y] Yes  [N] No  [?] Help (default is "Y"): y
Do you want to use the service CodeCov.io for code coverage reporting?
[Y] Yes  [N] No  [?] Help (default is "N"): n
Will you use GitHub.com as the collaboration platform for the project?
[Y] Yes  [N] No  [?] Help (default is "N"): n
Do you want to use Azure Pipelines to run the the build, test and or deploy pipeline?
[Y] Yes  [N] No  [?] Help (default is "N"): y
Will you use Visual Studio Code as the code editor for the project?
[Y] Yes  [N] No  [?] Help (default is "N"): y

Let me break down what this command does:

  • ModuleName - What you want to call your module
  • DestinationPath - Where you want your new module folder created.
    It will automatically create a subfolder with the new module’s name in which all files/folders will be placed
  • ModuleType - The template to use (SimpleModule is perfect for most cases)
  • Source Control - In case you will use git, it will provide default .gitignore and .gitattributes files.
    You can read more about what those files do here (.gitignore) and here (.gitattributes).
  • Default branch Name - Will add this information in the GitVersion.yml and azure-pipelines.yml files to trigger on
  • GitVersion - This will add GitVersion to your module, allowing for automated version bumping (raising the version number) based on things such as commit messages
  • CodeCov.io - This is a service that you can use to easily show Code Coverage statistics for your module (in case you want to show how much of your code is tested)
  • GitHub collaboration - In case you want to use GitHub including GitHub Actions, it will create the required folders for this
  • Azure Pipelines - It will create the azure-pipelines.yml file for you which you can immediately use in your Azure Pipelines
  • Visual Studio Code as Editor - this will create the .vscode folder with a tasks.json file for extra configuration.
    You can read more about what this file can do for you if interested here

Now this looks like a lot and it is!
Just think about all the time you saved not configuring all this manually.

Based on the configuration above, you should end up with a folder structure like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
MyAwesomeModule/
├── .vscode/              # VS Code configuration
   └── tasks.json
├── output/               # Compiled module output
   └── RequiredModules/
├── source/
   ├── en-US/            # Help documentation
      └── about_MyAwesomeModule.help.txt
   ├── Private/          # Internal helper functions
      └── Get-PrivateFunction.ps1
   ├── Public/           # Your public functions go here
      └── Get-Something.ps1
   ├── MyAwesomeModule.psd1  # Module manifest (metadata)
   └── MyAwesomeModule.psm1  # Module script file (main code)
├── tests/
   ├── QA/               # Quality assurance tests
      └── module.tests.ps1
   └── Unit/             # Unit tests for your functions
       ├── Private/
          └── Get-PrivateFunction.tests.ps1
       └── Public/
           └── Get-Something.tests.ps1
├── azure-pipelines.yml   # CI/CD pipeline configuration
├── build.ps1            # Build script
├── build.yaml           # Build configuration
├── CHANGELOG.md         # Change log
├── GitVersion.yml       # Version management
├── README.md            # Documentation
├── RequiredModules.psd1  # Module dependencies
├── Resolve-Dependency.ps1 # Dependency resolver
└── Resolve-Dependency.psd1 # Dependency configuration

This structure follows PowerShell community best practices and gives you everything you need to start building professional modules.

A quick note about the key module files:

  • PSD1 file - This is your module manifest, like an “ID card” for your module. It contains metadata such as the module name, version, what functions it exports, and dependencies it needs.
  • PSM1 file - This contains the actual code that makes your module work. In Sampler’s structure, this file typically just loads all your functions from the Public and Private folders.

Now that you’ve scaffolded your first module, all files, folders, build functions and tests created, what do I to ‘use’ it?

The first thing you’ll want to do is resolve all the dependencies your module needs. Sampler includes a build script that handles this for you:

1
2
3
cd C:\Demo\MyAwesomeModule

./build.ps1 -ResolveDependency -Tasks noop -UseModuleFast

This command uses Justin Grote’s ModuleFast to download all required modules. In case you didn’t know this yet, ModuleFast is a faster alternative to PowerShellGet for downloading modules from the PowerShell Gallery. It’s significantly quicker than the traditional Install-Module approach, especially when dealing with multiple dependencies. If you’ve ever waited ages for modules to download, you’ll appreciate the speed improvement ModuleFast provides (I’m looking at you Az* and MSGraph* modules! ).

Once dependencies are resolved, you can build your module:

1
./build.ps1 -Tasks build

This compiles your module from the source files, updates the module manifest with the current version, and creates a deployable version in the output folder.

Sampler includes comprehensive testing capabilities. Run all tests with:

1
./build.ps1 -Tasks test

This runs both:

  • QA module tests - Quality assurance checks for your entire module
  • Function unit tests - Individual tests for each of your functions

Test test test

One of the most valuable aspects of Sampler is the automatic quality assurance testing. The QA tests include checks for:

  • Changelog Management - Ensures your CHANGELOG.md is updated and follows the keepachangelog format
  • Module Loading - Verifies your module imports and removes without errors
  • Code Quality - Runs PowerShell Script Analyzer on all your functions
  • Help Documentation - Ensures every function has:
    • A .SYNOPSIS section
    • A .DESCRIPTION with more than 40 characters
    • At least one example
    • Descriptions for all parameters (minimum 25 characters each)
  • Test Coverage - Verifies that every public function has a corresponding unit test

These automated checks help ensure your module follows PowerShell best practices without you having to remember all the rules manually.

Customize YOUR module

Remember, Sampler provides a template - an excellent starting point that leads to high-quality modules. You can (and should) customize whatever you need for your specific project. Want to disable code coverage requirements? Need to publish to a private feed instead of PowerShell Gallery? All of this can be adjusted in the configuration files.

For extensive customization options, check out the excellent and extremely detailed README on the GitHub repository. It covers advanced scenarios, different module types, and various CI/CD configurations.

Sampler transforms the tedious process of setting up a PowerShell module into a quick, straightforward workflow. Instead of spending hours creating folder structures, writing build scripts, and configuring tests, you can have a professional module template ready in minutes.

Whether you’re building internal tools for your organization or creating modules to share with the PowerShell community, Sampler gives you a solid foundation that follows best practices. The automated quality checks ensure your code meets professional standards, while the flexible build system handles the complex parts of module development.

Next time you have an idea for a PowerShell module, don’t let the setup work discourage you. Install Sampler, scaffold your module, and start focusing on the code that actually solves problems.

Happy scripting! 😀