<# Deploys the Purple Envelope Orders Site to the production IIS server. Flow: 1. Build a release locally (scripts\build-release.ps1) - a clean file tree with the production web.config swapped in, and dev-only files excluded via .gitattributes. 2. Zip it and scp the zip to the remote host. 3. scp scripts\deploy-iis-remote-apply.ps1 to the remote host and run it over ssh - it wipes the deploy directory, extracts the new release, points IIS at it, runs migrations, and restarts the site/app pool. The database and error log live outside the deploy directory, so the wipe never touches them. 4. Smoke-test a few routes over HTTPS from this machine. Usage: powershell -File scripts\deploy-iis.ps1 powershell -File scripts\deploy-iis.ps1 -Ref master Remote target defaults to the "ssh user@host" line in scripts\deployinfo.txt (gitignored, not committed - create it locally, e.g.: ssh daniel_admin@kci-uluto-web). #> param( [string]$Ref = 'HEAD', [string]$RemoteTarget = '', [int]$RemotePort = 22, [string]$RemoteDir = 'C:\inetpub\wwwroot\Purple_Envelop_Order_Site', [string]$SiteName = 'PurpleEnvelopes', [string]$AppPool = 'PurpleEnvelopes', [string]$DbPath = 'C:\inetpub\data\webdata.accdb', [string]$BaseUrl = 'https://pe.kentcommunications.com/', [switch]$RunMigrations = $true, [string]$SshExe = 'ssh', [string]$ScpExe = 'scp' ) $ErrorActionPreference = 'Stop' $repoRoot = Split-Path $PSScriptRoot -Parent function Ensure-Command { param([string]$Name) if(!(Get-Command $Name -ErrorAction SilentlyContinue)){ throw "$Name not found on PATH" } } function Get-DefaultRemoteTarget { $infoPath = Join-Path $PSScriptRoot 'deployinfo.txt' if(!(Test-Path $infoPath)){ return '' } $sshLine = Get-Content $infoPath | Where-Object { $_ -match '^\s*ssh\s+' } | Select-Object -First 1 if([string]::IsNullOrWhiteSpace($sshLine)){ return '' } return ($sshLine -replace '^\s*ssh\s+', '').Trim() } if([string]::IsNullOrWhiteSpace($RemoteTarget)){ $RemoteTarget = Get-DefaultRemoteTarget } if([string]::IsNullOrWhiteSpace($RemoteTarget)){ throw 'No -RemoteTarget given and scripts\deployinfo.txt not found. Create scripts\deployinfo.txt with a line like: ssh user@host' } Ensure-Command $SshExe Ensure-Command $ScpExe Ensure-Command git # --- 1. Build --- $outDir = Join-Path $repoRoot ('dist\release_' + (Get-Date -Format 'yyyyMMdd_HHmmss')) & (Join-Path $PSScriptRoot 'build-release.ps1') -Ref $Ref -OutDir $outDir if($LASTEXITCODE -ne 0 -and $LASTEXITCODE -ne $null){ throw 'build-release.ps1 failed' } # --- 2. Zip and ship it --- $zipName = 'release_' + (Get-Date -Format 'yyyyMMdd_HHmmss') + '.zip' $localZip = Join-Path (Split-Path $outDir -Parent) $zipName Compress-Archive -Path (Join-Path $outDir '*') -DestinationPath $localZip -Force $remoteZip = 'C:\Windows\Temp\' + $zipName $remoteApplyScript = Join-Path $PSScriptRoot 'deploy-iis-remote-apply.ps1' $remoteApplyDest = 'C:\Windows\Temp\deploy-iis-remote-apply.ps1' Write-Host "Copying release to $RemoteTarget" & $ScpExe -P $RemotePort $localZip "${RemoteTarget}:$remoteZip" if($LASTEXITCODE -ne 0){ throw 'scp of release zip failed' } & $ScpExe -P $RemotePort $remoteApplyScript "${RemoteTarget}:$remoteApplyDest" if($LASTEXITCODE -ne 0){ throw 'scp of remote-apply script failed' } # --- 3. Apply on the remote host --- $remoteCommandParts = @( 'powershell', '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', ('"' + $remoteApplyDest + '"'), '-ZipPath', ('"' + $remoteZip + '"'), '-RemoteDir', ('"' + $RemoteDir + '"'), '-SiteName', ('"' + $SiteName + '"'), '-AppPool', ('"' + $AppPool + '"'), '-DbPath', ('"' + $DbPath + '"') ) if($RunMigrations){ $remoteCommandParts += '-RunMigrations' } Write-Host "Applying release on $RemoteTarget" & $SshExe -p $RemotePort $RemoteTarget ($remoteCommandParts -join ' ') if($LASTEXITCODE -ne 0){ throw 'remote apply failed' } # --- 4. Local cleanup --- Remove-Item $localZip -ErrorAction SilentlyContinue Remove-Item -Recurse -Force $outDir -ErrorAction SilentlyContinue # --- 5. Smoke test --- Write-Host 'Smoke testing...' $paths = @('/', '/request-order', '/404') foreach($path in $paths){ $url = $BaseUrl.TrimEnd('/') + $path $response = Invoke-WebRequest -UseBasicParsing -Uri $url -TimeoutSec 30 Write-Host ("OK " + $path + ' -> ' + $response.StatusCode) } Write-Host 'Deploy complete.'