Refactor Windows deployment scripts: unify build and management tools

Major improvements to deployment workflow with unified scripts and interactive menus.

New unified scripts:
- Build-ROA2WEB.ps1: Interactive menu for building all components
  * Isolated temp directory for frontend builds (prevents WSL node_modules corruption)
  * Automatic devDependencies installation (fixes Vite not found issue)
  * Auto-cleanup after build
  * Supports both interactive menu and non-interactive CLI

- ROA2WEB-Console.ps1: All-in-one deployment and management console
  * Interactive menus for deploy, manage services, and status checks
  * Automatic backups before deployment
  * Smart dependency updates (only if requirements.txt changed)
  * Health checks after service operations
  * Color-coded status output
  * Both interactive and non-interactive modes

Removed deprecated scripts (replaced by unified tools):
- Build-Frontend.ps1 → Use Build-ROA2WEB.ps1 -Component Frontend
- Build-TelegramBot.ps1 → Use Build-ROA2WEB.ps1 -Component TelegramBot
- Deploy-ROA2WEB.ps1 → Use ROA2WEB-Console.ps1 [Deploy menu]
- Deploy-TelegramBot.ps1 → Use ROA2WEB-Console.ps1 [Deploy menu]
- Manage-ROA2WEB.ps1 → Use ROA2WEB-Console.ps1 [Manage menu]

Updated documentation:
- Complete rewrite of scripts/README.md
- Clear workflow guides for first-time deployment and updates
- Comparison table v1.0 vs v2.0
- Updated best practices and troubleshooting

Benefits:
 Reduced from 13 to 8 scripts (better maintainability)
 Interactive menus for better UX
 Fixed WSL node_modules corruption issue
 Smart dependency management (faster deployments)
 Unified interface reduces learning curve
 Better error handling and health checks

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-12 01:35:14 +02:00
parent a227a10ca8
commit 1832684aca
8 changed files with 1447 additions and 3305 deletions

View File

@@ -14,11 +14,12 @@
- Supports automatic server transfer
.PARAMETER Component
Component(s) to build:
- All (default): Build complete package (frontend + backend + telegram bot)
Component(s) to build (optional - shows interactive menu if not specified):
- All: Build complete package (frontend + backend + telegram bot)
- Frontend: Build frontend + backend files only
- Backend: Copy backend files only (no frontend build)
- TelegramBot: Build telegram bot package only
- If omitted: Interactive menu will be displayed
.PARAMETER OutputPath
Output path for deployment package (default: ./deploy-package)
@@ -34,7 +35,11 @@
.EXAMPLE
.\Build-ROA2WEB.ps1
Build complete deployment package (all components)
Shows interactive menu to select components to build
.EXAMPLE
.\Build-ROA2WEB.ps1 -Component All
Build complete deployment package (all components) without menu
.EXAMPLE
.\Build-ROA2WEB.ps1 -Component Frontend
@@ -57,7 +62,7 @@
[CmdletBinding()]
param(
[ValidateSet("All", "Frontend", "Backend", "TelegramBot")]
[string]$Component = "All",
[string]$Component = "",
[string]$OutputPath = "./deploy-package",
[string]$ServerHost = "",
@@ -74,7 +79,7 @@ $ErrorActionPreference = "Stop"
$config = @{
BackendSource = "../../reports-app/backend"
FrontendSource = "../../reports-app/frontend"
TelegramBotSource = "../../../reports-app/telegram-bot"
TelegramBotSource = "../../reports-app/telegram-bot"
SharedSource = "../../shared"
ConfigSource = "../config"
RequiredNodeVersion = 16
@@ -114,6 +119,49 @@ function Resolve-FullPath {
return $fullPath
}
function Show-BuildMenu {
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
Write-Host " ROA2WEB - Build Component Selection Menu" -ForegroundColor Cyan
Write-Host ("=" * 70) -ForegroundColor Cyan
Write-Host ""
Write-Host " Select components to build:" -ForegroundColor Yellow
Write-Host ""
Write-Host " [1] All Components" -ForegroundColor White
Write-Host " (Frontend + Backend + Telegram Bot)" -ForegroundColor Gray
Write-Host ""
Write-Host " [2] Frontend + Backend" -ForegroundColor White
Write-Host " (Vue.js build + FastAPI backend files)" -ForegroundColor Gray
Write-Host ""
Write-Host " [3] Backend Only" -ForegroundColor White
Write-Host " (FastAPI backend files + shared modules)" -ForegroundColor Gray
Write-Host ""
Write-Host " [4] Telegram Bot Only" -ForegroundColor White
Write-Host " (Telegram bot standalone package)" -ForegroundColor Gray
Write-Host ""
Write-Host " [Q] Quit" -ForegroundColor Red
Write-Host ""
Write-Host ("=" * 70) -ForegroundColor Cyan
do {
Write-Host "`nYour choice: " -ForegroundColor Yellow -NoNewline
$choice = Read-Host
switch ($choice.ToUpper()) {
"1" { return "All" }
"2" { return "Frontend" }
"3" { return "Backend" }
"4" { return "TelegramBot" }
"Q" {
Write-Host "`nBuild cancelled by user." -ForegroundColor Yellow
exit 0
}
default {
Write-Host "Invalid choice. Please select 1-4 or Q." -ForegroundColor Red
}
}
} while ($true)
}
function Test-NodeJS {
Write-Step "Checking Node.js installation..."
@@ -142,37 +190,90 @@ function Test-NodeJS {
}
function Build-Frontend {
param([string]$SourcePath)
param(
[string]$SourcePath,
[string]$OutputPath
)
Write-Step "Building Vue.js frontend..."
Write-Step "Building Vue.js frontend in isolated environment..."
if (-not (Test-Path $SourcePath)) {
throw "Frontend source path not found: $SourcePath"
}
Push-Location $SourcePath
try {
# Clean node_modules if it exists
$nodeModulesPath = Join-Path $SourcePath "node_modules"
if (Test-Path $nodeModulesPath) {
Write-Step "Cleaning existing node_modules..."
try {
Remove-Item -Path $nodeModulesPath -Recurse -Force -ErrorAction Stop
Write-Success "Cleaned node_modules"
} catch {
Write-Warning "Could not remove node_modules: $_"
throw "Cannot proceed with locked node_modules. Close all IDEs and retry."
# Create temporary build directory
$tempBuildDir = Join-Path $OutputPath ".temp-frontend-build"
if (Test-Path $tempBuildDir) {
Write-Step "Cleaning existing temp build directory..."
Remove-Item -Path $tempBuildDir -Recurse -Force
}
New-Item -ItemType Directory -Path $tempBuildDir -Force | Out-Null
Write-Success "Created temp build directory (isolated from WSL)"
# Copy frontend sources to temp (exclude node_modules, dist, .git)
Write-Step "Copying frontend sources to temp directory..."
$excludeDirs = @("node_modules", "dist", ".git", "__pycache__", ".vscode", ".idea")
$excludeFiles = @(".env", ".env.local", "*.log")
Get-ChildItem -Path $SourcePath -Recurse | ForEach-Object {
$relativePath = $_.FullName.Substring($SourcePath.Length).TrimStart('\', '/')
# Check if in excluded directory
$inExcludedDir = $false
foreach ($excludeDir in $excludeDirs) {
if ($relativePath -match "^$excludeDir" -or $relativePath -match "[\\/]$excludeDir[\\/]") {
$inExcludedDir = $true
break
}
}
if ($inExcludedDir) { return }
# Install dependencies
Write-Step "Installing npm dependencies..."
# Check if excluded file
$isExcludedFile = $false
foreach ($pattern in $excludeFiles) {
if ($_.Name -like $pattern) {
$isExcludedFile = $true
break
}
}
if ($isExcludedFile) { return }
$destPath = Join-Path $tempBuildDir $relativePath
if ($_.PSIsContainer) {
if (-not (Test-Path $destPath)) {
New-Item -ItemType Directory -Path $destPath -Force | Out-Null
}
} else {
$destDir = Split-Path $destPath -Parent
if (-not (Test-Path $destDir)) {
New-Item -ItemType Directory -Path $destDir -Force | Out-Null
}
Copy-Item -Path $_.FullName -Destination $destPath -Force
}
}
Write-Success "Frontend sources copied to temp"
# Build in temp directory
Push-Location $tempBuildDir
try {
# Install dependencies (including devDependencies for Vite)
Write-Step "Installing npm dependencies (Windows binaries)..."
# Clear NODE_ENV to ensure devDependencies (vite, etc.) are installed
Remove-Item Env:\NODE_ENV -ErrorAction SilentlyContinue
npm install | Out-Default
$nodeModulesPath = Join-Path $tempBuildDir "node_modules"
if (-not (Test-Path $nodeModulesPath)) {
throw "npm install failed: node_modules not created"
}
Write-Success "Dependencies installed"
Write-Success "Dependencies installed in temp"
# Verify Vite is installed
$vitePath = Join-Path $nodeModulesPath ".bin\vite.cmd"
if (-not (Test-Path $vitePath)) {
throw "Vite not found in node_modules - devDependencies not installed"
}
# Build for production
Write-Step "Building for production..."
@@ -181,7 +282,7 @@ function Build-Frontend {
Write-Success "Build completed"
# Verify dist folder
$distPath = Join-Path $SourcePath "dist"
$distPath = Join-Path $tempBuildDir "dist"
if (-not (Test-Path $distPath)) {
throw "Build failed: dist folder not found"
}
@@ -417,6 +518,26 @@ function Copy-ConfigTemplates {
}
}
function Remove-TempDirectories {
param([string]$OutputPath)
Write-Step "Cleaning up temporary build directories..."
$tempBuildDir = Join-Path $OutputPath ".temp-frontend-build"
if (Test-Path $tempBuildDir) {
try {
Remove-Item -Path $tempBuildDir -Recurse -Force -ErrorAction Stop
Write-Success "Temporary build directory cleaned"
} catch {
Write-Warning "Could not remove temp directory: $_"
Write-Warning "You may need to manually delete: $tempBuildDir"
}
} else {
Write-Success "No temporary directories to clean"
}
}
function Copy-DeploymentScripts {
param(
[string]$ScriptsSourcePath,
@@ -652,7 +773,7 @@ function New-DeploymentPackage {
switch ($ComponentType) {
"All" {
# Frontend
$frontendDistPath = Build-Frontend -SourcePath $Paths.FrontendSource
$frontendDistPath = Build-Frontend -SourcePath $Paths.FrontendSource -OutputPath $OutputPath
$frontendDest = Join-Path $OutputPath "frontend"
New-Item -ItemType Directory -Path $frontendDest -Force | Out-Null
Write-Step "Copying frontend files..."
@@ -678,7 +799,7 @@ function New-DeploymentPackage {
"Frontend" {
# Frontend build
$frontendDistPath = Build-Frontend -SourcePath $Paths.FrontendSource
$frontendDistPath = Build-Frontend -SourcePath $Paths.FrontendSource -OutputPath $OutputPath
$frontendDest = Join-Path $OutputPath "frontend"
New-Item -ItemType Directory -Path $frontendDest -Force | Out-Null
Write-Step "Copying frontend files..."
@@ -719,6 +840,11 @@ function New-DeploymentPackage {
}
}
# Cleanup temporary directories
if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend") {
Remove-TempDirectories -OutputPath $OutputPath
}
# Copy deployment scripts
Copy-DeploymentScripts -ScriptsSourcePath $PSScriptRoot -DestPath $OutputPath -ComponentType $ComponentType
@@ -741,6 +867,11 @@ function New-DeploymentPackage {
# =============================================================================
function Main {
# Show interactive menu if no component specified
if ([string]::IsNullOrWhiteSpace($Component)) {
$script:Component = Show-BuildMenu
}
$banner = @"
====================================================================