CI/CD Integration¶
PSScriptBuilder is a PowerShell module — integrating it into a CI/CD pipeline follows the same pattern as any other PowerShell-based build tool. This guide explains what PSScriptBuilder needs in any automated environment and illustrates it with a GitHub Actions example. The principles apply to GitLab CI, Azure DevOps, Jenkins, or any other system that can run PowerShell.
What PSScriptBuilder Needs in CI¶
Regardless of the CI/CD system, every PSScriptBuilder build requires the same four steps:
- Install the module — PSScriptBuilder must be available in the PowerShell module path
- Set the project root — call
Set-PSScriptBuilderProjectRootat the start of your build script; PSScriptBuilder resolves all relative paths from this root. Calling it inside the build script keeps CI configuration minimal and the build locally reproducible. - Run the build script — invoke your
Build-MyModule.ps1(or equivalent); the script runsInvoke-PSScriptBuilderBuildand produces the output file - Check the result — the build throws on failure, so a non-zero exit code is sufficient
for most CI systems; use
$result.SyntaxValidortry/catchfor more granular control
Keep the build script outside CI configuration
Define your full build logic in a dedicated PowerShell script (e.g. Build-MyModule.ps1)
rather than inlining it in the CI configuration file. This keeps your CI steps short,
makes the build locally reproducible, and avoids platform-specific escaping issues.
Example: GitHub Actions¶
The following workflow illustrates the four steps above using GitHub Actions. The workflow
runs on every push and pull request, installs PSScriptBuilder from the PowerShell Gallery,
and delegates the actual build logic to Build-MyModule.ps1. Keeping the build logic in a
script — rather than inline YAML — means the same script works locally and in CI without
any changes.
Adapt the YAML syntax to your CI/CD system. The PowerShell commands inside the steps remain the same regardless of the platform:
name: Build
on: [push, pull_request]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Install PSScriptBuilder
shell: pwsh
run: Install-Module PSScriptBuilder -Force -SkipPublisherCheck
- name: Build
shell: pwsh
run: .\Build-MyModule.ps1
Handling the Build Result¶
Invoke-PSScriptBuilderBuild throws a typed exception on any build failure — circular
dependencies, missing files, name conflicts, and syntax errors all result in a non-zero
PowerShell exit code. Most CI systems treat this as a job failure automatically, so no
additional error handling is strictly required.
That said, wrapping the build in a try/catch block has two advantages in a CI context:
the error message is written explicitly to the error stream (making it easier to spot in
CI logs), and you have a single place to add cleanup logic or notifications if needed:
Set-PSScriptBuilderProjectRoot -Path $PSScriptRoot
try {
$result = New-PSScriptBuilderContentCollector |
Add-PSScriptBuilderCollector -Type Class -IncludePath 'src\Classes' |
Add-PSScriptBuilderCollector -Type Function -IncludePath 'src\Public' |
Invoke-PSScriptBuilderBuild `
-TemplatePath 'build\Templates\MyModule.psm1.template' `
-OutputPath 'build\Output\MyModule.psm1'
$result | Format-PSScriptBuilderBuildResult
}
catch {
Write-Error "Build failed: $($_.Exception.Message)"
exit 1
}
Compressing Before Deploy¶
A standard build output preserves all comments, blank lines, and verbose logging — useful
during development, but unnecessary in a deployed script. Before copying the output to a
deploy location or publishing it to the PowerShell Gallery, you can reduce the file size
by stripping those elements with
Compress-PSScriptBuilderScript.
Chain it directly after Invoke-PSScriptBuilderBuild using the pipeline and write to a
separate deploy location — the original build output in build\Output\ stays intact:
Set-PSScriptBuilderProjectRoot -Path $PSScriptRoot
New-PSScriptBuilderContentCollector |
Add-PSScriptBuilderCollector -Type Class -IncludePath 'src\Classes' |
Add-PSScriptBuilderCollector -Type Function -IncludePath 'src\Public' |
Invoke-PSScriptBuilderBuild `
-TemplatePath 'build\Templates\MyModule.psm1.template' `
-OutputPath 'build\Output\MyModule.psm1' |
Compress-PSScriptBuilderScript `
-RemoveComments `
-RemoveBlankLines `
-DestinationPath 'deploy\MyModule.psm1' `
-Force
The pipeline passes the build result directly into Compress-PSScriptBuilderScript, so
there is no $result variable to inspect. If you also need to log component counts or
handle errors explicitly, capture the result as shown in
Handling the Build Result and call
Compress-PSScriptBuilderScript separately.
See Also¶
- Build Guide — full build pipeline documentation
- Cmdlet Reference: Invoke-PSScriptBuilderBuild
- Cmdlet Reference: Compress-PSScriptBuilderScript