PSModuleUtils.psm1
function Build-PSModule { [CmdletBinding()] param ( [String]$Name = 'PSModule', [String]$Version = '0.0.1', [String]$Description = 'A PowerShell module.', [String[]]$Tags = @('PSEdition_Desktop', 'PSEdition_Core', 'Windows'), [String]$SourceDirectory = "$PWD/src", [String]$OutputDirectory = "$PWD/out", [Switch]$FixScriptAnalyzer ) Remove-Item -Path $OutputDirectory -Recurse -Force -ErrorAction SilentlyContinue $ModuleOutputDirectory = "$OutputDirectory/$Name/$Version" Invoke-ScriptAnalyzer -Path $SourceDirectory -Recurse -Severity Information -Fix:$FixScriptAnanlyzer $null = New-Item -Path "$ModuleOutputDirectory/$name.psm1" -ItemType File -Force $functionNames = @() $moduleContent = @() Get-ChildItem -Path "$SourceDirectory/public" -Filter '*.ps1' -Exclude '*.Tests.ps1' -File -Recurse | ForEach-Object -Process { $functionName = $_.BaseName $functionNames += $functionName $functionContent = Get-Content -Path $_.FullName # Remove any init blocks outside of the function $startIndex = ( $functionContent.IndexOf('<#'), $functionContent.IndexOf($functionContent -match "function $functionName")[0] ) | Where-Object -FilterScript { $_ -ge 0 } | Sort-Object | Select-Object -First 1 $functionContent = $functionContent[$startIndex..($functionContent.Length - 1)] # Format the private function dot sources for the expected folder structure $functionContent = $functionContent.Replace('private', 'private') $moduleContent += '' $moduleContent += $functionContent } $moduleContent | Set-Content -Path "$ModuleOutputDirectory/$name.psm1" -Force $null = New-Item -Path "$ModuleOutputDirectory/private" -ItemType Directory -Force Get-ChildItem -Path "$SourceDirectory/private" -Exclude '*.Tests.ps1' | Copy-Item -Destination "$ModuleOutputDirectory/private" -Recurse -Force $manifestPath = "$ModuleOutputDirectory/$Name.psd1" $repoUrl = ( & git config --get remote.origin.url ).Replace('.git', '') $companyName = if ($repoUrl -match 'github') { $repoUrl.Split('/')[3] } else { $env:USERDOMAIN } $existingGuid = Find-Module -Name $Name -Repository PSGallery -ErrorAction SilentlyContinue | Select-Object -ExpandProperty AdditionalMetadata | Select-Object -ExpandProperty GUID $guid = if ($existingGuid) { $existingGuid } else { ( New-Guid ).Guid } $requiredModulesStatement = Get-Content -Path "$SourceDirectory\$Name.psm1" | Where-Object -FilterScript { $_ -match '#Requires' } $requiredModules = (($requiredModulesStatement -split '-Modules ')[1] -split ',').Trim() $newModuleManifest = @{ Path = $manifestPath Author = ( & git log --format='%aN' | Sort-Object -Unique ) CompanyName = $companyName Copyright = "(c) $( Get-Date -Format yyyy ) $companyName. All rights reserved." RootModule = "$Name.psm1" ModuleVersion = $Version Guid = $guid Description = $Description PowerShellVersion = 5.1 FunctionsToExport = $functionNames CompatiblePSEditions = ('Desktop', 'Core') Tags = $Tags ProjectUri = $repoUrl LicenseUri = 'https://opensource.org/licenses/MIT' ReleaseNotes = ( git log -1 --pretty=%B )[0] } if ($requiredModules) { $newModuleManifest['RequiredModules'] = $requiredModules } New-ModuleManifest @newModuleManifest Get-Item -Path $manifestPath Get-Module -Name $Name -All | Remove-Module -Force -ErrorAction SilentlyContinue Import-Module -Name $manifestPath -Force -PassThru } function Publish-PSModule { [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [String]$Name = 'PSModule', [String]$OutputDirectory = "$PWD/out", [String]$Repository = 'PSGallery', [String]$ApiKey = $env:PSGALLERYAPIKEY ) Get-Module -Name $Name -All | Remove-Module -Force -ErrorAction SilentlyContinue $versionedFolder = Get-ChildItem -Path "$OutputDirectory/$Name" | Select-Object -Last 1 if ($versionedFolder) { Import-Module -Name "$($versionedFolder.FullName)/$Name.psd1" -Force -PassThru if ($PSCmdlet.ShouldProcess("$Name v$($versionedFolder.BaseName)", "Publish-Module")) { Publish-Module ` -Path $versionedFolder.FullName ` -NuGetApiKey $ApiKey ` -Repository $Repository Find-Module -Name $Name -RequiredVersion $versionedFolder.BaseName -Repository $Repository } } else { Write-Warning -Message "No module named $Name found to publish." } } function Test-PSModule { [CmdletBinding()] param ( [String]$Name = 'PSModule', [String]$SourceDirectory = "$PWD/src", [String[]]$Tag ) Get-Module -Name $Name -All | Remove-Module -Force -ErrorAction SilentlyContinue $config = [PesterConfiguration]::Default if ($Tag) { $config.Filter.Tag = 'Unit' } $config.Run.Path = $SourceDirectory $config.Run.Exit = $true $config.Run.Throw = $true $config.Output.Verbosity = 'Detailed' Invoke-Pester -Configuration $config } |