Skip to main content

Getting Started with PowerShellBuild

This guide walks through adding PowerShellBuild to a PowerShell module project from scratch. By the end you will have a working build pipeline that cleans, stages, analyzes, tests, and packages your module.

Prerequisites

  • PowerShell 5.1 or PowerShell 7+
  • psake >= 4.9.0
  • PowerShellBuild >= 0.7.0

Install both modules from the PowerShell Gallery:

Install-Module -Name psake -Repository PSGallery
Install-Module -Name PowerShellBuild -Repository PSGallery

Expected Directory Structure

PowerShellBuild expects a conventional PowerShell module layout. The defaults work with the following structure (all paths are configurable — see Configuration):

MyModule/
├── src/
│ ├── MyModule.psd1 # Module manifest
│ ├── MyModule.psm1 # Root module file
│ ├── Public/ # Exported functions
│ │ └── Get-Thing.ps1
│ └── Private/ # Internal functions
│ └── Invoke-Helper.ps1
├── tests/
│ └── MyModule.Tests.ps1 # Pester tests
├── docs/ # PlatyPS markdown (generated)
├── build/ # Output directory (generated)
├── psakeFile.ps1 # Your build task file
├── build.ps1 # Build bootstrap script
└── requirements.psd1 # Module dependencies

Minimal Setup

1. Create psakeFile.ps1

The simplest possible build file just references the Build task from PowerShellBuild:

psakeFile.ps1
properties {
$PSBPreference.Build.OutDir = "$PSScriptRoot/build"
$PSBPreference.General.SrcRootDir = "$PSScriptRoot/src"
}

task default -depends Build

task Build -FromModule PowerShellBuild -Version '0.7.1'

That is all you need. When psake runs the Build task, it loads it from the PowerShellBuild module and automatically runs the full dependency chain:

Init → Clean → StageFiles → GenerateMarkdown → GenerateMAML → BuildHelp → Build

2. Create build.ps1

A bootstrap script that installs dependencies and invokes psake:

build.ps1
[CmdletBinding()]
param(
[string[]]$Task = 'default',
[switch]$Bootstrap
)

if ($Bootstrap) {
Get-PackageProvider -Name NuGet -ForceBootstrap | Out-Null
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
Install-Module -Name psake, PowerShellBuild -Scope CurrentUser -Force
}

Import-Module psake
Invoke-psake -buildFile "$PSScriptRoot/psakeFile.ps1" -taskList $Task -nologo

exit ([int](-not $psake.build_success))

3. Run the Build

# First-time setup
.\build.ps1 -Bootstrap

# Build the module
.\build.ps1

# Run tests only
.\build.ps1 -Task Test

# Publish to PSGallery
.\build.ps1 -Task Publish

What Each Task Does

When you run .\build.ps1 (which runs the default task → Build), here is what happens:

StepTaskWhat it does
1InitCalls Initialize-PSBuild to set up build variables
2CleanRemoves the output directory
3StageFilesCopies (or compiles) module source into the output directory
4GenerateMarkdownGenerates PlatyPS markdown from module help comments
5GenerateMAMLConverts PlatyPS markdown to MAML help XML
6BuildHelpMeta-task — signals that help generation is complete
7BuildMeta-task — signals that the build is complete

Running .\build.ps1 -Task Test additionally runs:

StepTaskWhat it does
8AnalyzeRuns PSScriptAnalyzer against the staged module
9PesterRuns Pester tests, optionally with code coverage
10TestMeta-task — signals that all tests passed

Using with Invoke-Build

If you prefer Invoke-Build over psake, PowerShellBuild supports it via a dot-sourced task file:

.build.ps1
Import-Module PowerShellBuild

# Dot-source the Invoke-Build task definitions
. PowerShellBuild.IB.Tasks

# Override preferences after import
$PSBPreference.Build.OutDir = "$PSScriptRoot/build"
$PSBPreference.General.SrcRootDir = "$PSScriptRoot/src"
$PSBPreference.Test.ScriptAnalysis.Enabled = $true

Run it with:

Invoke-Build Build
Invoke-Build Test

Next Steps