Build/Build.ps1

<#
    .SYNOPSIS
    Builds your PowerShell module.

    .DESCRIPTION
    A tool to Build a basic module with. It can take several variables to flesh out your build environment and do
    your testing, build and publishing

    .PARAMETER Tasklist
    Tasks are:
    'Init' - sets the build location to the project root. Also adds /Staging and /BuildOutput folders to .gitignore
    'Clean' - cleans up any files/folders from a previous build and creates the Aritact and Staging directories
    'CombineAndStage' - pulls all your function files into a .psm1 and copies everything to /Staging
    'Stage' - pulls all your specified files into the /Staging folder in preparation for creation a .nupkg file or other artifact. Retains current directory structure.
    'ImportStagingModule' - Import the module you just staged, you'll use that for making a .zip or .nupkg. Separates your working tree from the code you are going to deploy
    'Analyze' - Run PSScriptAnalyzer on the modules in /Staging to ensure linting and syntax are correct
    'Test' - Run Pester tests against the code. Tests are coming from /Tests
    'Help' - Create/Update markdown helpfiles using PlatyPS
    'UpdateBuildVersion' - based on a parameter you pass (see below) the build number is updated
    'UpdateRepo' - does a git push back to your repo to sync your current files. Also tags files with the current build
    'BuildNuget' - builds a .nupkg file in the /BuildOutput directory
    'BuildZip' - creates a .zip file of your creation in the /BuildOutput folder
    'PublishAzure' - invokes Publish-Module to publish your code to your Azure Repo
    'PublishPSGallery' - invokes Publish-Module to publish to PowerShellGallery
    'Sign' - used to sign your module with a certificate

    .PARAMETER Parameters
    A hashtable of parameters you want to pass into your build. Ex.: @{BuildRev="REVISION", CommitMessage="I updated the build revision"}

    .PARAMETER Properties
    A hashtable to update various pathes and other settings used by this script

    .INPUTS
    System.Object

    .OUTPUTS
    PS Module

    .EXAMPLE
   ./Build/build.ps1 -Tasklist init -ResolveDependency

   Resolves your dependencies as specified in the build.depend.ps1 file and sets the build environment up for you.

    .EXAMPLE
    ./Build/build.ps1 -Tasklist BuildNuget -Parameters @{BuildRev="Revision"; CommitMessage="First Commit"}

    .NOTES
    Author: John McCrae

    .REFERENCES
    thanks to Adam Rush UK - https://adamrushuk.github.io/example-azure-devops-build-pipeline-for-powershell-modules/#test-1

#>

[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "")]
[CmdletBinding()]
param (
    [Parameter()]
    [System.String[]]
    $TaskList = 'Default',

    [Parameter()]
    [System.Collections.Hashtable]
    $Parameters,

    [Parameter()]
    [System.Collections.Hashtable]
    $Properties,

    [Parameter()]
    [Switch]
    $ResolveDependency
)

Write-Output "`nSTARTED TASKS: $($TaskList -join ',')`n"

Write-Output "`nPowerShell Version Information:"
$PSVersionTable


# Load dependencies
if ($PSBoundParameters.Keys -contains 'ResolveDependency') {
    # Bootstrap environment
    Get-PackageProvider -Name 'NuGet' -ForceBootstrap | Out-Null

    # Install PSDepend module if it is not already installed
    if (-not (Get-Module -Name 'PSDepend' -ListAvailable)) {
        Write-Output "`nPSDepend is not yet installed...installing PSDepend now..."
        Install-Module -Name 'PSDepend' -Scope 'CurrentUser'  -Repository PSGALLERY -Force
    }
    else {
        Write-Output "`nPSDepend already installed...skipping."
    }

    #checking for the presence of Git. The Buildhelpers dependency will fail at the end of setup if Git isn't installed
    try {
        git | Out-Null
        #$gitinstalled = $true
    }
    catch [System.Management.Automation.CommandNotFoundException] {
        $LASTEXITCODE = 1
        #$gitinstalled = $false
        throw "A git client was not detected. Please install one and re-run 'build.ps1 -ResolveDependency'"
    }

    # Install build dependencies
    $psdependencyConfigPath = Join-Path -Path $PSScriptRoot -ChildPath 'build.depend.psd1'
    Write-Output "Checking / resolving module dependencies from [$psdependencyConfigPath]...`n"
    Import-Module -Name 'PSDepend'

    $invokePSDependParams = @{
        Path    = $psdependencyConfigPath
        Tags    = 'Bootstrap'
        Import  = $true
        Confirm = $false
        Install = $true
        Verbose = $true
    }
    Invoke-PSDepend @invokePSDependParams

    # Remove ResolveDependency PSBoundParameter ready for passthru to PSake
    $PSBoundParameters.Remove('ResolveDependency')
}
else {
    Write-Host "Skipping dependency check...`n" -ForegroundColor 'Yellow'
}


# Init BuildHelpers
Set-BuildEnvironment -Force

## - jfm
Set-Item -Path env:\BHPSVersionNumber -Value $((Get-Variable 'PSVersionTable' -ValueOnly).PSVersion.Major)

$pathChar = [System.IO.Path]::DirectorySeparatorChar
Set-Item -Path env:\BHPathDivider -Value $pathChar

if ($env:BHPSVersionNumber -lt 6) {
    Set-Item -Path env:\BHBuildOS -Value 'Windows'
    Set-Item -Path env:\BHTempDirectory -Value $([System.IO.Path]::GetTempPath())
}
elseif (Get-Variable -Name 'IsWindows' -ErrorAction 'SilentlyContinue' -ValueOnly ) {
    Set-Item -Path env:\BHBuildOS -Value 'Windows'
    Set-Item -Path env:\BHTempDirectory -Value $([System.IO.Path]::GetTempPath())
}
elseif (Get-Variable -Name 'IsMacOS' -ErrorAction 'SilentlyContinue' -ValueOnly ) {
    Set-Item -Path env:\BHBuildOS -Value 'macOS'
    Set-Item -Path env:\BHTempDirectory -Value "/private/tmp"
}
elseif (Get-Variable -Name 'IsLinux' -ErrorAction 'SilentlyContinue' -ValueOnly ) {
    Set-Item -Path env:\BHBuildOS -Value 'Linux'
    Set-Item -Path env:\BHTempDirectory -Value "/tmp"
}
## - jfm

# The Default Build Helpers variable settings leave some gaps that need resolving. Doing that here.
#region - BHBUILDVARS
Set-Item -Path Env:BHBuildCulture -Value (get-culture).name
Set-Item -Path Env:BHBuildSystem -Value "Azure Pipelines"

$manifest = Import-PowerShellDataFile (Get-item env:\BHPSModuleManifest).Value
[version]$script:Version = $manifest.ModuleVersion
Set-Item -Path Env:BHBuildNumber -Value $script:Version

$stagingfolder = (Get-item env:\BHPSModulePath).Value + $env:BHPathDivider + "Staging"
Set-Item -Path env:\BHPSModulePath -Value $stagingfolder

$publishfolder = $ENV:BHModulePath + $env:BHPathDivider + "Staging" + $env:BHPathDivider + $ENV:BHProjectName
Set-Item -Path env:\BHModulePath -Value $publishfolder
#endregion

# Capture the build version type - Major, Minor, Build, Revision. Used later to bump the version number of your package
# The revision is passed in via the BuildRev parameter.
# also grabbing a Commit message so we an do a git push to your Repo.
if ($PSBoundParameters.Keys -contains 'Parameters') {
    foreach ($key in $Parameters.Keys) {
        if ($key -eq 'BuildRev') {
            $versiondetail = $Parameters.$key
            Set-Item -Path Env:BHBuildRevision -Value $versiondetail
        }
        elseif ($key -eq 'CommitMessage') {
            $commitMessage = $Parameters.$key
            Set-Item -Path Env:BHCommitMessage -Value $commitMessage
            Set-Item -Path Env:BHCommitFlag -Value 1
        }
    }
}

# If you don't specify a build version change, we go with no change
if ($PSBoundParameters.ContainsKey('Tasklist')) {
    if ((($TaskList -like "*Build*") -or ($TaskList -like "*Publish*")) -and ($Parameters.Keys -notcontains "BuildRev")) {
        $PSBoundParameters.Parameters += @{BuildRev = 'None' }
    }
    elseif (($TaskList -like "*Publish*") -and ((Get-Item -Path env:\BH*).Name -notcontains "BHPSGalleryKey")) {
        Write-Host "You need to create the environmental variable 'BHPSGalleryKey' with your PowerShell Gallery key" -ForegroundColor 'Red' -BackgroundColor 'Black'
        Break
    }

    # Execute PSake tasks
    $invokePsakeParams = @{
        buildFile = (Join-Path -Path $env:BHProjectPath -ChildPath $("Build" + $env:BHPathDivider + "build.psake.ps1"))
        nologo    = $true
    }
    Invoke-Psake @invokePsakeParams @PSBoundParameters

}

Write-Output "`nFINISHED TASKS: $($TaskList -join ',')"
exit ( [int](-not $psake.build_success) )