Files
roa2web-service-auto/deployment/windows/scripts/ROA2WEB-Console.ps1
Marius Mutu ce85e0643b fix: IIS sub-application deployment for production
Fixes 3 critical issues preventing production deployment on Windows IIS:

1. **IIS Sub-Application Path Stripping**
   - Changed URL patterns from ^roa2web/api/(.*) to ^api/(.*)
   - IIS sub-app at /roa2web automatically strips prefix
   - Requests arrive as /api/* not /roa2web/api/*

2. **SPA Fallback Absolute Path**
   - Changed from url="/index.html" to url="index.html"
   - Absolute paths (/) refer to site root, not sub-app
   - Relative path correctly serves from sub-app

3. **MIME Type Duplicates (500 Error)**
   - Added <remove> before <mimeMap> for .js, .json, .webmanifest
   - Prevents "duplicate collection entry" errors
   - Allows override of server-level MIME types

Build Script Improvements:
- Build-ROA2WEB.ps1: Copy public/ folder to temp build dir
- Build-ROA2WEB.ps1: Added verification logging for web.config
- ROA2WEB-Console.ps1: Fixed web.config verification location

Cleanup:
- Removed outdated web.config.10.0.20.36-INTERNAL
- Removed temporary test files and docs

Tested: https://roa2web.romfast.ro/roa2web/ - login page loads successfully

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 16:38:47 +02:00

822 lines
27 KiB
PowerShell

<#
.SYNOPSIS
ROA2WEB Unified Console - Ultrathin Monolith Management
.DESCRIPTION
Unified deployment and management console for ROA2WEB Ultrathin Monolith.
Single Windows service with multiple modules (Reports, Data Entry, Telegram).
Features:
- Deploy backend/frontend updates
- Manage unified service (start/stop/restart)
- View logs and service status
- Backup before deployment
- Module control via .env flags
.PARAMETER NonInteractive
Run in non-interactive mode with specific action
.PARAMETER Action
Action to perform:
- DeployBackend: Deploy backend files only
- DeployFrontend: Deploy frontend files only
- DeployAll: Deploy both backend and frontend
- StartService: Start ROA2WEB-Backend service
- StopService: Stop ROA2WEB-Backend service
- RestartService: Restart ROA2WEB-Backend service
- Status: Show service status and health
- ViewLogs: Display recent log entries
.PARAMETER PackagePath
Path to deployment package (for Deploy actions)
.EXAMPLE
.\ROA2WEB-Console.ps1
Launch interactive menu
.EXAMPLE
.\ROA2WEB-Console.ps1 -NonInteractive -Action DeployAll -PackagePath "C:\Temp\deploy-20250129-120000"
Deploy full package non-interactively
.EXAMPLE
.\ROA2WEB-Console.ps1 -NonInteractive -Action RestartService
Restart the unified backend service
.NOTES
Author: ROA2WEB Team
Version: 2.0 (Ultrathin Monolith)
Requires: Administrator privileges, PowerShell 5.1+
#>
[CmdletBinding()]
param(
[switch]$NonInteractive,
[ValidateSet("DeployBackend", "DeployFrontend", "DeployAll",
"StartService", "StopService", "RestartService",
"Status", "ViewLogs")]
[string]$Action = "",
[string]$PackagePath = ""
)
$ErrorActionPreference = "Stop"
# Require Administrator
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Host "[ERROR] This script requires Administrator privileges" -ForegroundColor Red
Write-Host "Please run PowerShell as Administrator and try again." -ForegroundColor Yellow
exit 1
}
# =============================================================================
# CONFIGURATION
# =============================================================================
$script:Config = @{
# Service Configuration
ServiceName = "ROA2WEB-Backend"
ServiceDisplayName = "ROA2WEB Unified Backend Service"
ServicePort = 8000
HealthUrl = "http://localhost:8000/health"
HealthTimeout = 10
# Installation Paths
InstallRoot = "C:\inetpub\wwwroot\roa2web"
BackendPath = "C:\inetpub\wwwroot\roa2web\backend"
FrontendPath = "C:\inetpub\wwwroot\roa2web\frontend"
SharedPath = "C:\inetpub\wwwroot\roa2web\shared"
ConfigPath = "C:\inetpub\wwwroot\roa2web\config"
DataPath = "C:\inetpub\wwwroot\roa2web\data"
# Logs
LogsPath = "C:\inetpub\wwwroot\roa2web\logs"
BackendStdoutLog = "C:\inetpub\wwwroot\roa2web\logs\backend-stdout.log"
BackendStderrLog = "C:\inetpub\wwwroot\roa2web\logs\backend-stderr.log"
# Backups
BackupPath = "C:\inetpub\wwwroot\roa2web\backups"
MaxBackups = 5
# IIS Configuration
IISSiteName = "Default Web Site"
IISAppName = "roa2web"
}
# =============================================================================
# HELPER FUNCTIONS
# =============================================================================
function Write-Step {
param([string]$Message)
Write-Host "`n[*] $Message" -ForegroundColor Cyan
}
function Write-Success {
param([string]$Message)
Write-Host " [OK] $Message" -ForegroundColor Green
}
function Write-Error {
param([string]$Message)
Write-Host " [ERROR] $Message" -ForegroundColor Red
}
function Write-Warning {
param([string]$Message)
Write-Host " [WARN] $Message" -ForegroundColor Yellow
}
function Write-Info {
param([string]$Message)
Write-Host " [*] $Message" -ForegroundColor Gray
}
function Wait-ForKeyPress {
Write-Host "`nPress any key to continue..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
# =============================================================================
# SERVICE MANAGEMENT
# =============================================================================
function Get-ServiceSafe {
param([string]$ServiceName)
try {
return Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
} catch {
return $null
}
}
function Test-ServiceInstalled {
$service = Get-ServiceSafe -ServiceName $Config.ServiceName
return ($null -ne $service)
}
function Start-ROAService {
Write-Step "Starting $($Config.ServiceDisplayName)..."
$service = Get-ServiceSafe -ServiceName $Config.ServiceName
if (-not $service) {
Write-Error "Service not found: $($Config.ServiceName)"
Write-Info "Run Install-ROA2WEB.ps1 first to install the service"
return $false
}
if ($service.Status -eq 'Running') {
Write-Success "Service is already running"
return $true
}
try {
Start-Service -Name $Config.ServiceName
Start-Sleep -Seconds 3
# Wait for service to start (max 30 seconds)
$maxWait = 30
$waited = 0
while ($waited -lt $maxWait) {
$service = Get-Service -Name $Config.ServiceName
if ($service.Status -eq 'Running') {
Write-Success "Service started successfully"
# Wait a bit more for backend to initialize
Write-Info "Waiting for backend initialization..."
Start-Sleep -Seconds 5
# Test health endpoint
Test-ServiceHealth | Out-Null
return $true
}
Start-Sleep -Seconds 2
$waited += 2
}
Write-Warning "Service started but status unclear"
return $false
} catch {
Write-Error "Failed to start service: $_"
return $false
}
}
function Stop-ROAService {
Write-Step "Stopping $($Config.ServiceDisplayName)..."
$service = Get-ServiceSafe -ServiceName $Config.ServiceName
if (-not $service) {
Write-Warning "Service not found: $($Config.ServiceName)"
return $true
}
if ($service.Status -eq 'Stopped') {
Write-Success "Service is already stopped"
return $true
}
try {
Stop-Service -Name $Config.ServiceName -Force
# Wait for service to stop (max 30 seconds)
$maxWait = 30
$waited = 0
while ($waited -lt $maxWait) {
$service = Get-Service -Name $Config.ServiceName
if ($service.Status -eq 'Stopped') {
Write-Success "Service stopped successfully"
return $true
}
Start-Sleep -Seconds 2
$waited += 2
}
Write-Warning "Service stop timeout - may still be running"
return $false
} catch {
Write-Error "Failed to stop service: $_"
return $false
}
}
function Restart-ROAService {
Write-Step "Restarting $($Config.ServiceDisplayName)..."
if (Stop-ROAService) {
Start-Sleep -Seconds 2
return Start-ROAService
}
return $false
}
function Test-ServiceHealth {
Write-Step "Checking service health..."
$service = Get-ServiceSafe -ServiceName $Config.ServiceName
if (-not $service) {
Write-Warning "Service not installed"
return $false
}
Write-Info "Service Status: $($service.Status)"
if ($service.Status -ne 'Running') {
Write-Warning "Service is not running"
return $false
}
# Test health endpoint
try {
Write-Info "Testing health endpoint: $($Config.HealthUrl)"
$response = Invoke-WebRequest -Uri $Config.HealthUrl -TimeoutSec $Config.HealthTimeout -UseBasicParsing
if ($response.StatusCode -eq 200) {
Write-Success "Health check PASSED (HTTP 200)"
# Parse response for module status
try {
$health = $response.Content | ConvertFrom-Json
Write-Info "Modules Status:"
if ($health.modules) {
foreach ($module in $health.modules.PSObject.Properties) {
$status = if ($module.Value) { "[ON] Enabled" } else { "[OFF] Disabled" }
Write-Info " - $($module.Name): $status"
}
}
} catch {
# If can't parse JSON, just show raw response
Write-Info "Response: $($response.Content)"
}
return $true
} else {
Write-Warning "Health check returned HTTP $($response.StatusCode)"
return $false
}
} catch {
Write-Warning "Health check FAILED: $_"
Write-Info "This may indicate the backend is still initializing or there's a configuration issue"
return $false
}
}
# =============================================================================
# BACKUP FUNCTIONS
# =============================================================================
function New-Backup {
param([string]$Component)
Write-Step "Creating backup before deployment..."
if (-not (Test-Path $Config.BackupPath)) {
New-Item -ItemType Directory -Path $Config.BackupPath -Force | Out-Null
}
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$backupName = "backup-${Component}-${timestamp}"
$backupDest = Join-Path $Config.BackupPath $backupName
try {
New-Item -ItemType Directory -Path $backupDest -Force | Out-Null
if ($Component -eq "Backend" -or $Component -eq "All") {
if (Test-Path $Config.BackendPath) {
Write-Info "Backing up backend..."
Copy-Item -Path $Config.BackendPath -Destination (Join-Path $backupDest "backend") -Recurse -Force
}
if (Test-Path $Config.SharedPath) {
Write-Info "Backing up shared modules..."
Copy-Item -Path $Config.SharedPath -Destination (Join-Path $backupDest "shared") -Recurse -Force
}
}
if ($Component -eq "Frontend" -or $Component -eq "All") {
if (Test-Path $Config.FrontendPath) {
Write-Info "Backing up frontend..."
Copy-Item -Path $Config.FrontendPath -Destination (Join-Path $backupDest "frontend") -Recurse -Force
}
}
Write-Success "Backup created: $backupName"
# Clean old backups (keep last N)
$allBackups = Get-ChildItem -Path $Config.BackupPath -Directory | Sort-Object CreationTime -Descending
if ($allBackups.Count -gt $Config.MaxBackups) {
$toDelete = $allBackups | Select-Object -Skip $Config.MaxBackups
foreach ($old in $toDelete) {
Write-Info "Removing old backup: $($old.Name)"
Remove-Item -Path $old.FullName -Recurse -Force
}
}
return $true
} catch {
Write-Error "Backup failed: $_"
return $false
}
}
# =============================================================================
# DEPLOYMENT FUNCTIONS
# =============================================================================
function Deploy-Backend {
param([string]$SourcePath)
Write-Step "Deploying backend..."
$sourceBe = Join-Path $SourcePath "backend"
$sourceShared = Join-Path $SourcePath "shared"
if (-not (Test-Path $sourceBe)) {
Write-Error "Backend not found in package: $sourceBe"
return $false
}
try {
# Stop service
if (-not (Stop-ROAService)) {
Write-Warning "Failed to stop service, continuing anyway..."
}
# Backup
if (-not (New-Backup -Component "Backend")) {
Write-Warning "Backup failed, but continuing with deployment"
}
# Deploy backend
Write-Info "Copying backend files..."
if (Test-Path $Config.BackendPath) {
# Preserve .env file
$envFile = Join-Path $Config.BackendPath ".env"
$envBackup = $null
if (Test-Path $envFile) {
$envBackup = Get-Content $envFile -Raw
Write-Info "Preserving .env file"
}
Remove-Item -Path $Config.BackendPath -Recurse -Force
Copy-Item -Path $sourceBe -Destination $Config.BackendPath -Recurse -Force
# Restore .env
if ($envBackup) {
Set-Content -Path $envFile -Value $envBackup -Force
Write-Success ".env file restored"
}
} else {
Copy-Item -Path $sourceBe -Destination $Config.BackendPath -Recurse -Force
}
Write-Success "Backend files deployed"
# Deploy shared modules if present
if (Test-Path $sourceShared) {
Write-Info "Copying shared modules..."
if (Test-Path $Config.SharedPath) {
Remove-Item -Path $Config.SharedPath -Recurse -Force
}
Copy-Item -Path $sourceShared -Destination $Config.SharedPath -Recurse -Force
Write-Success "Shared modules deployed"
}
# Start service
Start-Sleep -Seconds 2
if (Start-ROAService) {
Write-Success "Backend deployment completed successfully"
return $true
} else {
Write-Warning "Backend deployed but service start failed"
Write-Info "Check logs: $($Config.BackendStderrLog)"
return $false
}
} catch {
Write-Error "Backend deployment failed: $_"
return $false
}
}
function Deploy-Frontend {
param([string]$SourcePath)
Write-Step "Deploying frontend..."
$sourceFe = Join-Path $SourcePath "frontend"
if (-not (Test-Path $sourceFe)) {
Write-Error "Frontend not found in package: $sourceFe"
return $false
}
try {
# Backup
if (-not (New-Backup -Component "Frontend")) {
Write-Warning "Backup failed, but continuing with deployment"
}
# Deploy frontend
Write-Info "Copying frontend files to IIS..."
if (Test-Path $Config.FrontendPath) {
Remove-Item -Path $Config.FrontendPath -Recurse -Force
}
Copy-Item -Path $sourceFe -Destination $Config.FrontendPath -Recurse -Force
Write-Success "Frontend files deployed"
# Verify web.config was deployed (should be in frontend/ from dist/)
$deployedWebConfig = Join-Path $Config.FrontendPath "web.config"
if (Test-Path $deployedWebConfig) {
Write-Success "web.config deployed successfully"
# Verify it has correct configuration for /roa2web/ path
$configContent = Get-Content $deployedWebConfig -Raw
if ($configContent -match 'url="[^"]*roa2web/api') {
Write-Success "web.config contains correct /roa2web/api proxy rules"
} else {
Write-Warning "web.config may not have correct /roa2web/api proxy configuration"
}
} else {
Write-Warning "web.config not found in deployed frontend: $deployedWebConfig"
Write-Warning "IIS reverse proxy will not work without web.config"
Write-Warning "Ensure 'public/web.config' exists in source and rebuild frontend"
}
Write-Success "Frontend deployment completed successfully"
return $true
} catch {
Write-Error "Frontend deployment failed: $_"
return $false
}
}
function Deploy-All {
param([string]$SourcePath)
Write-Step "Deploying complete package (Backend + Frontend)..."
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
Write-Host " FULL DEPLOYMENT" -ForegroundColor Cyan
Write-Host ("=" * 70) -ForegroundColor Cyan
# Backup everything
if (-not (New-Backup -Component "All")) {
Write-Warning "Backup failed, but continuing with deployment"
}
# Deploy backend (includes service restart)
$backendOk = Deploy-Backend -SourcePath $SourcePath
# Deploy frontend
$frontendOk = Deploy-Frontend -SourcePath $SourcePath
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
Write-Host " DEPLOYMENT SUMMARY" -ForegroundColor Cyan
Write-Host ("=" * 70) -ForegroundColor Cyan
Write-Host " Backend: " -NoNewline
if ($backendOk) {
Write-Host "[OK] Success" -ForegroundColor Green
} else {
Write-Host "[X] Failed" -ForegroundColor Red
}
Write-Host " Frontend: " -NoNewline
if ($frontendOk) {
Write-Host "[OK] Success" -ForegroundColor Green
} else {
Write-Host "[X] Failed" -ForegroundColor Red
}
Write-Host ("=" * 70) -ForegroundColor Cyan
return ($backendOk -and $frontendOk)
}
# =============================================================================
# LOG VIEWING
# =============================================================================
function Show-Logs {
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
Write-Host " Service Logs" -ForegroundColor Cyan
Write-Host ("=" * 70) -ForegroundColor Cyan
# Backend stdout
if (Test-Path $Config.BackendStdoutLog) {
Write-Host "`n--- Backend STDOUT (last 30 lines) ---" -ForegroundColor Yellow
Get-Content $Config.BackendStdoutLog -Tail 30 | ForEach-Object {
Write-Host $_ -ForegroundColor Gray
}
} else {
Write-Warning "Backend stdout log not found: $($Config.BackendStdoutLog)"
}
# Backend stderr
if (Test-Path $Config.BackendStderrLog) {
Write-Host "`n--- Backend STDERR (last 20 lines) ---" -ForegroundColor Yellow
Get-Content $Config.BackendStderrLog -Tail 20 | ForEach-Object {
Write-Host $_ -ForegroundColor Red
}
} else {
Write-Info "Backend stderr log not found (this is OK if no errors)"
}
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
}
# =============================================================================
# STATUS DISPLAY
# =============================================================================
function Show-Status {
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
Write-Host " ROA2WEB Ultrathin Monolith - System Status" -ForegroundColor Cyan
Write-Host ("=" * 70) -ForegroundColor Cyan
# Service Status
$service = Get-ServiceSafe -ServiceName $Config.ServiceName
Write-Host "`n Service: $($Config.ServiceDisplayName)" -ForegroundColor Yellow
if ($service) {
Write-Host " Status: " -NoNewline
if ($service.Status -eq 'Running') {
Write-Host "$($service.Status)" -ForegroundColor Green
} else {
Write-Host "$($service.Status)" -ForegroundColor Red
}
Write-Host " Name: $($Config.ServiceName)" -ForegroundColor Gray
Write-Host " Port: $($Config.ServicePort)" -ForegroundColor Gray
} else {
Write-Host " Status: " -NoNewline
Write-Host "Not Installed" -ForegroundColor Red
Write-Host " Run Install-ROA2WEB.ps1 to install the service" -ForegroundColor Gray
}
# Health Check
if ($service -and $service.Status -eq 'Running') {
Write-Host ""
Test-ServiceHealth | Out-Null
}
# Paths
Write-Host "`n Installation Paths:" -ForegroundColor Yellow
Write-Host " Root: $($Config.InstallRoot)" -ForegroundColor Gray
Write-Host " Backend: $($Config.BackendPath)" -ForegroundColor Gray
Write-Host " Frontend: $($Config.FrontendPath)" -ForegroundColor Gray
Write-Host " Shared: $($Config.SharedPath)" -ForegroundColor Gray
Write-Host " Logs: $($Config.LogsPath)" -ForegroundColor Gray
# Module Configuration
$envFile = Join-Path $Config.BackendPath ".env"
if (Test-Path $envFile) {
Write-Host "`n Module Configuration (.env):" -ForegroundColor Yellow
$envContent = Get-Content $envFile
$modules = $envContent | Where-Object { $_ -match "^MODULE_.*_ENABLED=" }
foreach ($line in $modules) {
if ($line -match "MODULE_(.+)_ENABLED=(.+)") {
$moduleName = $matches[1]
$enabled = $matches[2] -eq "true"
Write-Host " $moduleName`: " -NoNewline -ForegroundColor Gray
if ($enabled) {
Write-Host "Enabled" -ForegroundColor Green
} else {
Write-Host "Disabled" -ForegroundColor Red
}
}
}
}
# Endpoints
Write-Host "`n API Endpoints:" -ForegroundColor Yellow
Write-Host " Health: http://localhost:$($Config.ServicePort)/health" -ForegroundColor Gray
Write-Host " Docs: http://localhost:$($Config.ServicePort)/docs" -ForegroundColor Gray
Write-Host " Frontend: http://localhost/ (via IIS)" -ForegroundColor Gray
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
}
# =============================================================================
# INTERACTIVE MENU
# =============================================================================
function Show-MainMenu {
Clear-Host
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
Write-Host " ROA2WEB Unified Console - Ultrathin Monolith" -ForegroundColor Cyan
Write-Host ("=" * 70) -ForegroundColor Cyan
$service = Get-ServiceSafe -ServiceName $Config.ServiceName
if ($service) {
Write-Host "`n Service Status: " -NoNewline
if ($service.Status -eq 'Running') {
Write-Host "RUNNING" -ForegroundColor Green
} else {
Write-Host "$($service.Status)" -ForegroundColor Yellow
}
} else {
Write-Host "`n Service Status: " -NoNewline
Write-Host "NOT INSTALLED" -ForegroundColor Red
}
Write-Host "`n Main Menu:" -ForegroundColor Yellow
Write-Host ""
Write-Host " === Deployment ===" -ForegroundColor Cyan
Write-Host " [1] Deploy Backend" -ForegroundColor White
Write-Host " [2] Deploy Frontend" -ForegroundColor White
Write-Host " [3] Deploy All (Backend + Frontend)" -ForegroundColor White
Write-Host ""
Write-Host " === Service Management ===" -ForegroundColor Cyan
Write-Host " [4] Start Service" -ForegroundColor White
Write-Host " [5] Stop Service" -ForegroundColor White
Write-Host " [6] Restart Service" -ForegroundColor White
Write-Host ""
Write-Host " === Monitoring ===" -ForegroundColor Cyan
Write-Host " [7] View Status" -ForegroundColor White
Write-Host " [8] View Logs" -ForegroundColor White
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" {
Write-Host "`nEnter deployment package path: " -NoNewline
$pkgPath = Read-Host
if (Test-Path $pkgPath) {
Deploy-Backend -SourcePath $pkgPath | Out-Null
} else {
Write-Error "Package path not found: $pkgPath"
}
Wait-ForKeyPress
return "Continue"
}
"2" {
Write-Host "`nEnter deployment package path: " -NoNewline
$pkgPath = Read-Host
if (Test-Path $pkgPath) {
Deploy-Frontend -SourcePath $pkgPath | Out-Null
} else {
Write-Error "Package path not found: $pkgPath"
}
Wait-ForKeyPress
return "Continue"
}
"3" {
Write-Host "`nEnter deployment package path: " -NoNewline
$pkgPath = Read-Host
if (Test-Path $pkgPath) {
Deploy-All -SourcePath $pkgPath | Out-Null
} else {
Write-Error "Package path not found: $pkgPath"
}
Wait-ForKeyPress
return "Continue"
}
"4" {
Start-ROAService | Out-Null
Wait-ForKeyPress
return "Continue"
}
"5" {
Stop-ROAService | Out-Null
Wait-ForKeyPress
return "Continue"
}
"6" {
Restart-ROAService | Out-Null
Wait-ForKeyPress
return "Continue"
}
"7" {
Show-Status
Wait-ForKeyPress
return "Continue"
}
"8" {
Show-Logs
Wait-ForKeyPress
return "Continue"
}
"Q" { return "Quit" }
default {
Write-Host "Invalid choice. Please select 1-8 or Q." -ForegroundColor Red
}
}
} while ($true)
}
# =============================================================================
# MAIN EXECUTION
# =============================================================================
function Main {
# Check if service installed
if (-not (Test-ServiceInstalled) -and -not $NonInteractive) {
Write-Warning "ROA2WEB service not found"
Write-Info "Run Install-ROA2WEB.ps1 first to install the service"
Write-Host ""
Wait-ForKeyPress
}
# Non-interactive mode
if ($NonInteractive -and $Action) {
switch ($Action) {
"DeployBackend" {
if (-not $PackagePath) {
Write-Error "PackagePath parameter required for DeployBackend"
exit 1
}
$success = Deploy-Backend -SourcePath $PackagePath
exit $(if ($success) { 0 } else { 1 })
}
"DeployFrontend" {
if (-not $PackagePath) {
Write-Error "PackagePath parameter required for DeployFrontend"
exit 1
}
$success = Deploy-Frontend -SourcePath $PackagePath
exit $(if ($success) { 0 } else { 1 })
}
"DeployAll" {
if (-not $PackagePath) {
Write-Error "PackagePath parameter required for DeployAll"
exit 1
}
$success = Deploy-All -SourcePath $PackagePath
exit $(if ($success) { 0 } else { 1 })
}
"StartService" {
$success = Start-ROAService
exit $(if ($success) { 0 } else { 1 })
}
"StopService" {
$success = Stop-ROAService
exit $(if ($success) { 0 } else { 1 })
}
"RestartService" {
$success = Restart-ROAService
exit $(if ($success) { 0 } else { 1 })
}
"Status" {
Show-Status
exit 0
}
"ViewLogs" {
Show-Logs
exit 0
}
}
}
# Interactive mode
do {
$result = Show-MainMenu
} while ($result -eq "Continue")
Write-Host "`nGoodbye!`n" -ForegroundColor Cyan
}
# Run main
Main