invoke.build.ps1
[CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [String]$ModuleName, [Parameter()] [ValidateNotNullOrEmpty()] [String]$Author, [Parameter()] [String]$Version, [Parameter()] [Bool]$UpdateDocs = $false, [Parameter()] [Bool]$NewRelease = $false ) # Synopsis: Initiate the build process task . ImportBuildModule, InitaliseBuildDirectory, UpdateChangeLog, CopyChangeLog, CreateRootModule, CreateProcessScript, UpdateModuleManifest, CreateArchive, UpdateDocs, UpdateProjectRepo # Synopsis: Install dependent build modules task InstallDependencies { $Modules = "PlatyPS","ChangelogManagement" if ($Script:ModuleName -ne "codaamok.build") { $Module += "codaamok.build" } Install-BuildModules -Module $Modules } # Synopsis: Set build platform specific environment variables task SetGitHubActionEnvironmentVariables { New-BuildEnvironmentVariable -Platform "GitHubActions" -Variable @{ "GH_USERNAME" = $Author "GH_PROJECTNAME" = $ModuleName } } # Synopsis: Publish module to the PowerShell Gallery task PublishModule { Publish-Module -Path $BuildRoot\build\$ModuleName -NuGetApiKey $env:PSGALLERY_API_KEY -ErrorAction "Stop" -Force } # Synopsis: Import the codaamok.build module task ImportBuildModule { if ($Script:ModuleName -eq "codaamok.build") { # This is to use module for building codaamok.build itself Import-Module .\codaamok.build\codaamok.build.psd1 } else { Import-Module "codaamok.build" } } # Synopsis: Create fresh build directories and initalise it with content from the project task InitaliseBuildDirectory { Invoke-BuildClean -Path @( "{0}\build\{1}" -f $BuildRoot, $Script:ModuleName "{0}\release" -f $BuildRoot ) if (Test-Path -Path $BuildRoot\$Script:ModuleName\* -Include "*format.ps1xml") { $Script:FormatFiles = Copy-Item -Path $BuildRoot\$Script:ModuleName -Destination $BuildRoot\build\$Script:ModuleName -Filter "*format.ps1xml" -PassThru } if (Test-Path -Path $BuildRoot\$Script:ModuleName\Files\*) { $Script:FileList = Copy-Item -Path $BuildRoot\$Script:ModuleName\Files\* -Destination $BuildRoot\build\$Script:ModuleName -Recurse -PassThru } Copy-Item -Path $BuildRoot\LICENSE -Destination $BuildRoot\build\$Script:ModuleName\LICENSE Copy-Item -Path $BuildRoot\$Script:ModuleName\en-US -Destination $BuildRoot\build\$Script:ModuleName -Recurse $Script:ManifestFile = Copy-Item -Path $BuildRoot\$Script:ModuleName\$Script:ModuleName.psd1 -Destination $BuildRoot\build\$Script:ModuleName\$Script:ModuleName.psd1 -PassThru } <# Synopsis: Determine version number to build with task GetVersionToBuild { $Params = @{ NewRelease = $Script:NewRelease } if ($Script:CommitMessage -match 'Version to build:') { if ($Script:CommitMessage -match '^Version to build: (\d+\.\d+\.\d+)$') { $Params["VersionToBuild"] = $Matches[1] } else { throw "Unable to parse version number from commit message '$Script:CommitMessage'" } } else { $Params["ModuleName"] = $Script:ModuleName $Params["ManifestData"] = Import-PowerShellDataFile -Path ("{0}\{1}\{1}.psd1" -f $BuildRoot, $Script:ModuleName) $Params["ChangeLogData"] = $Script:ChangeLogData } $Script:VersionToBuild = Get-BuildVersionNumber @Params New-BuildEnvironmentVariable -Platform "GitHubActions" -Variable @{ "VersionToBuild" = $Script:VersionToBuild.ToString() } } #> # Synopsis: Update CHANGELOG.md (if building a new release with -NewRelease) task UpdateChangeLog -If ($Script:NewRelease) { $LinkPattern = @{ FirstRelease = "https://github.com/{0}/{1}/tree/{{CUR}}" -f $Script:Author, $Script:ModuleName NormalRelease = "https://github.com/{0}/{1}/compare/{{PREV}}..{{CUR}}" -f $Script:Author, $Script:ModuleName Unreleased = "https://github.com/{0}/{1}/compare/{{CUR}}..HEAD" -f $Script:Author, $Script:ModuleName } Update-Changelog -Path $BuildRoot\CHANGELOG.md -ReleaseVersion $Script:Version -LinkMode Automatic -LinkPattern $LinkPattern } # Synopsis: Get change log data, copy it to the build directory, and create releasenotes.txt task CopyChangeLog { Copy-Item -Path $BuildRoot\CHANGELOG.md -Destination $BuildRoot\build\$Script:ModuleName\CHANGELOG.md $Script:ChangeLogData = Get-ChangeLogData -Path $BuildRoot\CHANGELOG.md Export-UnreleasedNotes -Path $BuildRoot\release\releasenotes.txt -ChangeLogData $Script:ChangeLogData -NewRelease $Script:NewRelease } # Synopsis: Creates a single .psm1 file of all private and public functions of the to-be-built module task CreateRootModule { $Script:RootModule = "{0}\build\{1}\{1}.psm1" -f $BuildRoot, $Script:ModuleName $DevModulePath = "{0}\{1}" -f $BuildRoot, $Script:ModuleName Export-RootModule -DevModulePath $DevModulePath -RootModule $Script:RootModule } # Synopsis: Create a single Process.ps1 script file for all script files under ScriptsToProcess\* (if any) task CreateProcessScript -If (Test-Path -Path ("{0}\{1}\ScriptsToProcess" -f $BuildRoot, $Script:ModuleName) -Include "*.ps1") { Export-ScriptsToProcess -Path ("{0}\{1}\ScriptsToProcess" -f $BuildRoot, $Script:ModuleName) $Script:ProcessScript = $true } # Synopsis: Update the module manifest in the build directory task UpdateModuleManifest { $UpdateModuleManifestSplat = @{ Path = $Script:ManifestFile RootModule = (Split-Path $Script:RootModule -Leaf) FunctionsToExport = Get-PublicFunctions -Path $BuildRoot\$Script:ModuleName\Public ReleaseNotes = (Get-Content $BuildRoot\release\releasenotes.txt) -replace '`' } # Build with pre-release data from the branch if the -Version parameter is not passed (for local development and testing) if ($Script:Version) { $UpdateModuleManifestSplat["ModuleVersion"] = $Script:Version } else { $GitVersion = (gitversion.exe | ConvertFrom-Json) $UpdateModuleManifestSplat["ModuleVersion"] = $GitVersion.MajorMinorPatch $UpdateModuleManifestSplat["Prerelease"] = $GitVersion.NuGetPreReleaseTag } if ($Script:FormatFiles) { $UpdateModuleManifestSplat["FormatsToProcess"] = $Script:FormatFiles.Name } if ($Script:FileList) { # Use this instead of Updatet-ModuleManifest due to https://github.com/PowerShell/PowerShellGet/issues/196 $Regex = '^# FileList = @\(\)$' $ReplaceStr = 'FileList = "{0}"' -f [String]::Join('", "', $Script:FileList.Name) (Get-Content -Path $Script:ManifestFile.FullName) -replace $Regex, $ReplaceStr | Set-Content -Path $Script:ManifestFile } if ($Script:ProcessScript) { # Use this instead of Updatet-ModuleManifest due to https://github.com/PowerShell/PowerShellGet/issues/196 $Regex = '(#? ?ScriptsToProcess.+)' $ReplaceStr = 'ScriptsToProcess = "Process.ps1"' (Get-Content -Path $Script:ManifestFile.FullName) -replace $Regex, $ReplaceStr | Set-Content -Path $Script:ManifestFile } Update-ModuleManifest @UpdateModuleManifestSplat # Arguably a moot point as Update-MooduleManifest obviously does some testing to ensure a valid manifest is there first before updating it # However with the regex replace for ScriptsToProcess, I want to be sure $null = Test-ModuleManifest -Path $Script:ManifestFile } # Synopsis: Create archive of the module task CreateArchive { $ReleaseAsset = "{0}_{1}.zip" -f $Script:ModuleName, $Script:Version Compress-Archive -Path $BuildRoot\build\$Script:ModuleName\* -DestinationPath $BuildRoot\release\$ReleaseAsset -Force } # Synopsis: Update documentation (-NewRelease or -UpdateDocs switch parameter) task UpdateDocs -If ($NewRelease -Or $UpdateDocs) { Import-Module -Name $BuildRoot\build\$Script:ModuleName -Force New-MarkdownHelp -Module $Script:ModuleName -OutputFolder $BuildRoot\docs -Force } # Synopsis: Update the project's repository with files updated by the pipeline e.g. module manifest task UpdateProjectRepo -If ($NewRelease) { $ManifestData = Import-PowerShellDataFile -Path $Script:ManifestFile # Instead of copying the manifest from the .\build directory, update it in place # This enables me to keep FunctionsToExport = '*' for development. Therefore instead only update the important bits e.g. version and release notes $UpdateModuleManifestSplat = @{ Path = "{0}\{1}\{1}.psd1" -f $BuildRoot, $Script:ModuleName ModuleVersion = $ManifestData.ModuleVersion ReleaseNotes = $ManifestData.PrivateData.PSData.ReleaseNotes } Update-ModuleManifest @UpdateModuleManifestSplat $null = Test-ModuleManifest -Path $Script:ManifestFile } |