Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

151 wiersze
5.5KB

  1. <#
  2. Deploys the Purple Envelope Orders Site to the production IIS server.
  3. Flow:
  4. 1. Build a release locally (scripts\build-release.ps1) - a clean file tree with the
  5. production web.config swapped in, and dev-only files excluded via .gitattributes.
  6. 2. Zip it and scp the zip to the remote host.
  7. 3. scp scripts\deploy-iis-remote-apply.ps1 to the remote host and run it over ssh - it
  8. wipes the deploy directory, extracts the new release, points IIS at it, runs
  9. migrations, and restarts the site/app pool. The database and error log live outside
  10. the deploy directory, so the wipe never touches them.
  11. 4. Smoke-test a few routes over HTTPS from this machine.
  12. Usage:
  13. powershell -File scripts\deploy-iis.ps1
  14. powershell -File scripts\deploy-iis.ps1 -Ref master
  15. Remote target defaults to the "ssh user@host" line in scripts\deployinfo.txt (gitignored,
  16. not committed - create it locally, e.g.: ssh daniel_admin@kci-uluto-web).
  17. #>
  18. param(
  19. [string]$Ref = 'HEAD',
  20. [string]$RemoteTarget = '',
  21. [int]$RemotePort = 22,
  22. [string]$RemoteDir = 'C:\inetpub\wwwroot\Purple_Envelop_Order_Site',
  23. [string]$SiteName = 'PurpleEnvelopes',
  24. [string]$AppPool = 'PurpleEnvelopes',
  25. [string]$DbPath = 'C:\inetpub\data\webdata.accdb',
  26. [string]$BaseUrl = 'https://pe.kentcommunications.com/',
  27. [switch]$RunMigrations = $true,
  28. [string]$SshExe = 'ssh',
  29. [string]$ScpExe = 'scp'
  30. )
  31. $ErrorActionPreference = 'Stop'
  32. $repoRoot = Split-Path $PSScriptRoot -Parent
  33. function Ensure-Command {
  34. param([string]$Name)
  35. if(!(Get-Command $Name -ErrorAction SilentlyContinue)){
  36. throw "$Name not found on PATH"
  37. }
  38. }
  39. function Get-DefaultRemoteTarget {
  40. $infoPath = Join-Path $PSScriptRoot 'deployinfo.txt'
  41. if(!(Test-Path $infoPath)){ return '' }
  42. $sshLine = Get-Content $infoPath | Where-Object { $_ -match '^\s*ssh\s+' } | Select-Object -First 1
  43. if([string]::IsNullOrWhiteSpace($sshLine)){ return '' }
  44. return ($sshLine -replace '^\s*ssh\s+', '').Trim()
  45. }
  46. if([string]::IsNullOrWhiteSpace($RemoteTarget)){
  47. $RemoteTarget = Get-DefaultRemoteTarget
  48. }
  49. if([string]::IsNullOrWhiteSpace($RemoteTarget)){
  50. throw 'No -RemoteTarget given and scripts\deployinfo.txt not found. Create scripts\deployinfo.txt with a line like: ssh user@host'
  51. }
  52. Ensure-Command $SshExe
  53. Ensure-Command $ScpExe
  54. Ensure-Command git
  55. # --- 1. Build ---
  56. $outDir = Join-Path $repoRoot ('dist\release_' + (Get-Date -Format 'yyyyMMdd_HHmmss'))
  57. & (Join-Path $PSScriptRoot 'build-release.ps1') -Ref $Ref -OutDir $outDir
  58. if($LASTEXITCODE -ne 0 -and $LASTEXITCODE -ne $null){ throw 'build-release.ps1 failed' }
  59. # --- 2. Zip and ship it ---
  60. $zipName = 'release_' + (Get-Date -Format 'yyyyMMdd_HHmmss') + '.zip'
  61. $localZip = Join-Path (Split-Path $outDir -Parent) $zipName
  62. Compress-Archive -Path (Join-Path $outDir '*') -DestinationPath $localZip -Force
  63. $remoteZip = 'C:\Windows\Temp\' + $zipName
  64. $remoteApplyScript = Join-Path $PSScriptRoot 'deploy-iis-remote-apply.ps1'
  65. $remoteApplyDest = 'C:\Windows\Temp\deploy-iis-remote-apply.ps1'
  66. # Force a fall-through to password auth: if pubkey auth isn't set up (or an agent offers a
  67. # key the server doesn't accept), plain ssh/scp can otherwise fail outright with
  68. # "Permission denied (publickey)" instead of ever prompting for a password.
  69. $AuthOpts = @(
  70. '-o', 'PreferredAuthentications=publickey,keyboard-interactive,password',
  71. '-o', 'NumberOfPasswordPrompts=3'
  72. )
  73. Write-Host "Copying release to $RemoteTarget"
  74. & $ScpExe -P $RemotePort @AuthOpts $localZip "${RemoteTarget}:$remoteZip"
  75. if($LASTEXITCODE -ne 0){ throw 'scp of release zip failed - see scp output above for the actual reason' }
  76. & $ScpExe -P $RemotePort @AuthOpts $remoteApplyScript "${RemoteTarget}:$remoteApplyDest"
  77. if($LASTEXITCODE -ne 0){ throw 'scp of remote-apply script failed - see scp output above for the actual reason' }
  78. # --- 3. Apply on the remote host ---
  79. $remoteCommandParts = @(
  80. 'powershell', '-NoProfile', '-ExecutionPolicy', 'Bypass',
  81. '-File', ('"' + $remoteApplyDest + '"'),
  82. '-ZipPath', ('"' + $remoteZip + '"'),
  83. '-RemoteDir', ('"' + $RemoteDir + '"'),
  84. '-SiteName', ('"' + $SiteName + '"'),
  85. '-AppPool', ('"' + $AppPool + '"'),
  86. '-DbPath', ('"' + $DbPath + '"')
  87. )
  88. if($RunMigrations){ $remoteCommandParts += '-RunMigrations' }
  89. Write-Host "Applying release on $RemoteTarget"
  90. & $SshExe -p $RemotePort @AuthOpts $RemoteTarget ($remoteCommandParts -join ' ')
  91. if($LASTEXITCODE -ne 0){ throw 'remote apply failed - see ssh output above for the actual reason' }
  92. # --- 4. Local cleanup ---
  93. Remove-Item $localZip -ErrorAction SilentlyContinue
  94. Remove-Item -Recurse -Force $outDir -ErrorAction SilentlyContinue
  95. # --- 5. Smoke test ---
  96. Write-Host 'Smoke testing...'
  97. # /404 is the app's own not-found route - a 404 there is correct, not a failure.
  98. $checks = @(
  99. @{ Path = '/'; Expect = 200 },
  100. @{ Path = '/request-order'; Expect = 200 },
  101. @{ Path = '/404'; Expect = 404 }
  102. )
  103. $failed = $false
  104. foreach($check in $checks){
  105. $url = $BaseUrl.TrimEnd('/') + $check.Path
  106. try {
  107. $response = Invoke-WebRequest -UseBasicParsing -Uri $url -TimeoutSec 30
  108. $status = [int]$response.StatusCode
  109. } catch {
  110. if($_.Exception.Response){
  111. $status = [int]$_.Exception.Response.StatusCode
  112. } else {
  113. Write-Host ("FAIL " + $check.Path + ' -> request failed: ' + $_.Exception.Message)
  114. $failed = $true
  115. continue
  116. }
  117. }
  118. if($status -eq $check.Expect){
  119. Write-Host ("OK " + $check.Path + ' -> ' + $status)
  120. } else {
  121. Write-Host ("FAIL " + $check.Path + ' -> ' + $status + ' (expected ' + $check.Expect + ')')
  122. $failed = $true
  123. }
  124. }
  125. if($failed){
  126. throw 'Smoke test failed - see above'
  127. }
  128. Write-Host 'Deploy complete.'

Powered by TurnKey Linux.