diff --git a/scripts/deploy-ftp.ps1 b/scripts/deploy-ftp.ps1 new file mode 100644 index 0000000..51b2c05 --- /dev/null +++ b/scripts/deploy-ftp.ps1 @@ -0,0 +1,81 @@ +param( + [Parameter(Mandatory = $true)][string]$FtpHost, + [Parameter(Mandatory = $true)][string]$FtpUser, + [Parameter(Mandatory = $true)][string]$FtpPassword, + [string]$RemoteDir = "/httpdocs", + [string]$ProjectPath = "..\\GameList.csproj", + [string]$Configuration = "Release", + [string]$Runtime = "win-x64", + [string]$PublishDir = "..\\artifacts\\publish", + [switch]$SelfContained, + [string]$WinScpPath = "WinSCP.com" +) + +<# +.SYNOPSIS + Publish the app and mirror the output to an FTP-deployed IIS site. + +.DESCRIPTION + - Builds with dotnet publish. + - Drops app_offline.htm to pause the IIS site while files upload. + - Uses WinSCP (ftp) to mirror publish output into $RemoteDir (deletes extraneous remote files). + - Removes app_offline.htm when done. + +.PREREQS + - WinSCP.com available in PATH or pass -WinScpPath "C:\Path\To\WinSCP.com". + - FTP user must have write/delete rights to $RemoteDir. + - If you have RDP, you can still run this locally; the app_offline flag safely stops the app without touching the pool. + +.EXAMPLE + pwsh ./scripts/deploy-ftp.ps1 ` + -FtpHost "ftp.example.com" ` + -FtpUser "deploy" ` + -FtpPassword (Get-Content ./secrets/ftp.pwd -Raw) ` + -RemoteDir "/httpdocs" ` + -Configuration Release +#> + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +function Assert-Tool { + param([string]$Name) + if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) { + throw "Required tool '$Name' not found. Install it or point -WinScpPath to the executable." + } +} + +Assert-Tool "dotnet" +Assert-Tool $WinScpPath + +Write-Host "1) Publishing..." -ForegroundColor Cyan +New-Item -ItemType Directory -Force -Path $PublishDir | Out-Null + +$publishArgs = @("publish", $ProjectPath, "-c", $Configuration, "-r", $Runtime, "-o", $PublishDir) +if (-not $SelfContained) { $publishArgs += "--self-contained=false" } +dotnet @publishArgs + +$offlineFile = Join-Path $PublishDir "app_offline.htm" +"

Updating…

Back in a moment.

" | Set-Content -Encoding UTF8 $offlineFile + +Write-Host "2) Syncing via WinSCP (FTP mirror with delete)..." -ForegroundColor Cyan +$tempScript = New-TemporaryFile +@" +option batch continue +option confirm off +open ftp://$($FtpUser):$($FtpPassword.Replace("`n","").Replace("`r",""))@$FtpHost +lcd $PublishDir +cd $RemoteDir +put app_offline.htm +synchronize remote . -delete +rm app_offline.htm +exit +"@ | Set-Content -Path $tempScript -Encoding UTF8 + +& $WinScpPath "/ini=nul" "/script=$tempScript" + +Remove-Item $tempScript -ErrorAction SilentlyContinue + +Write-Host "`nDone. If you want to explicitly bounce the app pool while on RDP:" -ForegroundColor Green +Write-Host " Import-Module WebAdministration" +Write-Host " Stop-WebAppPool 'YourAppPoolName'; Start-WebAppPool 'YourAppPoolName'" -ForegroundColor DarkGray