Преглед изворни кода

Fix build-release.ps1 dropping db/migrations from every release

The top-level prune step deleted the whole db/ folder before the
second step meant to keep db/migrations under it ever ran, so no
deploy has actually shipped migrations - the remote apply step was
running runMigrations.vbs against an empty migrations folder and
silently reporting nothing pending.

Also adds scripts/run-migrations-remote(-apply).ps1, a lighter
migrations-only counterpart to deploy-iis.ps1 for catching a
production schema up without redeploying app code - used just now to
patch prod after this bug meant it never received prior migrations.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
master
Daniel Covington пре 2 дана
родитељ
комит
1a517f606d
3 измењених фајлова са 149 додато и 1 уклоњено
  1. +1
    -1
      scripts/build-release.ps1
  2. +45
    -0
      scripts/run-migrations-remote-apply.ps1
  3. +103
    -0
      scripts/run-migrations-remote.ps1

+ 1
- 1
scripts/build-release.ps1 Прегледај датотеку

@@ -30,7 +30,7 @@ $ErrorActionPreference = 'Stop'
# the migration runner (+ its generator siblings, harmless to ship alongside it). Only
# db\migrations is kept under db - never db\webdata.accdb, even if something ever put a
# stray copy there.
$KeepTopLevel = @('app', 'core', 'public', 'scripts')
$KeepTopLevel = @('app', 'core', 'public', 'scripts', 'db')
$KeepUnderDb = @('migrations')

$repoRoot = Split-Path $PSScriptRoot -Parent


+ 45
- 0
scripts/run-migrations-remote-apply.ps1 Прегледај датотеку

@@ -0,0 +1,45 @@
<#
Runs ON the IIS server (invoked over SSH by scripts\run-migrations-remote.ps1). Not meant
to be run by hand except for troubleshooting.

Applies pending migrations to the live database WITHOUT touching the deployed site files:
- Copies the live public\web.config from RemoteDir into WorkDir, so runMigrations.vbs picks
up the real production connection string without it being hard-coded here.
- Runs `runMigrations.vbs status` (for the log) then `up` from WorkDir.
- Deletes WorkDir when done, win or lose - nothing is left behind on the server.
#>

param(
[Parameter(Mandatory = $true)][string]$RemoteDir,
[Parameter(Mandatory = $true)][string]$WorkDir
)

$ErrorActionPreference = 'Stop'

$liveWebConfig = Join-Path $RemoteDir 'public\web.config'
if(!(Test-Path $liveWebConfig)){
throw "No deployed web.config found at $liveWebConfig - is the site actually deployed at -RemoteDir?"
}

$workPublicDir = Join-Path $WorkDir 'public'
New-Item -ItemType Directory -Force -Path $workPublicDir | Out-Null
Copy-Item $liveWebConfig (Join-Path $workPublicDir 'web.config') -Force

try {
Push-Location $WorkDir
Write-Host '-- status before --'
& cscript.exe //nologo scripts\runMigrations.vbs status
if($LASTEXITCODE -ne 0){ throw 'runMigrations.vbs status failed - see output above' }

Write-Host ''
Write-Host '-- applying pending migrations --'
& cscript.exe //nologo scripts\runMigrations.vbs up
if($LASTEXITCODE -ne 0){ throw 'runMigrations.vbs up failed - see output above' }
} finally {
Pop-Location
Write-Host ''
Write-Host "Cleaning up $WorkDir"
Remove-Item -Recurse -Force $WorkDir -ErrorAction SilentlyContinue
}

Write-Host 'Remote migration apply complete.'

+ 103
- 0
scripts/run-migrations-remote.ps1 Прегледај датотеку

@@ -0,0 +1,103 @@
<#
Applies pending db\migrations\*.asp to the production database WITHOUT redeploying the
site - useful when the app code on the server is already current but the schema has
drifted (e.g. a migration was added after the last full deploy, or - as happened once -
build-release.ps1 was silently dropping db\migrations\ from every release).

Flow:
1. scp scripts\runMigrations.vbs and db\migrations\*.asp to a throwaway work folder in
C:\Windows\Temp on the remote host (never touches the live site's own deploy directory).
2. scp scripts\run-migrations-remote-apply.ps1 and run it over ssh - it copies the site's
already-deployed public\web.config into the work folder (so it uses the real production
connection string), runs `runMigrations.vbs status` then `up`, and deletes the work
folder afterward.

For a normal deploy (which also ships db\migrations and runs migrations automatically),
use scripts\deploy-iis.ps1 instead.

Usage:
powershell -File scripts\run-migrations-remote.ps1

Remote target defaults to the "ssh user@host" line in scripts\deployinfo.txt (gitignored),
same as deploy-iis.ps1.
#>

param(
[string]$RemoteTarget = '',
[int]$RemotePort = 22,
[string]$RemoteDir = 'C:\inetpub\wwwroot\Purple_Envelop_Order_Site',
[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

$AuthOpts = @(
'-o', 'PreferredAuthentications=publickey,keyboard-interactive,password',
'-o', 'NumberOfPasswordPrompts=3'
)

# --- 1. Stage a local bundle: scripts\runMigrations.vbs + db\migrations\*.asp ---
$stageDir = Join-Path $repoRoot ('dist\migrations_stage_' + (Get-Date -Format 'yyyyMMdd_HHmmss'))
New-Item -ItemType Directory -Force -Path (Join-Path $stageDir 'scripts') | Out-Null
New-Item -ItemType Directory -Force -Path (Join-Path $stageDir 'db\migrations') | Out-Null
Copy-Item (Join-Path $repoRoot 'scripts\runMigrations.vbs') (Join-Path $stageDir 'scripts\runMigrations.vbs') -Force
Copy-Item (Join-Path $repoRoot 'db\migrations\*.asp') (Join-Path $stageDir 'db\migrations') -Force

$remoteWorkDir = 'C:\Windows\Temp\pe-migrations-' + (Get-Date -Format 'yyyyMMdd_HHmmss')
$remoteApplyDest = 'C:\Windows\Temp\run-migrations-remote-apply.ps1'

# --- 2. Ship the bundle and the remote-apply script ---
# A single recursive source -> a destination that doesn't exist yet makes scp create that
# destination as a copy of the source, so this also creates $remoteWorkDir - no separate
# "ssh mkdir" step needed (the remote shell is cmd.exe, not PowerShell, so raw PowerShell
# commands passed straight through ssh don't run there without an explicit powershell.exe
# wrapper; simplest to just avoid needing one here).
Write-Host "Copying migrations bundle to $RemoteTarget"
& $ScpExe -P $RemotePort @AuthOpts -r $stageDir "${RemoteTarget}:$remoteWorkDir"
if($LASTEXITCODE -ne 0){ throw 'scp of migrations bundle failed - see scp output above for the actual reason' }

& $ScpExe -P $RemotePort @AuthOpts (Join-Path $PSScriptRoot 'run-migrations-remote-apply.ps1') "${RemoteTarget}:$remoteApplyDest"
if($LASTEXITCODE -ne 0){ throw 'scp of remote-apply script failed - see scp output above for the actual reason' }

Remove-Item -Recurse -Force $stageDir -ErrorAction SilentlyContinue

# --- 3. Apply on the remote host (also deletes $remoteWorkDir when done) ---
$remoteCommandParts = @(
'powershell', '-NoProfile', '-ExecutionPolicy', 'Bypass',
'-File', ('"' + $remoteApplyDest + '"'),
'-RemoteDir', ('"' + $RemoteDir + '"'),
'-WorkDir', ('"' + $remoteWorkDir + '"')
)

Write-Host "Applying pending migrations on $RemoteTarget"
& $SshExe -p $RemotePort @AuthOpts $RemoteTarget ($remoteCommandParts -join ' ')
if($LASTEXITCODE -ne 0){ throw 'remote migration apply failed - see ssh output above' }

Write-Host 'Done.'

Loading…
Откажи
Сачувај

Powered by TurnKey Linux.