Skip to content

Commit 7f7f84b

Browse files
baasith6cursoragent
andcommitted
Fix Jenkins deploy: SSH key ACLs, scp exit checks, auto-download installer tools.
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent c8381ad commit 7f7f84b

4 files changed

Lines changed: 98 additions & 11 deletions

File tree

Jenkinsfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pipeline {
6161
-VmHost ${params.VM_HOST} ^
6262
-VmUser ${params.VM_USER} ^
6363
-BackendUrl ${params.BACKEND_URL} ^
64-
-SshKeyPath %SSH_KEY%${extra}
64+
-SshKeyPath "${env.SSH_KEY}"${extra}
6565
"""
6666
}
6767
}

docs/JENKINS_DEPLOY.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,10 @@ powershell -ExecutionPolicy Bypass -File scripts/deploy-vm.ps1 -SkipInstaller
8888

8989
| Issue | Fix |
9090
|-------|-----|
91-
| SSH permission denied | Check `onevo-vm-ssh-key` credential; test `ssh azureuser@20.193.69.220` from Jenkins service account |
91+
| SSH permission denied | Re-check `onevo-vm-ssh-key` credential; deploy script copies the key with strict ACLs for OpenSSH on Windows |
9292
| GPU compose error | Keep `USE_GPU=false` on CPU VM |
93-
| Installer build fails | Install Inno Setup; run `scripts/build-installer.ps1` manually once |
93+
| Missing `ffmpeg.exe` | First build auto-downloads to `%ProgramData%\onevo\installer-tools\`; or run `scripts/ensure-installer-tools.ps1` once |
94+
| Installer build fails | Install Inno Setup 6 + PyInstaller; run `scripts/build-installer.ps1` manually once |
9495
| Backend unhealthy after deploy | SSH to VM: `cd /opt/onevo/app && docker compose logs backend --tail 50` |
9596

9697
## Related

scripts/deploy-vm.ps1

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,37 @@ $ErrorActionPreference = "Stop"
1414
$root = Split-Path -Parent $PSScriptRoot
1515
$tarball = Join-Path $env:TEMP "onevo-deploy.tar.gz"
1616

17-
function Get-SshArgs {
18-
if ($SshKeyPath -and (Test-Path $SshKeyPath)) {
19-
return @("-i", $SshKeyPath, "-o", "StrictHostKeyChecking=no")
17+
function Prepare-SshKey([string]$KeyPath) {
18+
if (-not $KeyPath -or -not (Test-Path $KeyPath)) {
19+
throw "SSH key not found (pass -SshKeyPath or configure default ~/.ssh key). Got: '$KeyPath'"
2020
}
21-
return @()
21+
$dest = Join-Path $env:TEMP ("onevo-deploy-key-{0}" -f [Guid]::NewGuid().ToString("N"))
22+
$raw = [IO.File]::ReadAllText($KeyPath) -replace "`r`n", "`n" -replace "`r", "`n"
23+
if (-not $raw.EndsWith("`n")) { $raw += "`n" }
24+
[IO.File]::WriteAllText($dest, $raw)
25+
$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
26+
& icacls $dest /inheritance:r /grant:r "${identity}:(R)" | Out-Null
27+
return $dest
2228
}
2329

24-
$sshArgs = Get-SshArgs
30+
function Invoke-Checked {
31+
param([string]$Label, [scriptblock]$Command)
32+
& $Command
33+
if ($LASTEXITCODE -ne 0) {
34+
throw "$Label failed (exit $LASTEXITCODE)"
35+
}
36+
}
37+
38+
function Get-SshArgs([string]$KeyPath) {
39+
if ($KeyPath -and (Test-Path $KeyPath)) {
40+
return @("-i", $KeyPath, "-o", "StrictHostKeyChecking=no", "-o", "BatchMode=yes")
41+
}
42+
return @("-o", "StrictHostKeyChecking=no", "-o", "BatchMode=yes")
43+
}
44+
45+
$preparedKey = $null
46+
if ($SshKeyPath) { $preparedKey = Prepare-SshKey $SshKeyPath }
47+
$sshArgs = Get-SshArgs $preparedKey
2548
$scpArgs = @($sshArgs) + @("${VmUser}@${VmHost}:")
2649

2750
Write-Host "==> Packaging app (excluding large artifacts)..."
@@ -51,16 +74,18 @@ try {
5174
}
5275

5376
Write-Host "==> Uploading to ${VmUser}@${VmHost}..."
54-
scp @sshArgs $tarball "${VmUser}@${VmHost}:/tmp/onevo-deploy.tar.gz"
77+
Invoke-Checked "SCP tarball" { scp @sshArgs $tarball "${VmUser}@${VmHost}:/tmp/onevo-deploy.tar.gz" }
5578

5679
$installerExe = $null
5780
if (-not $SkipInstaller) {
81+
Write-Host "==> Ensuring installer tools (ffmpeg, WinSW)..."
82+
& (Join-Path $root "scripts\ensure-installer-tools.ps1")
5883
Write-Host "==> Building Windows installer..."
5984
& (Join-Path $root "scripts\build-installer.ps1") -BackendUrl $BackendUrl -AllowHttp
6085
$installerExe = Get-ChildItem (Join-Path $root "connector\dist\ONEVO-Connector-Setup-*.exe") |
6186
Sort-Object LastWriteTime -Descending | Select-Object -First 1
6287
if (-not $installerExe) { throw "Installer EXE not found after build" }
63-
scp @sshArgs $installerExe.FullName "${VmUser}@${VmHost}:/tmp/$($installerExe.Name)"
88+
Invoke-Checked "SCP installer" { scp @sshArgs $installerExe.FullName "${VmUser}@${VmHost}:/tmp/$($installerExe.Name)" }
6489
$installerRemoteName = $installerExe.Name
6590
} else {
6691
$installerRemoteName = ""
@@ -95,7 +120,11 @@ docker compose ps --format 'table {{.Name}}\t{{.Status}}'
95120
"@ -replace "`r`n", "`n"
96121

97122
Write-Host "==> Running remote deploy..."
98-
ssh @sshArgs "${VmUser}@${VmHost}" $remoteScript
123+
try {
124+
Invoke-Checked "SSH deploy" { ssh @sshArgs "${VmUser}@${VmHost}" $remoteScript }
125+
} finally {
126+
if ($preparedKey -and (Test-Path $preparedKey)) { Remove-Item $preparedKey -Force -ErrorAction SilentlyContinue }
127+
}
99128

100129
Write-Host ""
101130
Write-Host "Deploy complete."

scripts/ensure-installer-tools.ps1

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Ensure connector/installer/tools has ffmpeg.exe and WinSW-x64.exe (gitignored).
2+
param(
3+
[string]$ToolsDir = "",
4+
[string]$CacheDir = ""
5+
)
6+
7+
$ErrorActionPreference = "Stop"
8+
$root = Split-Path -Parent $PSScriptRoot
9+
if (-not $ToolsDir) { $ToolsDir = Join-Path $root "connector\installer\tools" }
10+
if (-not $CacheDir) { $CacheDir = Join-Path $env:ProgramData "onevo\installer-tools" }
11+
12+
New-Item -ItemType Directory -Force -Path $ToolsDir, $CacheDir | Out-Null
13+
14+
$ffmpegDest = Join-Path $ToolsDir "ffmpeg.exe"
15+
$winswDest = Join-Path $ToolsDir "WinSW-x64.exe"
16+
$ffmpegCache = Join-Path $CacheDir "ffmpeg.exe"
17+
$winswCache = Join-Path $CacheDir "WinSW-x64.exe"
18+
19+
$ffmpegZipUrl = "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip"
20+
$winswUrl = "https://github.com/winsw/winsw/releases/download/v2.12.0/WinSW-x64.exe"
21+
22+
function Copy-IfMissing([string]$Source, [string]$Dest, [string]$Label) {
23+
if (Test-Path $Dest) { return }
24+
if (-not (Test-Path $Source)) { throw "Missing cached $Label at $Source" }
25+
Copy-Item -Force $Source $Dest
26+
Write-Host " Copied $Label -> $Dest"
27+
}
28+
29+
function Download-File([string]$Url, [string]$Dest) {
30+
Write-Host " Downloading $Url ..."
31+
Invoke-WebRequest -Uri $Url -OutFile $Dest -UseBasicParsing
32+
}
33+
34+
if (-not (Test-Path $ffmpegCache)) {
35+
$zipPath = Join-Path $CacheDir "ffmpeg-release-essentials.zip"
36+
Download-File $ffmpegZipUrl $zipPath
37+
$extractDir = Join-Path $CacheDir "ffmpeg-extract"
38+
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force }
39+
Expand-Archive -Path $zipPath -DestinationPath $extractDir
40+
$ffmpegBin = Get-ChildItem -Path $extractDir -Recurse -Filter "ffmpeg.exe" |
41+
Where-Object { $_.FullName -match '\\bin\\ffmpeg\.exe$' } |
42+
Select-Object -First 1
43+
if (-not $ffmpegBin) { throw "ffmpeg.exe not found inside downloaded archive" }
44+
Copy-Item -Force $ffmpegBin.FullName $ffmpegCache
45+
Remove-Item $extractDir -Recurse -Force
46+
Remove-Item $zipPath -Force
47+
Write-Host " Cached ffmpeg.exe"
48+
}
49+
50+
if (-not (Test-Path $winswCache)) {
51+
Download-File $winswUrl $winswCache
52+
Write-Host " Cached WinSW-x64.exe"
53+
}
54+
55+
Copy-IfMissing $ffmpegCache $ffmpegDest "ffmpeg.exe"
56+
Copy-IfMissing $winswCache $winswDest "WinSW-x64.exe"
57+
Write-Host "Installer tools ready in $ToolsDir"

0 commit comments

Comments
 (0)