Files
clean-copy/release.ps1
T

234 lines
6.0 KiB
PowerShell
Raw Normal View History

param(
[Parameter(Mandatory = $true)]
[string]$Version
)
$ErrorActionPreference = "Stop"
$VpsHost = "bit_bastion"
$VpsDeployDir = "/home/stevan/cleancopy.stevanfreeborn.com"
$ContainerName = "clean-copy"
$ImageName = "clean-copy-server"
if ($Version -notmatch '^\d+\.\d+\.\d+$') {
Write-Error "Invalid version format '$Version'. Expected semver (e.g. 0.2.0)"
exit 1
}
Write-Host "=== CleanCopy Release v$Version ===" -ForegroundColor Cyan
Write-Host ""
try {
docker info 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0) {
throw
}
} catch {
Write-Error "Docker Desktop is not running. Start it and try again."
exit 1
}
Write-Host "[1/11] Checking SSH connectivity..." -ForegroundColor Yellow
try {
ssh $VpsHost "echo ok" 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0) {
throw
}
} catch {
Write-Error "Cannot SSH into $VpsHost. Check your SSH config."
exit 1
}
Write-Host " OK" -ForegroundColor Green
Write-Host "[2/11] Running tests..." -ForegroundColor Yellow
cargo test --workspace
if ($LASTEXITCODE -ne 0) {
Write-Error "Rust tests failed";
exit 1
}
Push-Location app
npm test
if ($LASTEXITCODE -ne 0) { Pop-Location; Write-Error "Frontend tests failed"; exit 1 }
Pop-Location
Write-Host " All tests passed" -ForegroundColor Green
Write-Host "[3/11] Bumping versions to $Version..." -ForegroundColor Yellow
$cargoFiles = @(
"app/src-tauri/Cargo.toml",
"shared/Cargo.toml",
"server/Cargo.toml"
)
foreach ($file in $cargoFiles) {
$content = Get-Content $file -Raw
$content = $content -replace '(?m)^version = ".*"', "version = `"$Version`""
Set-Content $file $content -NoNewline
}
$pkg = Get-Content "app/package.json" -Raw
$pkg = $pkg -replace '"version":\s*"[^"]*"', "`"version`": `"$Version`""
Set-Content "app/package.json" $pkg -NoNewline
$tauri = Get-Content "app/src-tauri/tauri.conf.json" -Raw
$tauri = $tauri -replace '"version":\s*"[^"]*"', "`"version`": `"$Version`""
Set-Content "app/src-tauri/tauri.conf.json" $tauri -NoNewline
Write-Host " Updated: Cargo.toml (x3), package.json, tauri.conf.json" -ForegroundColor Green
Write-Host "[4/11] Creating git commit and tag..." -ForegroundColor Yellow
git add -A
git commit -m "release: v$Version"
if ($LASTEXITCODE -ne 0) {
Write-Error "Git commit failed";
exit 1
}
git tag "v$Version"
if ($LASTEXITCODE -ne 0) {
Write-Error "Git tag failed";
exit 1
}
Write-Host " Tagged v$Version" -ForegroundColor Green
Write-Host "[5/11] Building Tauri app..." -ForegroundColor Yellow
Push-Location app
npx tauri build
if ($LASTEXITCODE -ne 0) {
Pop-Location; Write-Error "Tauri build failed";
exit 1
}
Pop-Location
Write-Host " Built clean-copy.exe + MSI" -ForegroundColor Green
Write-Host "[6/11] Organizing release artifacts..." -ForegroundColor Yellow
$releaseDir = "server/releases/$Version/x86_64"
New-Item -ItemType Directory -Force -Path $releaseDir | Out-Null
$exeSrc = "app/src-tauri/target/release/clean-copy.exe"
$msiSrc = Get-ChildItem "app/src-tauri/target/release/bundle/msi/*.msi" | Select-Object -First 1
if (-not (Test-Path $exeSrc)) {
Write-Error "Expected $exeSrc not found"
exit 1
}
Copy-Item $exeSrc "$releaseDir/clean-copy-$Version.exe"
Write-Host " Copied clean-copy-$Version.exe" -ForegroundColor Green
if ($msiSrc) {
Copy-Item $msiSrc.FullName "$releaseDir/$($msiSrc.Name)"
Write-Host " Copied $($msiSrc.Name)" -ForegroundColor Green
} else {
Write-Host " Warning: No MSI found" -ForegroundColor Yellow
}
Write-Host "[7/11] Building Docker image for linux/arm64..." -ForegroundColor Yellow
docker buildx build --platform linux/arm64 -t "${ImageName}:${Version}" -t "${ImageName}:latest" -f server/Dockerfile . --load
if ($LASTEXITCODE -ne 0) {
Write-Error "Docker build failed";
exit 1
}
Write-Host " Built ${ImageName}:${Version}" -ForegroundColor Green
Write-Host "[8/11] Saving Docker image to tarball..." -ForegroundColor Yellow
$tarball = "${ImageName}-${Version}.tar"
docker save "${ImageName}:${Version}" -o $tarball
if ($LASTEXITCODE -ne 0) {
Write-Error "Docker save failed";
exit 1
}
$tarSize = [math]::Round((Get-Item $tarball).Length / 1MB, 1)
Write-Host " Saved $tarball ($tarSize MB)" -ForegroundColor Green
Write-Host "[9/11] Transferring files to VPS..." -ForegroundColor Yellow
scp $tarball "${VpsHost}:${VpsDeployDir}/"
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to transfer tarball"; exit 1
}
Write-Host " Transferred $tarball" -ForegroundColor Green
ssh $VpsHost "mkdir -p ${VpsDeployDir}/data/releases/${Version}/x86_64"
scp -r "${releaseDir}/*" "${VpsHost}:${VpsDeployDir}/data/releases/${Version}/x86_64/"
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to transfer release artifacts";
exit 1
}
Write-Host " Transferred release artifacts" -ForegroundColor Green
Write-Host "[10/11] Deploying on VPS..." -ForegroundColor Yellow
$deployScript = @"
cd ${VpsDeployDir} && \
docker load -i ${ImageName}-${Version}.tar && \
docker stop ${ContainerName} 2>/dev/null; docker rm ${ContainerName} 2>/dev/null; \
docker run -d \
--name ${ContainerName} \
-p 3000:3000 \
-v ${VpsDeployDir}/data:/data \
--env-file ${VpsDeployDir}/.env \
--restart unless-stopped \
${ImageName}:${Version} && \
rm ${ImageName}-${Version}.tar && \
echo "DEPLOY_OK"
"@
$result = ssh $VpsHost $deployScript
if ($result -notmatch "DEPLOY_OK") {
Write-Error "Deployment failed. Output: $result"
exit 1
}
Write-Host " Container $ContainerName started" -ForegroundColor Green
Write-Host "[11/11] Cleaning up local tarball..." -ForegroundColor Yellow
Remove-Item $tarball -Force
Write-Host " Removed $tarball" -ForegroundColor Green
Write-Host ""
Write-Host "=== Release Complete ===" -ForegroundColor Cyan
Write-Host " Version: v$Version"
Write-Host " Image: ${ImageName}:${Version}"
Write-Host " Container: $ContainerName (running)"
Write-Host " Deploy dir: ${VpsDeployDir}"
Write-Host ""
Write-Host " Next: git push && git push --tags" -ForegroundColor Yellow