You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
5.2KB

  1. <#
  2. Runs ON the IIS server (invoked over SSH by scripts\deploy-iis.ps1). Not meant to be run
  3. by hand except for troubleshooting a stuck deploy.
  4. - Stops the site/app pool
  5. - Wipes RemoteDir and re-extracts the release zip into it (safe: the DB and error log
  6. live outside RemoteDir, at DbPath/ErrorLogDir, so a full wipe never touches them)
  7. - Points IIS at RemoteDir\public
  8. - Ensures the app pool identity has modify rights on the persistent data folder
  9. - Runs pending migrations (32-bit cscript - ACE OLEDB is x86-only)
  10. - Restarts the site/app pool
  11. #>
  12. param(
  13. [Parameter(Mandatory = $true)][string]$ZipPath,
  14. [Parameter(Mandatory = $true)][string]$RemoteDir,
  15. [Parameter(Mandatory = $true)][string]$SiteName,
  16. [Parameter(Mandatory = $true)][string]$AppPool,
  17. [Parameter(Mandatory = $true)][string]$DbPath,
  18. [string]$AdminSiteName = '',
  19. [string]$AdminAppPool = '',
  20. [switch]$RunMigrations = $true
  21. )
  22. $ErrorActionPreference = 'Stop'
  23. Import-Module WebAdministration
  24. if(!(Get-Website -Name $SiteName -ErrorAction SilentlyContinue)){
  25. 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."
  26. }
  27. if(!(Test-Path ('IIS:\AppPools\' + $AppPool))){
  28. throw "App pool '$AppPool' does not exist yet. Create it once manually before running this deploy."
  29. }
  30. Write-Host "Stopping IIS site $SiteName and app pool $AppPool"
  31. try { Stop-Website -Name $SiteName } catch { }
  32. try { Stop-WebAppPool -Name $AppPool } catch { }
  33. # The admin site's physical path may already point inside RemoteDir (e.g. RemoteDir\public-admin)
  34. # from a previous deploy - if it's left running, IIS holds those files open and the wipe below
  35. # fails with "Access is denied". Stop it up front, alongside the public site, not after.
  36. if(![string]::IsNullOrWhiteSpace($AdminSiteName) -and (Get-Website -Name $AdminSiteName -ErrorAction SilentlyContinue)){
  37. Write-Host "Stopping IIS admin site $AdminSiteName"
  38. try { Stop-Website -Name $AdminSiteName } catch { }
  39. if(![string]::IsNullOrWhiteSpace($AdminAppPool)){
  40. try { Stop-WebAppPool -Name $AdminAppPool } catch { }
  41. }
  42. }
  43. if(Test-Path $RemoteDir){
  44. Write-Host "Wiping $RemoteDir"
  45. Remove-Item -Recurse -Force (Join-Path $RemoteDir '*') -ErrorAction SilentlyContinue
  46. } else {
  47. New-Item -ItemType Directory -Force -Path $RemoteDir | Out-Null
  48. }
  49. Write-Host "Extracting $ZipPath -> $RemoteDir"
  50. Expand-Archive -Path $ZipPath -DestinationPath $RemoteDir -Force
  51. Remove-Item $ZipPath -ErrorAction SilentlyContinue
  52. $publicDir = Join-Path $RemoteDir 'public'
  53. if(!(Test-Path $publicDir)){
  54. throw "No public\ folder in the extracted release - deploy aborted, site left stopped for inspection."
  55. }
  56. # Persistent data folder (DB + error log) - lives outside RemoteDir so it survives the wipe
  57. # above. Create it and grant the app pool identity modify rights.
  58. $dataDir = Split-Path $DbPath -Parent
  59. if(!(Test-Path $dataDir)){
  60. New-Item -ItemType Directory -Force -Path $dataDir | Out-Null
  61. }
  62. $logDir = Join-Path $dataDir 'logs'
  63. if(!(Test-Path $logDir)){
  64. New-Item -ItemType Directory -Force -Path $logDir | Out-Null
  65. }
  66. icacls $dataDir /grant ("IIS AppPool\" + $AppPool + ":(OI)(CI)(M)") /T | Out-Null
  67. Set-ItemProperty ('IIS:\Sites\' + $SiteName) -Name physicalPath -Value $publicDir
  68. Set-ItemProperty ('IIS:\Sites\' + $SiteName) -Name applicationPool -Value $AppPool
  69. # This server has the 64-bit Access Database Engine (ACE OLEDB) installed, unlike the local
  70. # dev machine, which needs the 32-bit one - so the app pool stays 64-bit here.
  71. Set-ItemProperty ('IIS:\AppPools\' + $AppPool) -Name enable32BitAppOnWin64 -Value $false
  72. # --- Admin site ---
  73. $adminPublicDir = Join-Path $RemoteDir 'public-admin'
  74. if(![string]::IsNullOrWhiteSpace($AdminSiteName) -and (Test-Path $adminPublicDir)){
  75. if(!(Get-Website -Name $AdminSiteName -ErrorAction SilentlyContinue)){
  76. throw "IIS admin site '$AdminSiteName' does not exist yet. Create the site and app pool once manually before running this deploy."
  77. }
  78. Write-Host "Configuring admin site $AdminSiteName"
  79. if(![string]::IsNullOrWhiteSpace($AdminAppPool)){
  80. Set-ItemProperty ('IIS:\Sites\' + $AdminSiteName) -Name applicationPool -Value $AdminAppPool
  81. Set-ItemProperty ('IIS:\AppPools\' + $AdminAppPool) -Name enable32BitAppOnWin64 -Value $false
  82. icacls $dataDir /grant ("IIS AppPool\" + $AdminAppPool + ":(OI)(CI)(M)") /T | Out-Null
  83. }
  84. Set-ItemProperty ('IIS:\Sites\' + $AdminSiteName) -Name physicalPath -Value $adminPublicDir
  85. }
  86. if($RunMigrations){
  87. Write-Host 'Running pending migrations'
  88. Push-Location $RemoteDir
  89. try {
  90. & cscript.exe //nologo scripts\runMigrations.vbs up
  91. if($LASTEXITCODE -ne 0){ throw 'runMigrations.vbs up failed - see output above' }
  92. } finally {
  93. Pop-Location
  94. }
  95. }
  96. Write-Host "Starting IIS site $SiteName and app pool $AppPool"
  97. if((Get-WebAppPoolState -Name $AppPool).Value -eq 'Started'){
  98. Restart-WebAppPool -Name $AppPool
  99. } else {
  100. Start-WebAppPool -Name $AppPool
  101. }
  102. Start-Website $SiteName
  103. if(![string]::IsNullOrWhiteSpace($AdminSiteName)){
  104. if(![string]::IsNullOrWhiteSpace($AdminAppPool)){
  105. if((Get-WebAppPoolState -Name $AdminAppPool).Value -eq 'Started'){
  106. Restart-WebAppPool -Name $AdminAppPool
  107. } else {
  108. Start-WebAppPool -Name $AdminAppPool
  109. }
  110. }
  111. Start-Website $AdminSiteName
  112. }
  113. Write-Host 'Remote apply complete.'

Powered by TurnKey Linux.