<# Runs ON the IIS server (invoked over SSH by scripts\deploy-iis.ps1). Not meant to be run by hand except for troubleshooting a stuck deploy. - Stops the site/app pool - Wipes RemoteDir and re-extracts the release zip into it (safe: the DB and error log live outside RemoteDir, at DbPath/ErrorLogDir, so a full wipe never touches them) - Points IIS at RemoteDir\public - Ensures the app pool identity has modify rights on the persistent data folder - Runs pending migrations (32-bit cscript - ACE OLEDB is x86-only) - Restarts the site/app pool #> param( [Parameter(Mandatory = $true)][string]$ZipPath, [Parameter(Mandatory = $true)][string]$RemoteDir, [Parameter(Mandatory = $true)][string]$SiteName, [Parameter(Mandatory = $true)][string]$AppPool, [Parameter(Mandatory = $true)][string]$DbPath, [switch]$RunMigrations = $true ) $ErrorActionPreference = 'Stop' Import-Module WebAdministration if(!(Get-Website -Name $SiteName -ErrorAction SilentlyContinue)){ throw "IIS site '$SiteName' does not exist yet. Create the site and app pool once manually (or via a one-time setup script) before running this deploy." } if(!(Test-Path ('IIS:\AppPools\' + $AppPool))){ throw "App pool '$AppPool' does not exist yet. Create it once manually before running this deploy." } Write-Host "Stopping IIS site $SiteName and app pool $AppPool" try { Stop-Website -Name $SiteName } catch { } try { Stop-WebAppPool -Name $AppPool } catch { } if(Test-Path $RemoteDir){ Write-Host "Wiping $RemoteDir" Remove-Item -Recurse -Force (Join-Path $RemoteDir '*') -ErrorAction SilentlyContinue } else { New-Item -ItemType Directory -Force -Path $RemoteDir | Out-Null } Write-Host "Extracting $ZipPath -> $RemoteDir" Expand-Archive -Path $ZipPath -DestinationPath $RemoteDir -Force Remove-Item $ZipPath -ErrorAction SilentlyContinue $publicDir = Join-Path $RemoteDir 'public' if(!(Test-Path $publicDir)){ throw "No public\ folder in the extracted release - deploy aborted, site left stopped for inspection." } # Persistent data folder (DB + error log) - lives outside RemoteDir so it survives the wipe # above. Create it and grant the app pool identity modify rights. $dataDir = Split-Path $DbPath -Parent if(!(Test-Path $dataDir)){ New-Item -ItemType Directory -Force -Path $dataDir | Out-Null } $logDir = Join-Path $dataDir 'logs' if(!(Test-Path $logDir)){ New-Item -ItemType Directory -Force -Path $logDir | Out-Null } icacls $dataDir /grant ("IIS AppPool\" + $AppPool + ":(OI)(CI)(M)") /T | Out-Null Set-ItemProperty ('IIS:\Sites\' + $SiteName) -Name physicalPath -Value $publicDir Set-ItemProperty ('IIS:\Sites\' + $SiteName) -Name applicationPool -Value $AppPool if($RunMigrations){ Write-Host 'Running pending migrations' Push-Location $RemoteDir try { & C:\Windows\SysWOW64\cscript.exe //nologo scripts\runMigrations.vbs up if($LASTEXITCODE -ne 0){ throw 'runMigrations.vbs up failed - see output above' } } finally { Pop-Location } } Write-Host "Starting IIS site $SiteName and app pool $AppPool" if((Get-WebAppPoolState -Name $AppPool).Value -eq 'Started'){ Restart-WebAppPool -Name $AppPool } else { Start-WebAppPool -Name $AppPool } Start-Website $SiteName Write-Host 'Remote apply complete.'