Pentia.Publish-WebProject.psm1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<#
 .SYNOPSIS
 Publishes a web project to the specified output directory using MSBuild.
 
 .PARAMETER WebProjectFilePath
 Absolute or relative path of the web project file.
 
 .PARAMETER OutputPath
 Absolute or relative path of the output directory.
 
 .PARAMETER MSBuildExecutablePath
 Absolute or relative path of MSBuild.exe. If null or empty, the script will attempt to find the latest MSBuild.exe installed with Visual Studio 2017 or later.
 
 .EXAMPLE
 Publish-WebProject -WebProjectFilePath "C:\Path\To\MyProject.csproj" -OutputPath "C:\Websites\MyWebsite"
 Publish a project.
 
 .EXAMPLE
 Publish-WebProject -WebProjectFilePath "C:\Path\To\MyProject.csproj" -OutputPath "C:\Websites\MyWebsite" -MSBuildExecutablePath "C:\Path\To\MsBuild.exe"
 Publish a project and specify which MSBuild.exe to use.
#>

function Publish-WebProject {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline)]
        [string]$WebProjectFilePath,

        [Parameter(Mandatory = $true)]
        [string]$OutputPath,

        [Parameter(Mandatory = $false)]
        [string]$MSBuildExecutablePath
    )

    process {
        if (!(Test-Path $WebProjectFilePath -PathType Leaf)) {
            throw "File path '$WebProjectFilePath' not found."
        }
        if (-not ([System.IO.Path]::IsPathRooted($OutputPath))) {
            $OutputPath = [System.IO.Path]::Combine($PWD, $OutputPath)
        }
        Write-Verbose "Publishing '$WebProjectFilePath' to '$OutputPath'."
        $buildArgs = @(
            "/t:WebPublish",
            "/p:WebPublishMethod=FileSystem",
            "/p:PublishUrl=""$OutputPath""",
            "/p:DeleteExistingFiles=false",
            "/p:MSDeployUseChecksum=true",
            "/m"
        )
        Invoke-MSBuild -MSBuildExecutablePath $MSBuildExecutablePath -ProjectOrSolutionFilePath $WebProjectFilePath -BuildArgs $buildArgs
    }
}

<#
 .SYNOPSIS
 Publishes a web project to the specified output directory using MSBuild and applies all relevant XDTs.
 
 .DESCRIPTION
 Publishes a web project to the specified output directory using MSBuild and applies all relevant XDTs. The XDTs are then deleted.
 Optional function parameters which are omitted, will be read from the settings found in "<solution root>\.pentia\user-settings.json".
 If no settings file exists, the user is prompted for input.
 
 .PARAMETER WebProjectFilePath
 Absolute or relative path of the web project file.
 
 .PARAMETER OutputPath
 Absolute or relative path of the output directory.
 
 .EXAMPLE
 Publish-ConfiguredWebProject -WebProjectFilePath "C:\Path\To\MyProject.csproj" -OutputPath "C:\Websites\MyWebsite" -BuildConfiguration "Debug"
 Publish a project, and apply all XDTs for the "Debug" configuration.
 
 .EXAMPLE
 Publish-ConfiguredWebProject -WebProjectFilePath "C:\Path\To\MyProject.csproj" -OutputPath "C:\Websites\MyWebsite" -BuildConfiguration "Debug" -MSBuildExecutablePath "C:\Path\To\MsBuild.exe"
 Publish a project, apply all XDTs for the "Debug" configuration, and use the specified MSBuild.exe.
 
 "./MyProject.csproj" | Publish-ConfiguredWebProject
 Publish the project "MyProject.csproj", using the settings found in "<solution root>\.pentia\user-settings.json".
 
 Get-WebProject | Publish-ConfiguredWebProject
 Retrive all web projects in or under the current directory, and publish them using the settings found in "<solution root>\.pentia\user-settings.json".
#>

function Publish-ConfiguredWebProject {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline)]
        [string]$WebProjectFilePath,

        [Parameter(Mandatory = $false)]
        [string]$WebrootOutputPath,

        [Parameter(Mandatory = $false)]
        [string]$DataOutputPath,

        [Parameter(Mandatory = $false)]
        [string]$BuildConfiguration
    )
    process {
        if (-not (Test-Path $WebProjectFilePath -PathType Leaf)) {
            throw "File path '$WebProjectFilePath' not found."
        }
        $solutionRootPath = $WebProjectFilePath | Find-SolutionRootPath
        $settings = Get-MergedParametersAndUserSettings -SolutionRootPath $solutionRootPath -WebrootOutputPath $WebrootOutputPath -DataOutputPath $DataOutputPath -BuildConfiguration $BuildConfiguration
        Publish-WebProject -WebProjectFilePath $WebProjectFilePath -OutputPath $settings.webrootOutputPath
        $projectDirectory = [System.IO.Path]::GetDirectoryName($WebProjectFilePath)
        Invoke-AllConfigurationTransforms -SolutionOrProjectRootPath $projectDirectory -WebrootOutputPath $settings.webrootOutputPath -BuildConfiguration $settings.buildConfiguration
        # Delete XDTs
        Get-ConfigurationTransformFile -SolutionRootPath $settings.webrootOutputPath | ForEach-Object { Remove-Item -Path $_ }
    }
}

function Find-SolutionRootPath {
    [CmdletBinding()]
    [OutputType([string])]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline)]
        [string]$SearchStartPath
    )
    process {
        if (-not (Test-Path $SearchStartPath)) {
            throw "Path '$SearchStartPath' not found."
        }
        $absoluteSearchStartPath = Resolve-Path $SearchStartPath
        if (Test-Path $absoluteSearchStartPath -PathType Leaf) {
            $directory = [System.IO.Path]::GetDirectoryName($absoluteSearchStartPath)
        }
        else {
            $directory = $absoluteSearchStartPath
        }

        $userSettingsFilePath = Get-UserSettingsFilePath -SolutionRootPath $directory
        if (Test-Path $userSettingsFilePath) {
            return "$directory"
        }

        $parent = Split-Path $directory -Parent
        if ([string]::IsNullOrWhiteSpace($parent)) {
            return $null
        }

        Find-SolutionRootPath -SearchStartPath $parent
    }
}

New-Alias -Name Publish-UnconfiguredWebProject -Value Publish-WebProject
Export-ModuleMember -Function Publish-WebProject, Publish-ConfiguredWebProject -Alias Publish-UnconfiguredWebProject