139 lines
4.0 KiB
PowerShell
139 lines
4.0 KiB
PowerShell
# Deploy prebuilt MyOffice artifacts to a Proxmox CT (or any Linux host).
|
|
# Usage:
|
|
# .\proxmox\publish.ps1
|
|
# .\proxmox\deploy.ps1 -TargetHost 192.168.1.120
|
|
# .\proxmox\deploy.ps1 -TargetHost 192.168.1.120 -User root -RemotePath /opt/myoffice/api
|
|
#
|
|
# Requires OpenSSH client (ssh/scp). Prefers rsync if available (Git Bash / WSL / cwRsync).
|
|
# Preserves CT-owned appsettings.Production.json / appsettings.shared.Production.json.
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[Alias('ComputerName', 'Host')]
|
|
[string]$TargetHost,
|
|
|
|
[string]$User = 'root',
|
|
|
|
[Alias('Path')]
|
|
[string]$RemotePath = '/opt/myoffice/api',
|
|
|
|
[string]$Service = 'myoffice-api',
|
|
|
|
[string]$PublishDir = '',
|
|
|
|
[int]$Port = 22
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
$repoRoot = Resolve-Path (Join-Path $scriptDir '..')
|
|
|
|
if (-not $PublishDir) {
|
|
$PublishDir = Join-Path $repoRoot '_Published'
|
|
}
|
|
if (-not (Test-Path $PublishDir)) {
|
|
throw "Publish folder not found: $PublishDir — run .\proxmox\publish.ps1 first."
|
|
}
|
|
if (-not (Test-Path (Join-Path $PublishDir 'MyOffice.Web.dll'))) {
|
|
throw "MyOffice.Web.dll missing in $PublishDir — run .\proxmox\publish.ps1 first."
|
|
}
|
|
|
|
$ctOwnedSettings = @(
|
|
'appsettings.Production.json',
|
|
'appsettings.shared.Production.json'
|
|
)
|
|
|
|
$remote = "${User}@${TargetHost}"
|
|
$sshTarget = @('-p', "$Port", $remote)
|
|
$scpTarget = @('-P', "$Port")
|
|
|
|
function Invoke-Remote {
|
|
param([Parameter(Mandatory = $true)][string]$Command)
|
|
& ssh @sshTarget $Command
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "ssh failed (exit $LASTEXITCODE): $Command"
|
|
}
|
|
}
|
|
|
|
function Test-Rsync {
|
|
return [bool](Get-Command rsync -ErrorAction SilentlyContinue)
|
|
}
|
|
|
|
function ConvertTo-RsyncPath([string]$WindowsPath) {
|
|
$p = ($WindowsPath.TrimEnd('\', '/') + '/') -replace '\\', '/'
|
|
if ($p -match '^[A-Za-z]:') {
|
|
$drive = $p.Substring(0, 1).ToLower()
|
|
$p = "/$drive" + $p.Substring(2)
|
|
}
|
|
return $p
|
|
}
|
|
|
|
Write-Host "-----------------------------------------------"
|
|
Write-Host "Deploy $PublishDir -> ${remote}:${RemotePath}"
|
|
Write-Host "-----------------------------------------------"
|
|
|
|
Write-Host "Stopping $Service..."
|
|
Invoke-Remote "systemctl stop $Service || true"
|
|
|
|
Invoke-Remote "mkdir -p '$RemotePath'"
|
|
|
|
$rsync = Test-Rsync
|
|
if ($rsync) {
|
|
Write-Host "Copying with rsync (preserve CT Production appsettings)..."
|
|
$rsyncSrc = ConvertTo-RsyncPath $PublishDir
|
|
$rsyncArgs = @(
|
|
'-r', '--info=progress2',
|
|
'--exclude', 'appsettings.Production.json',
|
|
'--exclude', 'appsettings.shared.Production.json',
|
|
'-e', "ssh -p $Port",
|
|
$rsyncSrc,
|
|
"${remote}:${RemotePath}/"
|
|
)
|
|
& rsync @rsyncArgs
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "rsync failed with exit code $LASTEXITCODE"
|
|
}
|
|
}
|
|
else {
|
|
Write-Host "rsync not found — using tar+scp fallback..."
|
|
$staging = Join-Path $env:TEMP ("myoffice-deploy-" + [guid]::NewGuid().ToString('N'))
|
|
New-Item -ItemType Directory -Path $staging | Out-Null
|
|
try {
|
|
Get-ChildItem -Path $PublishDir -Force | Where-Object {
|
|
$_.Name -notin $ctOwnedSettings
|
|
} | ForEach-Object {
|
|
Copy-Item $_.FullName -Destination $staging -Recurse -Force
|
|
}
|
|
|
|
$tarLocal = Join-Path $env:TEMP 'myoffice-deploy.tar.gz'
|
|
if (Test-Path $tarLocal) { Remove-Item -Force $tarLocal }
|
|
Push-Location $staging
|
|
try {
|
|
tar -czf $tarLocal *
|
|
if ($LASTEXITCODE -ne 0) { throw "tar create failed" }
|
|
}
|
|
finally {
|
|
Pop-Location
|
|
}
|
|
|
|
& scp @scpTarget $tarLocal "${remote}:/tmp/myoffice-deploy.tar.gz"
|
|
if ($LASTEXITCODE -ne 0) { throw "scp failed" }
|
|
|
|
Invoke-Remote "tar -xzf /tmp/myoffice-deploy.tar.gz -C '$RemotePath' && rm -f /tmp/myoffice-deploy.tar.gz"
|
|
}
|
|
finally {
|
|
Remove-Item -Recurse -Force $staging -ErrorAction SilentlyContinue
|
|
Remove-Item -Force (Join-Path $env:TEMP 'myoffice-deploy.tar.gz') -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
|
|
Write-Host "Starting $Service..."
|
|
Invoke-Remote "systemctl start $Service"
|
|
Invoke-Remote "systemctl --no-pager --full status $Service || true"
|
|
|
|
Write-Host ""
|
|
Write-Host "Deployed to http://${TargetHost}:9100 (or your nginx public URL)"
|
|
Write-Host ""
|