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
# MIIIEwYJKoZIhvcNAQcCoIIIBDCCCAACAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA5MtBiC1NMkkm6
# LSuzLacYM2GCqZPCC3+TN4NPbb8bPqCCBQ8wggULMIIC86ADAgECAgIApTANBgkq
# hkiG9w0BAQsFADCBoDELMAkGA1UEBhMCU0sxETAPBgNVBAgTCFNsb3Zha2lhMRMw
# EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpMb210ZWMuY29tMSswKQYDVQQD
# EyJMb210ZWMuY29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MScwJQYJKoZIhvcN
# AQkBFhhJbXJpY2guU3pvbGlrQGxvbXRlYy5jb20wHhcNMTkwMzI2MTUwNDQzWhcN
# MzAwMTAxMDAwMDAwWjCBkzELMAkGA1UEBhMCU0sxETAPBgNVBAgTCFNsb3Zha2lh
# MRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpMb210ZWMuY29tMR4wHAYD
# VQQDExVMb210ZWMuY29tIFBvd2Vyc2hlbGwxJzAlBgkqhkiG9w0BCQEWGEltcmlj
# aC5Tem9saWtAbG9tdGVjLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
# ggEBAL4n4nCHbkdrf09IHNFQ2P/z6I43GKScsFJOQHUMkRD3ALoUFL/URC9sW2fY
# rqG5VkFAKhnM0VxeiICR53cAshNShjFf58PhaS973jtCoJcaugIVBVoFIuQ+gnNY
# Jp2VdBbIPKMW4JjjZOxBEkHpMWmfitXKWGKeU68Qcn3oI6PO+YSztfXLe1NU+1GI
# O3fA7E0vHVPUf/qWZXMYU5ElLQVm9AXbfX79mTgl76A57+OC6j+Aehkd2OPfUl4w
# snox3fOyUAUA8iojeWh97PpXd/s+RkuxWdgsC4YSWDUjhZSzBkml9uerYqo9a+XA
# b39dvkpK9TPl3q5HNBQMkCfp8bkCAwEAAaNaMFgwCQYDVR0TBAIwADALBgNVHQ8E
# BAMCB4AwKwYDVR0lBCQwIgYIKwYBBQUHAwMGCisGAQQBgjcCARUGCisGAQQBgjcC
# ARYwEQYJYIZIAYb4QgEBBAQDAgSwMA0GCSqGSIb3DQEBCwUAA4ICAQAJJapv9skY
# jh5HTsJnqDdtqh7YOOXuA8g+DKBj+5gDEZE5V9VhAFVp8UJ9RoITGGIRTVId0lqc
# LJiVSTHx305VW9aID8vo77kfrTyXvPXNIsTtHnPkkwH47+CoiY3IpPQLjUA/Q6Qd
# qwINvvwom7/Wc+OoIqlPdJH5DbBrIy85dr6M/Lm3Rw2BolcTRwXTB3xAhweth78B
# P6pbcAd32FdymkRopLIihuNs7g7ZR/Q/5803G+OiQIMRGyTvaQ+aQjJgFpkzp7NI
# whzougfCOV47Sc89jEpUqw16i2UFfz2ywOlWUyYtue1S1PjM1ljgJfRo+e0wUnFp
# gFQzXGF1bTYVaQ4e3nJleADfvqeXoH2AYeBTbz9BcogkkfURAC3iiob1bNs5jE1C
# brEDCw6m/03k0oOmm3xQksXyAhBYuUkRwu9jd4y3FwZ/syDGLz3b6cY8o1YyINOO
# A3B2r92shNt0rWhJu3v+qcIVmFQ0aKlhNNRoiVlQgJ7NgO0UV+vU2lgiscpUSxEt
# xKN+450r49su06NA6zsyn3CELUmVkPyjx5fyizwt9KxVuYOUSEb32Y7QCffHJ1qt
# F6SuQrKbgb/24y7cCDW6PDVRvPOySUlKu9sPykICDjvzXBvjYEILM7AmtYCIBGQg
# imBsQvTEoXJXiwAOi1XNz3LxcjQHQ/ZM4zGCAlowggJWAgEBMIGnMIGgMQswCQYD
# VQQGEwJTSzERMA8GA1UECBMIU2xvdmFraWExEzARBgNVBAcTCkJyYXRpc2xhdmEx
# EzARBgNVBAoTCkxvbXRlYy5jb20xKzApBgNVBAMTIkxvbXRlYy5jb20gQ2VydGlm
# aWNhdGlvbiBBdXRob3JpdHkxJzAlBgkqhkiG9w0BCQEWGEltcmljaC5Tem9saWtA
# bG9tdGVjLmNvbQICAKUwDQYJYIZIAWUDBAIBBQCggYQwGAYKKwYBBAGCNwIBDDEK
# MAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3
# AgELMQ4wDAYKKwYBBAGCNwIBFjAvBgkqhkiG9w0BCQQxIgQgvtLt2sbGpjQHd+nD
# iVUxCZNEyHvSbj4QpUyfdK0eMxQwDQYJKoZIhvcNAQEBBQAEggEAkJH+O6P4CpAX
# YqBMrs28RdUzeZ/bnj7iSgAVqWCCGbmsn6U2LU3udT+yjLHIAXIpAuNPMQgexsIx
# rWnM1wHBgC020EYMzGcqSbAgIw/O4o5ptpNifIsBSuchNXFVn1aoVj5jOId/TbKj
# bugCLU2aNykfFMGrb5lFTRhyKE89P6wNkN3wQMP49AjaWJijwLM77scL8pvZOPVc
# tPWCNRtaoVwc7NnK8CRBKlAAgPaCVNSQNdrib754z6dKDvJr8Ol9Ybuf0hqJWjqE
# fGpWQjszctH17iiJ4s+L5ebJ9H+UQJv88psxSyXtAcK9WzHaCwuEV26SugLiSqkf
# HJ/UWq4VrQ==
# SIG # End signature block