Noveris.Build.psm1

<#
#>


################
# Global settings
$InformationPreference = "Continue"
$ErrorActionPreference = "Stop"

################
# Script variables
$semVerPattern = "^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"

$script:BuildState = [PSCustomObject]@{
    Stages = @{}
    RunState = @{}
}

<#
#>

Function Set-BuildVersionInfo
{
    [CmdletBinding()]
    param(
        [Parameter(mandatory=$true)]
        [ValidateNotNull()]
        [string[]]$Sources
    )

    process
    {
        foreach ($src in $Sources)
        {
            if ($src -eq $null -or $src -eq "")
            {
                continue
            }

            Write-Verbose "Processing version candidate: ${src}"

            # Strip any refs/tags/ reference at the beginning of the version source
            $tagBranch = "refs/tags/"
            if ($src.StartsWith($tagBranch))
            {
                Write-Verbose "Version starts with refs/tags format - Removing"
                $src = $src.Substring($tagBranch.Length)
            }

            if ($src.StartsWith("v"))
            {
                Write-Verbose "Version starts with 'v' - Removing"
                $src = $src.Substring(1)
            }

            if ($src -notmatch $semVerPattern)
            {
                Write-Verbose "Version string not in correct format. skipping"
                continue
            }
          
            $Prerelease = $Matches[4]
            if ($Prerelease -eq $null) {
                $Prerelease = ""
            }
        
            $Buildmetadata = $Matches[5]
            if ($Buildmetadata -eq $null) {
                $Buildmetadata = ""
            }
        
            Write-Verbose "Version is valid"
            $script:BuildState.RunState["Version"] = [ordered]@{
                FileName = $FileName
                Project = $ProjectName
                Version = $version
                Major = [Convert]::ToInt32($Matches[1])
                Minor = [Convert]::ToInt32($Matches[2])
                Patch = [Convert]::ToInt32($Matches[3])
                Prerelease = $Prerelease
                Buildmetadata = $Buildmetadata
            }

            return
        }

        # throw error as we didn't find a valid version source
        Write-Error "Could not find a valid version source"
    }
}

<#
#>

Function Set-BuildStage
{
    [CmdletBinding()]
    param(
        [Parameter(mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Stage,

        [Parameter(mandatory=$true)]
        [ValidateNotNull()]
        [ScriptBlock]$Script
    )

    process
    {
        $script:BuildState.Stages[$Stage] = $Script
    }
}

<#
#>

Function Remove-BuildStage
{
    [CmdletBinding()]
    param(
        [Parameter(mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Stage
    )

    process
    {
        $script:BuildState.Stages.Remove($Stage)
    }
}

<#
#>

function Invoke-BuildStages
{
    [CmdletBinding()]
    param(
        [Parameter(mandatory=$true)]
        [ValidateNotNull()]
        [string[]]$Stages
    )

    process
    {
        $Stages | ForEach-Object {
            if (!$script:BuildState.Stages.ContainsKey($_) -or $script:BuildState.Stages[$_] -eq $null)
            {
                Write-Error "Processing for stage ($_) requested, but it does not exist or is null."
                return
            }

            Write-Information "Running Stage: $_"
            $script:BuildState.RunState | ForEach-Object -Process $script:BuildState.Stages[$_]
            Write-Information "Stage Complete: $_"
        }
    }
}

<#
#>

Function Format-TemplateFile
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Template,

        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Target,

        [Parameter(Mandatory=$true)]
        [Hashtable]$Content
    )

    process
    {
        Get-Content $Template -Encoding UTF8 | Format-TemplateString -Content $Content | Out-File -Encoding UTF8 $Target
    }
}

<#
#>

Function Format-TemplateString
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipeline)]
        [AllowEmptyString()]
        [string]$TemplateString,

        [Parameter(Mandatory=$true)]
        [Hashtable]$Content
    )

    process
    {
        $working = $TemplateString

        foreach ($key in $Content.Keys)
        {
            $working = $working.Replace($key, $Content[$key])
        }

        $working
    }
}

<#
#>

Function Publish-ArtifactFile
{
    [CmdletBinding()]
    param(
        [Parameter(mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Uri,

        [Parameter(mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [string]$Method = "PUT",

        [Parameter(mandatory=$false)]
        [ValidateNorNull()]
        [HashTable]$Headers = @{},

        [Parameter(mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$File
    )

    process
    {
        Invoke-RestMethod -Method $Method -Uri $Uri -Headers $Headers -InFile $File
    }
}