您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

104 行
4.6KB

  1. <#
  2. Applies pending db\migrations\*.asp to the production database WITHOUT redeploying the
  3. site - useful when the app code on the server is already current but the schema has
  4. drifted (e.g. a migration was added after the last full deploy, or - as happened once -
  5. build-release.ps1 was silently dropping db\migrations\ from every release).
  6. Flow:
  7. 1. scp scripts\runMigrations.vbs and db\migrations\*.asp to a throwaway work folder in
  8. C:\Windows\Temp on the remote host (never touches the live site's own deploy directory).
  9. 2. scp scripts\run-migrations-remote-apply.ps1 and run it over ssh - it copies the site's
  10. already-deployed public\web.config into the work folder (so it uses the real production
  11. connection string), runs `runMigrations.vbs status` then `up`, and deletes the work
  12. folder afterward.
  13. For a normal deploy (which also ships db\migrations and runs migrations automatically),
  14. use scripts\deploy-iis.ps1 instead.
  15. Usage:
  16. powershell -File scripts\run-migrations-remote.ps1
  17. Remote target defaults to the "ssh user@host" line in scripts\deployinfo.txt (gitignored),
  18. same as deploy-iis.ps1.
  19. #>
  20. param(
  21. [string]$RemoteTarget = '',
  22. [int]$RemotePort = 22,
  23. [string]$RemoteDir = 'C:\inetpub\wwwroot\Purple_Envelop_Order_Site',
  24. [string]$SshExe = 'ssh',
  25. [string]$ScpExe = 'scp'
  26. )
  27. $ErrorActionPreference = 'Stop'
  28. $repoRoot = Split-Path $PSScriptRoot -Parent
  29. function Ensure-Command {
  30. param([string]$Name)
  31. if(!(Get-Command $Name -ErrorAction SilentlyContinue)){
  32. throw "$Name not found on PATH"
  33. }
  34. }
  35. function Get-DefaultRemoteTarget {
  36. $infoPath = Join-Path $PSScriptRoot 'deployinfo.txt'
  37. if(!(Test-Path $infoPath)){ return '' }
  38. $sshLine = Get-Content $infoPath | Where-Object { $_ -match '^\s*ssh\s+' } | Select-Object -First 1
  39. if([string]::IsNullOrWhiteSpace($sshLine)){ return '' }
  40. return ($sshLine -replace '^\s*ssh\s+', '').Trim()
  41. }
  42. if([string]::IsNullOrWhiteSpace($RemoteTarget)){
  43. $RemoteTarget = Get-DefaultRemoteTarget
  44. }
  45. if([string]::IsNullOrWhiteSpace($RemoteTarget)){
  46. throw 'No -RemoteTarget given and scripts\deployinfo.txt not found. Create scripts\deployinfo.txt with a line like: ssh user@host'
  47. }
  48. Ensure-Command $SshExe
  49. Ensure-Command $ScpExe
  50. $AuthOpts = @(
  51. '-o', 'PreferredAuthentications=publickey,keyboard-interactive,password',
  52. '-o', 'NumberOfPasswordPrompts=3'
  53. )
  54. # --- 1. Stage a local bundle: scripts\runMigrations.vbs + db\migrations\*.asp ---
  55. $stageDir = Join-Path $repoRoot ('dist\migrations_stage_' + (Get-Date -Format 'yyyyMMdd_HHmmss'))
  56. New-Item -ItemType Directory -Force -Path (Join-Path $stageDir 'scripts') | Out-Null
  57. New-Item -ItemType Directory -Force -Path (Join-Path $stageDir 'db\migrations') | Out-Null
  58. Copy-Item (Join-Path $repoRoot 'scripts\runMigrations.vbs') (Join-Path $stageDir 'scripts\runMigrations.vbs') -Force
  59. Copy-Item (Join-Path $repoRoot 'db\migrations\*.asp') (Join-Path $stageDir 'db\migrations') -Force
  60. $remoteWorkDir = 'C:\Windows\Temp\pe-migrations-' + (Get-Date -Format 'yyyyMMdd_HHmmss')
  61. $remoteApplyDest = 'C:\Windows\Temp\run-migrations-remote-apply.ps1'
  62. # --- 2. Ship the bundle and the remote-apply script ---
  63. # A single recursive source -> a destination that doesn't exist yet makes scp create that
  64. # destination as a copy of the source, so this also creates $remoteWorkDir - no separate
  65. # "ssh mkdir" step needed (the remote shell is cmd.exe, not PowerShell, so raw PowerShell
  66. # commands passed straight through ssh don't run there without an explicit powershell.exe
  67. # wrapper; simplest to just avoid needing one here).
  68. Write-Host "Copying migrations bundle to $RemoteTarget"
  69. & $ScpExe -P $RemotePort @AuthOpts -r $stageDir "${RemoteTarget}:$remoteWorkDir"
  70. if($LASTEXITCODE -ne 0){ throw 'scp of migrations bundle failed - see scp output above for the actual reason' }
  71. & $ScpExe -P $RemotePort @AuthOpts (Join-Path $PSScriptRoot 'run-migrations-remote-apply.ps1') "${RemoteTarget}:$remoteApplyDest"
  72. if($LASTEXITCODE -ne 0){ throw 'scp of remote-apply script failed - see scp output above for the actual reason' }
  73. Remove-Item -Recurse -Force $stageDir -ErrorAction SilentlyContinue
  74. # --- 3. Apply on the remote host (also deletes $remoteWorkDir when done) ---
  75. $remoteCommandParts = @(
  76. 'powershell', '-NoProfile', '-ExecutionPolicy', 'Bypass',
  77. '-File', ('"' + $remoteApplyDest + '"'),
  78. '-RemoteDir', ('"' + $RemoteDir + '"'),
  79. '-WorkDir', ('"' + $remoteWorkDir + '"')
  80. )
  81. Write-Host "Applying pending migrations on $RemoteTarget"
  82. & $SshExe -p $RemotePort @AuthOpts $RemoteTarget ($remoteCommandParts -join ' ')
  83. if($LASTEXITCODE -ne 0){ throw 'remote migration apply failed - see ssh output above' }
  84. Write-Host 'Done.'

Powered by TurnKey Linux.