This repository provides a comprehensive GitHub Actions workflow system for PowerShell module development, testing, building, and publishing. When contributing to this project or using it as a reference, please follow these guidelines and patterns.
Process-PSModule is a reusable workflow that:
- Builds, tests, and publishes PowerShell modules using the PSModule framework
- Provides multi-OS testing (Linux, macOS, Windows)
- Generates documentation and publishes to GitHub Pages
- Publishes modules to PowerShell Gallery
- Follows Test-Driven Development and Continuous Delivery practices
- Public Functions: Place in
src/functions/public/ - Private Functions: Place in
src/functions/private/ - Classes: Place in
src/classes/public/orsrc/classes/private/ - Data Files: Place in
src/data/(.psd1files) - Module Manifest:
src/manifest.psd1
function Verb-Noun {
<#
.SYNOPSIS
Brief description of what the function does.
.DESCRIPTION
Detailed description of the function's purpose and behavior.
.PARAMETER ParameterName
Description of the parameter.
.EXAMPLE
Verb-Noun -ParameterName 'Value'
Description of what this example does.
.NOTES
Additional notes about the function.
.LINK
https://github.com/PSModule/Process-PSModule
#>
[CmdletBinding()]
param (
# Parameter description
[Parameter(Mandatory)]
[string] $ParameterName
)
begin {
# Initialization code
}
process {
# Main function logic
}
end {
# Cleanup code
}
}Based on PSScriptAnalyzer configuration:
- Use 4 spaces for indentation (no tabs)
- Maximum line length: 150 characters
- Place opening braces on the same line
- Place closing braces on new line
- Use consistent whitespace around operators and separators
# Correct
if ($condition) {
Write-Output "Good"
}
# Incorrect
if ($condition)
{
Write-Output "Bad"
}- Use PascalCase for parameters:
$ModuleName - Use camelCase for local variables:
$tempPath - Use meaningful, descriptive names
try {
# Main logic
}
catch {
Write-Error "Detailed error message: $($_.Exception.Message)"
throw
}Describe 'Function-Name' {
Context 'When condition is met' {
It 'Should perform expected action' {
# Arrange
$input = 'test value'
# Act
$result = Function-Name -Parameter $input
# Assert
$result | Should -Be 'expected value'
}
}
Context 'When validation fails' {
It 'Should throw meaningful error' {
{ Function-Name -Parameter $null } | Should -Throw
}
}
}- Unit tests:
tests/Unit/ - Integration tests:
tests/Integration/ - Test files should mirror source structure
- Name test files:
[FunctionName].Tests.ps1
Every public function must include:
.SYNOPSIS- Brief one-line description.DESCRIPTION- Detailed explanation.PARAMETER- For each parameter.EXAMPLE- At least one working example.NOTES- Additional context if needed.LINK- Reference links
- Function documentation:
src/functions/public/[Category]/[Category].md - Use clear headings and code examples
- Include real-world usage scenarios
Name: ModuleName
Test:
Skip: false
SourceCode:
Skip: false
PSModule:
Skip: false
Module:
Skip: false
CodeCoverage:
PercentTarget: 80
Build:
Skip: false
Module:
Skip: false
Docs:
Skip: false
Publish:
Module:
Skip: false
AutoCleanup: true
AutoPatching: true- Get-Settings - Read configuration
- Build-Module - Compile source into module
- Test-SourceCode - Test source files
- Lint-SourceCode - PSScriptAnalyzer validation
- Test-Module - PSModule framework tests
- Test-ModuleLocal - Pester tests from repo
- Get-TestResults - Aggregate test results
- Get-CodeCoverage - Calculate coverage
- Build-Docs - Generate documentation
- Build-Site - Create static site
- Publish - Release to PowerShell Gallery and GitHub
- Tests run on multiple OS platforms (matrix strategy)
- Steps can be skipped via configuration
- Publishing only occurs on merged PRs
inputs:
Name:
type: string
description: Module name
required: false
SettingsPath:
type: string
description: Path to settings file
default: .github/PSModule.yml
Debug:
type: boolean
description: Enable debug output
default: falseAPIKEY- PowerShell Gallery API key for publishing
Use #Requires statements at the top of files that need specific modules:
#Requires -Modules @{ModuleName='RequiredModule'; ModuleVersion='1.0.0'}# Multiple alias methods supported
[Alias('Short-Name1')]
[Alias('Short-Name2')]
function Long-FunctionName {
# Function body
}
# Alternative alias definitions at end of file
New-Alias Short-Name3 Long-FunctionName
New-Alias -Name Short-Name4 -Value Long-FunctionName
Set-Alias Short-Name5 Long-FunctionNameWhen suppression is necessary, use the standard format:
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'RuleName', 'Target', Scope = 'Function',
Justification = 'Clear reason for suppression'
)]
function Function-Name {
# Function body
}[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[ValidatePattern('^[a-zA-Z0-9-]+$')]
[string] $ModuleName.github/
workflows/ # GitHub Actions workflows
linters/ # Linter configurations
PSModule.yml # Project configuration
src/
functions/
public/ # Exported functions
private/ # Internal functions
classes/
public/ # Exported classes
private/ # Internal classes
data/ # Configuration files
assemblies/ # Binary dependencies
modules/ # Nested modules
tests/
Unit/ # Unit tests
Integration/ # Integration tests
docs/ # Additional documentation
- Follow PowerShell naming conventions - Use approved verbs (
Get-Verb) - Write comprehensive tests first (TDD approach)
- Include proper error handling with meaningful messages
- Document all public interfaces with comment-based help
- Use semantic versioning for releases
- Validate inputs thoroughly using parameter validation
- Write clean, readable code that follows the style guide
- Test on multiple platforms when making changes
- PSScriptAnalyzer violations - Check against rules in
.powershell-psscriptanalyzer.psd1 - Test failures - Ensure tests follow Pester v5 syntax
- Build failures - Verify module manifest and dependencies
- Documentation errors - Check mkdocs.yml configuration
When making changes, always:
- Run PSScriptAnalyzer locally
- Execute relevant tests
- Update documentation
- Follow the established patterns in existing code