be70809bf0
Co-authored-by: Cursor <cursoragent@cursor.com>
104 lines
3.5 KiB
PowerShell
104 lines
3.5 KiB
PowerShell
# Deploy Idle Fantasy Save Viewer to production.
|
|
# Usage (from repo root): .\scripts\deploy.ps1
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
function Write-Step([string]$Message) {
|
|
Write-Host "==> $Message"
|
|
}
|
|
|
|
function Fail([string]$Message) {
|
|
Write-Error $Message
|
|
exit 1
|
|
}
|
|
|
|
function Invoke-RemoteDeploy {
|
|
param(
|
|
[string[]]$SshOptions,
|
|
[string]$TargetHost,
|
|
[string]$ScriptPath,
|
|
[string]$RemoteDir,
|
|
[string]$Branch,
|
|
[string]$ExpectedSha,
|
|
[string]$HealthUrl,
|
|
[int]$HealthRetries,
|
|
[int]$HealthInterval
|
|
)
|
|
|
|
if (-not (Get-Command scp -ErrorAction SilentlyContinue)) {
|
|
Fail "scp not found. Install OpenSSH client or use Git Bash with scripts/deploy.sh"
|
|
}
|
|
|
|
$remoteScript = "/tmp/if-viewer-deploy-$PID.sh"
|
|
$quoted = @(
|
|
$RemoteDir,
|
|
$Branch,
|
|
$ExpectedSha,
|
|
$HealthUrl,
|
|
"$HealthRetries",
|
|
"$HealthInterval"
|
|
) | ForEach-Object { "'" + ($_ -replace "'", "'\\''") + "'" }
|
|
|
|
$remoteArgs = $quoted -join " "
|
|
$remoteRun = "bash $remoteScript $remoteArgs; rc=`$?; rm -f $remoteScript; exit `$rc"
|
|
|
|
& scp @SshOptions $ScriptPath "${TargetHost}:${remoteScript}"
|
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
|
|
|
& ssh @SshOptions $TargetHost $remoteRun
|
|
return $LASTEXITCODE
|
|
}
|
|
|
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
$RemoteScriptPath = Join-Path $ScriptDir "deploy-remote.sh"
|
|
|
|
$RepoRoot = git rev-parse --show-toplevel 2>$null
|
|
if (-not $RepoRoot) { Fail "Not inside a git repository." }
|
|
Set-Location $RepoRoot
|
|
|
|
# On Windows use native OpenSSH (same client as interactive "ssh" in PowerShell).
|
|
# Git Bash ships its own ssh/known_hosts and breaks host key verification.
|
|
$OnWindows = ($env:OS -match "Windows") -or ($PSVersionTable.PSPlatform -eq "Win32NT")
|
|
if (-not $OnWindows -and (Get-Command bash -ErrorAction SilentlyContinue)) {
|
|
& bash "./scripts/deploy.sh"
|
|
exit $LASTEXITCODE
|
|
}
|
|
|
|
$DeployHost = if ($env:DEPLOY_HOST) { $env:DEPLOY_HOST } else { "root@10.0.0.5" }
|
|
$DeployDir = if ($env:DEPLOY_DIR) { $env:DEPLOY_DIR } else { "/opt/apps/Idle-Fantasy-Save-Viewer" }
|
|
$HealthUrl = if ($env:DEPLOY_HEALTH_URL) { $env:DEPLOY_HEALTH_URL } else { "http://127.0.0.1:5000/" }
|
|
$HealthRetries = if ($env:DEPLOY_HEALTH_RETRIES) { [int]$env:DEPLOY_HEALTH_RETRIES } else { 20 }
|
|
$HealthInterval = if ($env:DEPLOY_HEALTH_INTERVAL) { [int]$env:DEPLOY_HEALTH_INTERVAL } else { 2 }
|
|
$SshOpts = @("-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new")
|
|
|
|
$Branch = git rev-parse --abbrev-ref HEAD
|
|
if ($Branch -eq "HEAD") { Fail "Detached HEAD - checkout a branch before deploying." }
|
|
|
|
$Status = git status --porcelain
|
|
if ($Status) { Fail "Working tree is not clean. Commit or stash changes before deploying." }
|
|
|
|
$Upstream = git rev-parse --abbrev-ref --symbolic-full-name "@{u}" 2>$null
|
|
if (-not $Upstream) { Fail "Branch '$Branch' has no upstream. Run: git push -u origin $Branch" }
|
|
|
|
$LocalSha = git rev-parse HEAD
|
|
Write-Step "Local branch: $Branch ($LocalSha)"
|
|
Write-Step "Pushing $Branch to origin..."
|
|
git push origin $Branch
|
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
|
|
|
Write-Step "Deploying to ${DeployHost}:${DeployDir}"
|
|
|
|
$exitCode = Invoke-RemoteDeploy `
|
|
-SshOptions $SshOpts `
|
|
-TargetHost $DeployHost `
|
|
-ScriptPath $RemoteScriptPath `
|
|
-RemoteDir $DeployDir `
|
|
-Branch $Branch `
|
|
-ExpectedSha $LocalSha `
|
|
-HealthUrl $HealthUrl `
|
|
-HealthRetries $HealthRetries `
|
|
-HealthInterval $HealthInterval
|
|
if ($exitCode -ne 0) { exit $exitCode }
|
|
|
|
Write-Step "Deployment finished successfully."
|