Publish-Application.psm1

#
function Get-Absolute-Path([string]$path){
    if($path.StartsWith(".")){
        $path = [IO.Path]::Combine((Get-Location).Path,$path)
    }
    return [IO.Path]::GetFullPath($path)
}
#
function Get-Default-Settings($configuration,[string] $publishPath,[string] $project){
    #
    $setting =  @{}
    #
    $setting.Enabled =  $true
    if($null -ne $configuration.Enabled){
        $setting.Enabled = $configuration.Enabled
    } 
    #
    $setting.Configuration =  "Release"
    if($null -ne  $configuration.Configuration){
        $setting.Configuration = $configuration.Configuration
    }
    #
    $setting.Runtime =  "linux-x64"
    if($null -ne  $configuration.Runtime){
        $setting.Runtime =$configuration.Runtime 
    } 
    #
    $setting.SelfContained =  $false
    if($null -ne  $configuration.SelfContained){
        $setting.SelfContained = $configuration.SelfContained
    }
    #
    $setting.SingleFile =  $false
    if($null -ne  $configuration.SingleFile ){
        $setting.SingleFile = $configuration.SingleFile
    }
    #
    $path = $configuration.Path
    if([string]::IsNullOrEmpty($path)){
        $path = ""
    }
    #
    if([string]::IsNullOrEmpty($path) -and $null -ne $project){
        $path = [IO.Path]::GetFileNameWithoutExtension($project)
    }
    #
    $setting.Path = [IO.Path]::Combine($publishPath,  $path);
    return $setting
}
<#
.Synopsis
   Automatic Publish Tool (APT)
.DESCRIPTION
   Publish visual studio solution
.EXAMPLE
   Publish-VisualStudioSolution D:\Projects\project.sln
.NOTES
   Author: Imrich Szolik
#>

function Publish-Application
{
    [CmdletBinding()]
    [Alias()]
    Param(
        # Solution file (sln)
        [string]
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$false, HelpMessage="Project file.")]
        $Solution,

        #Publish path.
        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$false, HelpMessage="Publish path.")]
        [string]
        $PublishPath,

        #Configuration path.
        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$false, HelpMessage="Configuration path.")]
        [string]
        $ConfigurationPath = $null,

        #Publish path.
        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$false, HelpMessage="Publish path.")]
        [string]
        $NugetPublishPath = $null,

        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$false, HelpMessage="Publish json config")]
        [string]
        $JsonConfig = "lomtec.json",
        
        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$false, HelpMessage="Build verbosity")]
        [ValidateSet('quiet','minimal','normal',' detailed', 'diagnostic')]
        $Verbosity = "quiet",

        [switch]
        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$false, HelpMessage="Force restore packages (.net 48 required!)")]
        $ForceRestorePackages,

        [switch]
        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$false, HelpMessage="Disable cleanup")]
        $DisableCleanup        
    )
    Begin{
        #validate Solution
        if( (-not (Test-Path -Path $Solution -PathType Leaf)) -or (-not ( $Solution -like '*.sln')) ){
            throw "$Solution is not valid"
        }

        $Solution = ( Resolve-Path $Solution ).Path
        $solutionPath = Split-Path -Parent $Solution

        if([string]::IsNullOrEmpty($PublishPath)){
            $PublishPath = [IO.Path]::Combine($solutionPath,"publish")
        }
        
        if([string]::IsNullOrEmpty($NugetPublishPath)){
            $NugetPublishPath = $PublishPath
        }
        
        #
        $PublishPath = Get-Absolute-Path $PublishPath
        $NugetPublishPath = Get-Absolute-Path $NugetPublishPath
        if(-not [string]::IsNullOrEmpty($ConfigurationPath)){
            $ConfigurationPath = Get-Absolute-Path $ConfigurationPath
        }        
    }
    Process{
        #
        if( -not ($DisableCleanup.IsPresent) ) {
            #cleanup
            Write-Verbose "Remove bin & obj [$solutionPath]"
            Get-ChildItem $solutionPath -Recurse -Directory -Filter obj | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
            Get-ChildItem $solutionPath -Recurse -Directory -Filter bin | Where-Object -Property FullName -NotMatch node_modules | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
            #
            Write-Verbose "Remove publish [$PublishPath] & nuget [$NugetPublishPath] folders"
            Remove-Item $PublishPath -Force -Recurse -ErrorAction SilentlyContinue
            if($PublishPath -ne $NugetPublishPath){
                Remove-Item $NugetPublishPath -Force -Recurse -ErrorAction SilentlyContinue
            }
        }
        
        #restore packages (force restore)
        if($ForceRestorePackages.IsPresent){
            Write-Host "#### APT NUGET restoring packages ####"
            nuget restore $Solution -verbosity quiet
            if($LastExitCode) {
                throw "NUGET RESTORE failed"
            }
        }
        
        #config
        $lomtecConfigs =  Get-ChildItem -Recurse $solutionPath -Filter $JsonConfig | Select-Object -ExpandProperty FullName
        if($lomtecConfigs.Length -eq 0){
            throw "Not found any build configuration [$JsonConfig]!"
        }
        #
        foreach($lomtec in $lomtecConfigs){
            #has project section
            $project = Get-ChildItem (Split-Path -Parent $lomtec) -Filter "*.csproj" | Select-Object -ExpandProperty FullName -First 1
            if($null -eq $project){
                Write-Verbose "Missing csproj file for [$lomtec]"
                Continue
            }

            #json
            $json = Get-Content $lomtec | ConvertFrom-Json

            #has build section
            if($null -eq $json.Build){
                Write-Warning "Missing Build section for [$lomtecConfigs]"
                Continue
            }

            #process Publish or Nuget
            if($null -ne $json.Build.Publish -and $json.Build.Publish.Count -gt 0){
                #
                foreach($config in $json.Build.Publish){
                    #setting
                    $setting = Get-Default-Settings $config $PublishPath $ConfigurationPath $project
                    #publish
                    if($setting.Enabled){
                        Write-Host "#### APT PUBLISH $(Split-Path -Leaf $project) to $($setting.Path) ####"
                        dotnet publish -nologo --verbosity $Verbosity --runtime $setting.Runtime --configuration $setting.Configuration --self-contained $setting.SelfContained -p:PublishSingleFile=$($setting.SingleFile) $project --output $setting.Path
                        if($LastExitCode) {
                            throw "DOTNET PUBLISH $(Split-Path -Leaf $project) failed"
                        }
                        
                    }
                    else{
                        Write-Warning "#### APT PUBLISH $(Split-Path -Leaf $project) [$(Split-Path -Leaf $setting.Path)] is not enabled ####"
                    }            
                }
            }
            elseif($null -ne $json.Build.Nuget){
                #setting
                $config  = $json.Build.Nuget
                $setting = Get-Default-Settings $config $NugetPublishPath

                Write-Host "#### APT BUILD $(Split-Path -Leaf $project) ####"
                dotnet build -nologo --verbosity $Verbosity --configuration $setting.Configuration $project 
                if($LastExitCode) {
                    throw "DOTNET BUILD $(Split-Path -Leaf $project) failed"
                }

                Write-Host "#### APT NUGET $(Split-Path -Leaf $project) to $($setting.Path) ####"
                $nuspec = $project.Replace("csproj","nuspec")
                if(Test-Path -Path $nuspec -PathType Leaf){
                    nuget pack -OutputDirectory $setting.Path -properties Configuration=$($setting.Configuration) -verbosity quiet $nuspec
                    if($LastExitCode) {
                        throw "NUGET PACK $(Split-Path -Leaf $project) failed"
                    }
                }
                else{
                    Write-Warning "Missing nuspec $nuspec!"
                }
            }
            else{
                Write-Warning "Missing Build/Publish or Build/Nuget section for [$lomtecConfigs]!"
            }
        }
        #cleanup
        Write-Verbose "Publish cleanup [$PublishPath]"
        Get-ChildItem -Path $PublishPath -Recurse -Filter *.pdb -File -ErrorAction SilentlyContinue | Remove-Item -Force
        Get-ChildItem -Path $PublishPath -Recurse -Filter $JsonConfig -File -ErrorAction SilentlyContinue | Remove-Item -Force
    }
    End{
    }
}

Export-ModuleMember -Function Publish-Application



# SIG # Begin signature block
# MIIH7gYJKoZIhvcNAQcCoIIH3zCCB9sCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUY/NUkOyreKUA0bfqtSKCEsaw
# 0/GgggUPMIIFCzCCAvOgAwIBAgICAKUwDQYJKoZIhvcNAQELBQAwgaAxCzAJBgNV
# BAYTAlNLMREwDwYDVQQIEwhTbG92YWtpYTETMBEGA1UEBxMKQnJhdGlzbGF2YTET
# MBEGA1UEChMKTG9tdGVjLmNvbTErMCkGA1UEAxMiTG9tdGVjLmNvbSBDZXJ0aWZp
# Y2F0aW9uIEF1dGhvcml0eTEnMCUGCSqGSIb3DQEJARYYSW1yaWNoLlN6b2xpa0Bs
# b210ZWMuY29tMB4XDTE5MDMyNjE1MDQ0M1oXDTMwMDEwMTAwMDAwMFowgZMxCzAJ
# BgNVBAYTAlNLMREwDwYDVQQIEwhTbG92YWtpYTETMBEGA1UEBxMKQnJhdGlzbGF2
# YTETMBEGA1UEChMKTG9tdGVjLmNvbTEeMBwGA1UEAxMVTG9tdGVjLmNvbSBQb3dl
# cnNoZWxsMScwJQYJKoZIhvcNAQkBFhhJbXJpY2guU3pvbGlrQGxvbXRlYy5jb20w
# ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+J+Jwh25Ha39PSBzRUNj/
# 8+iONxiknLBSTkB1DJEQ9wC6FBS/1EQvbFtn2K6huVZBQCoZzNFcXoiAked3ALIT
# UoYxX+fD4Wkve947QqCXGroCFQVaBSLkPoJzWCadlXQWyDyjFuCY42TsQRJB6TFp
# n4rVylhinlOvEHJ96COjzvmEs7X1y3tTVPtRiDt3wOxNLx1T1H/6lmVzGFORJS0F
# ZvQF231+/Zk4Je+gOe/jguo/gHoZHdjj31JeMLJ6Md3zslAFAPIqI3lofez6V3f7
# PkZLsVnYLAuGElg1I4WUswZJpfbnq2KqPWvlwG9/Xb5KSvUz5d6uRzQUDJAn6fG5
# AgMBAAGjWjBYMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgeAMCsGA1UdJQQkMCIGCCsG
# AQUFBwMDBgorBgEEAYI3AgEVBgorBgEEAYI3AgEWMBEGCWCGSAGG+EIBAQQEAwIE
# sDANBgkqhkiG9w0BAQsFAAOCAgEACSWqb/bJGI4eR07CZ6g3baoe2Djl7gPIPgyg
# Y/uYAxGROVfVYQBVafFCfUaCExhiEU1SHdJanCyYlUkx8d9OVVvWiA/L6O+5H608
# l7z1zSLE7R5z5JMB+O/gqImNyKT0C41AP0OkHasCDb78KJu/1nPjqCKpT3SR+Q2w
# ayMvOXa+jPy5t0cNgaJXE0cF0wd8QIcHrYe/AT+qW3AHd9hXcppEaKSyIobjbO4O
# 2Uf0P+fNNxvjokCDERsk72kPmkIyYBaZM6ezSMIc6LoHwjleO0nPPYxKVKsNeotl
# BX89ssDpVlMmLbntUtT4zNZY4CX0aPntMFJxaYBUM1xhdW02FWkOHt5yZXgA376n
# l6B9gGHgU28/QXKIJJH1EQAt4oqG9WzbOYxNQm6xAwsOpv9N5NKDppt8UJLF8gIQ
# WLlJEcLvY3eMtxcGf7Mgxi892+nGPKNWMiDTjgNwdq/drITbdK1oSbt7/qnCFZhU
# NGipYTTUaIlZUICezYDtFFfr1NpYIrHKVEsRLcSjfuOdK+PbLtOjQOs7Mp9whC1J
# lZD8o8eX8os8LfSsVbmDlEhG99mO0An3xydarRekrkKym4G/9uMu3Ag1ujw1Ubzz
# sklJSrvbD8pCAg4781wb42BCCzOwJrWAiARkIIpgbEL0xKFyV4sADotVzc9y8XI0
# B0P2TOMxggJJMIICRQIBATCBpzCBoDELMAkGA1UEBhMCU0sxETAPBgNVBAgTCFNs
# b3Zha2lhMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpMb210ZWMuY29t
# MSswKQYDVQQDEyJMb210ZWMuY29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MScw
# JQYJKoZIhvcNAQkBFhhJbXJpY2guU3pvbGlrQGxvbXRlYy5jb20CAgClMAkGBSsO
# AwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEM
# BgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEWMCMGCSqG
# SIb3DQEJBDEWBBSIc9fy6OtHRW50DH/A/uLmPKuVazANBgkqhkiG9w0BAQEFAASC
# AQA8yLSG5HUotLfUnni2YVNr9cqLWAxzSRG9uFoc+EaQBDNC10ij2sjKQ+VP4MXi
# FfNL1fiGJW34Zl5Qa59dNoEfAov/ttPcT93Fdo/MAtA7xEizZG/7Cp2Jd6gJsZ+Y
# msVLd0vgwh9Q/6q1iU+Iwwt4T8SnGsQ4XAt3No2zJRIRrL5QtFYw3nswbnE2QScX
# rpt0jmoTG/o0jMC/mges3loyb4etTeSGfugSWKiLRYm1sbltqBLY3WzWq7RCdOTP
# TFl8hluEmwJYJNgCknGiNUTL/+vgE2BFjwqGBP3OPa3k+gQKDHS+sumOolUBFbAv
# +jjMWFDUVruk+fCMxyIcXSIk
# SIG # End signature block