diff --git a/.gitignore b/.gitignore index a26f7d2..ca32c5a 100644 --- a/.gitignore +++ b/.gitignore @@ -343,10 +343,28 @@ cython_debug/ db.sqlite3 db.sqlite3-journal debug.log -deploy_production.sh +# ============================================================================== +# 📦 WINDOWS DEPLOYMENT ARTIFACTS - Generated by Build-ROA2WEB.ps1 +# ============================================================================== +# These files are build artifacts and should NOT be committed to git +# They are generated fresh by running: .\Build-ROA2WEB.ps1 + +# Deployment packages (all variations) deployment/windows/deploy-package/ +deploy-package/ +**/deploy-package/ + +# Deployment logs and temporary files deployment/windows/scripts/*.log deployment/windows/temp/ +deployment/windows/*.log + +# Cache and database files in deployment artifacts +**/cache_data.db +**/roa2web_cache.db + +# Deployment temporary files +deploy_production.sh dev.log dev.log develop-eggs/ @@ -396,9 +414,7 @@ playwright-report/ profile_default/ quick_test.* quick_test.* -roa2web/deployment/windows/deploy-package/ -roa2web/deployment/windows/scripts/*.log -roa2web/deployment/windows/temp/ +# Removed duplicate - already covered in deployment section above roa2web/reports-app/telegram-bot/data/*.db roa2web/reports-app/telegram-bot/data/*.db-* run_tests.* diff --git a/CLAUDE.md b/CLAUDE.md index 6c5bc1a..6ae1a03 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -367,9 +367,15 @@ See `DEPLOYMENT_GUIDE.md` for full Linux/Docker deployment instructions. Windows Server deployment uses IIS and Windows Services without Docker: **Build deployment package (on WSL/Linux development machine):** -```bash +```powershell cd deployment/windows/scripts -./Build-Frontend.ps1 + +# Build complete package (Frontend + Backend + Telegram Bot) +.\Build-ROA2WEB.ps1 + +# Or build specific components +.\Build-ROA2WEB.ps1 -Component Frontend # Frontend + Backend only +.\Build-ROA2WEB.ps1 -Component TelegramBot # Telegram Bot only # Output: ./deploy-package/ # Transfer this to Windows Server @@ -379,22 +385,30 @@ cd deployment/windows/scripts ```powershell # Initial installation cd C:\path\to\deploy-package\scripts + +# Install main application .\Install-ROA2WEB.ps1 -# Configure application +# Install Telegram Bot +.\Install-TelegramBot.ps1 + +# Configure applications notepad C:\inetpub\wwwroot\roa2web\backend\.env +notepad C:\inetpub\wwwroot\roa2web\telegram-bot\.env -# Deploy application files -.\Deploy-ROA2WEB.ps1 -SourcePath "C:\path\to\deploy-package" +# Deploy/update application files +.\Deploy-ROA2WEB.ps1 +.\Deploy-TelegramBot.ps1 -# Management -.\Start-ROA2WEB.ps1 -.\Stop-ROA2WEB.ps1 -.\Restart-ROA2WEB.ps1 +# Service Management (Unified) +.\Manage-ROA2WEB.ps1 -Action Start # Start all services +.\Manage-ROA2WEB.ps1 -Action Stop # Stop all services +.\Manage-ROA2WEB.ps1 -Action Restart # Restart all services +.\Manage-ROA2WEB.ps1 -Action Status # Check status -# Check status -Get-Service ROA2WEB-Backend -Get-Website ROA2WEB +# Manage specific components +.\Manage-ROA2WEB.ps1 -Action Start -Component Backend +.\Manage-ROA2WEB.ps1 -Action Restart -Component TelegramBot ``` **Windows Deployment Architecture:** diff --git a/deployment/windows/DEPLOY_PACKAGE.md b/deployment/windows/DEPLOY_PACKAGE.md new file mode 100644 index 0000000..ab32d45 --- /dev/null +++ b/deployment/windows/DEPLOY_PACKAGE.md @@ -0,0 +1,221 @@ +# 📦 Deployment Package Generation + +This document explains how to generate deployment packages for ROA2WEB Windows deployment. + +## ⚠️ Important Note + +The `deploy-package/` directory is **NOT** committed to git. It contains build artifacts that are generated fresh each time you build. + +## 🔨 Generating Deployment Packages + +Use the unified build script **`Build-ROA2WEB.ps1`** to generate deployment packages: + +### Build Complete Package (Recommended) + +```powershell +cd deployment/windows/scripts +.\Build-ROA2WEB.ps1 +``` + +This generates a complete deployment package containing: +- ✅ Frontend (Vue.js built static files) +- ✅ Backend (FastAPI Python application) +- ✅ Shared modules (auth, database, utils) +- ✅ Telegram Bot application +- ✅ Configuration templates +- ✅ Deployment scripts + +**Output**: `deployment/windows/deploy-package/` + +### Build Specific Components + +```powershell +# Frontend + Backend only +.\Build-ROA2WEB.ps1 -Component Frontend + +# Backend only (no frontend build) +.\Build-ROA2WEB.ps1 -Component Backend + +# Telegram Bot only +.\Build-ROA2WEB.ps1 -Component TelegramBot +``` + +### Custom Output Path + +```powershell +# Build to custom location with date suffix +.\Build-ROA2WEB.ps1 -OutputPath "D:\deployments\roa2web-$(Get-Date -Format 'yyyyMMdd')" +``` + +## 📂 Package Structure + +After building, `deploy-package/` will contain: + +``` +deploy-package/ +├── backend/ # FastAPI application files +│ ├── app/ # Application code +│ ├── requirements.txt # Python dependencies +│ └── ... +├── frontend/ # Built Vue.js static files +│ ├── assets/ # JS, CSS, fonts +│ ├── index.html # Main HTML +│ └── ... +├── telegram-bot/ # Telegram bot application +│ ├── app/ # Bot code +│ ├── requirements.txt # Bot dependencies +│ └── .env.example # Configuration template +├── shared/ # Shared Python modules +│ ├── auth/ # Authentication +│ ├── database/ # Oracle connection pool +│ └── utils/ # Utilities +├── config/ # Configuration templates +│ ├── .env.production.windows +│ ├── .env.production.windows.telegram +│ └── web.config # IIS configuration +├── scripts/ # Deployment scripts +│ ├── Install-ROA2WEB.ps1 +│ ├── Install-TelegramBot.ps1 +│ ├── Deploy-ROA2WEB.ps1 +│ ├── Deploy-TelegramBot.ps1 +│ ├── Manage-ROA2WEB.ps1 +│ ├── Backup-TelegramDB.ps1 +│ ├── Setup-DailyBackup.ps1 +│ ├── Setup-ClaudeAuth.ps1 +│ └── Enable-HTTPS.ps1 +└── README.txt # Deployment instructions +``` + +## 🚀 Deployment Workflow + +### 1. Build Package (Development Machine) + +```powershell +# On WSL or development machine +cd deployment/windows/scripts +.\Build-ROA2WEB.ps1 +``` + +### 2. Transfer to Windows Server + +```powershell +# Via network share +Copy-Item -Path ./deploy-package -Destination \\SERVER\C$\Temp\roa2web-deploy -Recurse + +# Or via RDP (manual copy) +``` + +### 3. Install on Server (First Time) + +```powershell +# On Windows Server (as Administrator) +cd C:\Temp\roa2web-deploy\scripts + +# Install main application +.\Install-ROA2WEB.ps1 + +# Install Telegram bot +.\Install-TelegramBot.ps1 +``` + +### 4. Configure & Start + +```powershell +# Configure environment +notepad C:\inetpub\wwwroot\roa2web\backend\.env +notepad C:\inetpub\wwwroot\roa2web\telegram-bot\.env + +# Start services +.\Manage-ROA2WEB.ps1 -Action Start +``` + +### 5. Deploy Updates + +```powershell +# Stop services +.\Manage-ROA2WEB.ps1 -Action Stop + +# Deploy updates +.\Deploy-ROA2WEB.ps1 +.\Deploy-TelegramBot.ps1 + +# Start services +.\Manage-ROA2WEB.ps1 -Action Start +``` + +## 🔧 Requirements + +**Development Machine (for building):** +- Node.js 16+ (for Frontend builds) +- npm +- PowerShell 5.1+ + +**Windows Server (for deployment):** +- Windows Server 2016+ or Windows 10/11 +- IIS with URL Rewrite Module +- Python 3.11+ +- PowerShell 5.1+ (Administrator) + +## 📝 Notes + +- **Build artifacts are NOT version-controlled**: The `deploy-package/` directory is in `.gitignore` +- **Fresh builds recommended**: Always generate a fresh package before deploying +- **Virtual environments**: Not included in package (created automatically during installation) +- **.env files**: Not included in package (created from templates during installation) +- **Database files**: Excluded from package (SQLite for Telegram bot created on server) + +## ⚙️ Advanced Options + +### Transfer to Server Automatically + +```powershell +# Using network share (Windows) +.\Build-ROA2WEB.ps1 -ServerHost "10.0.20.36" -ServerPath "C:\Temp\roa2web-deploy" +``` + +### Clean Build + +The build script automatically cleans the output directory. To preserve existing output: + +```powershell +.\Build-ROA2WEB.ps1 -Clean $false +``` + +## 🐛 Troubleshooting + +### "Node.js not found" + +Install Node.js 16+ from https://nodejs.org/ + +### "deploy-package already exists" + +The script automatically cleans old builds. If you see errors, manually delete `deploy-package/` and retry. + +### Build fails with "locked files" + +Close VS Code, IDEs, and file explorers that might have files open in the source directories. + +## 📚 Documentation + +- **Complete Deployment Guide**: [`docs/WINDOWS_DEPLOYMENT.md`](docs/WINDOWS_DEPLOYMENT.md) +- **Script Reference**: [`scripts/README.md`](scripts/README.md) +- **Quick Start**: [`README.md`](README.md) +- **Project Documentation**: [`../../CLAUDE.md`](../../CLAUDE.md) + +## 🔄 Migration from Old Build Scripts + +If you were using the old build scripts, here's the mapping: + +| Old Script | New Script | Equivalent Command | +|------------|------------|-------------------| +| `Build-Frontend.ps1` | `Build-ROA2WEB.ps1` | `.\Build-ROA2WEB.ps1 -Component Frontend` | +| `Build-TelegramBot.ps1` | `Build-ROA2WEB.ps1` | `.\Build-ROA2WEB.ps1 -Component TelegramBot` | +| Both scripts together | `Build-ROA2WEB.ps1` | `.\Build-ROA2WEB.ps1` (default: All) | + +**Note**: Old scripts are marked as DEPRECATED and will be removed in a future version. + +--- + +**Generated by**: ROA2WEB Team +**Last Updated**: 2025-11-11 +**Version**: 2.0 (Unified Build System) diff --git a/deployment/windows/scripts/Build-Frontend.ps1 b/deployment/windows/scripts/Build-Frontend.ps1 index 548291a..a4de503 100644 --- a/deployment/windows/scripts/Build-Frontend.ps1 +++ b/deployment/windows/scripts/Build-Frontend.ps1 @@ -1,3 +1,24 @@ +<# +================================================================================ +⚠️ DEPRECATED - This script is deprecated in favor of Build-ROA2WEB.ps1 +================================================================================ + +This script is maintained for backward compatibility but will be removed in +a future version. Please use the new unified build script instead: + + .\Build-ROA2WEB.ps1 -Component Frontend + +The new script provides: + - Unified build process for all components + - Better parameter validation + - Consistent output structure + - Support for building All, Frontend, Backend, or TelegramBot + +For complete package: .\Build-ROA2WEB.ps1 -Component All + +================================================================================ +#> + <# .SYNOPSIS Build ROA2WEB Frontend for Production Deployment diff --git a/deployment/windows/scripts/Build-ROA2WEB.ps1 b/deployment/windows/scripts/Build-ROA2WEB.ps1 new file mode 100644 index 0000000..8f7ca49 --- /dev/null +++ b/deployment/windows/scripts/Build-ROA2WEB.ps1 @@ -0,0 +1,802 @@ +<# +.SYNOPSIS + Unified Build Script for ROA2WEB Windows Deployment + +.DESCRIPTION + This script builds complete deployment packages for ROA2WEB application. + Supports building Frontend, Backend, Telegram Bot, or all components together. + + Features: + - Flexible component selection + - Validates dependencies (Node.js, Python) + - Creates production-optimized builds + - Generates deployment-ready packages + - Supports automatic server transfer + +.PARAMETER Component + Component(s) to build: + - All (default): 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 + +.PARAMETER OutputPath + Output path for deployment package (default: ./deploy-package) + +.PARAMETER ServerHost + Remote server hostname/IP for automatic deployment (optional) + +.PARAMETER ServerPath + Remote server path for automatic deployment (optional) + +.PARAMETER Clean + Clean output directory before building (default: true) + +.EXAMPLE + .\Build-ROA2WEB.ps1 + Build complete deployment package (all components) + +.EXAMPLE + .\Build-ROA2WEB.ps1 -Component Frontend + Build only frontend + backend files + +.EXAMPLE + .\Build-ROA2WEB.ps1 -Component TelegramBot + Build only Telegram bot package + +.EXAMPLE + .\Build-ROA2WEB.ps1 -Component All -OutputPath "D:\deployments\roa2web-$(Get-Date -Format 'yyyyMMdd')" + Build complete package to custom output path + +.NOTES + Author: ROA2WEB Team + Version: 2.0 (Unified Build Script) + Requires: Node.js 16+ (for Frontend), Python 3.11+ (for validation) +#> + +[CmdletBinding()] +param( + [ValidateSet("All", "Frontend", "Backend", "TelegramBot")] + [string]$Component = "All", + + [string]$OutputPath = "./deploy-package", + [string]$ServerHost = "", + [string]$ServerPath = "", + [bool]$Clean = $true +) + +$ErrorActionPreference = "Stop" + +# ============================================================================= +# CONFIGURATION +# ============================================================================= + +$config = @{ + BackendSource = "../../reports-app/backend" + FrontendSource = "../../reports-app/frontend" + TelegramBotSource = "../../../reports-app/telegram-bot" + SharedSource = "../../shared" + ConfigSource = "../config" + RequiredNodeVersion = 16 +} + +# ============================================================================= +# 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 Resolve-FullPath { + param([string]$Path) + + $scriptDir = Split-Path -Parent $PSScriptRoot + $fullPath = Join-Path $scriptDir $Path + $fullPath = [System.IO.Path]::GetFullPath($fullPath) + + return $fullPath +} + +function Test-NodeJS { + Write-Step "Checking Node.js installation..." + + try { + $nodeVersion = node --version 2>&1 + $npmVersion = npm --version 2>&1 + + Write-Success "Node.js: $nodeVersion" + Write-Success "npm: $npmVersion" + + # Check minimum version + if ($nodeVersion -match "v(\d+)\.") { + $major = [int]$matches[1] + if ($major -lt $config.RequiredNodeVersion) { + throw "Node.js version $($config.RequiredNodeVersion)+ required (found: $nodeVersion)" + } + } + + return $true + } catch { + Write-Error "Node.js not found or version too old" + Write-Host "`n Install Node.js from: https://nodejs.org/" -ForegroundColor Yellow + Write-Host " Minimum version: $($config.RequiredNodeVersion).x" -ForegroundColor Yellow + throw + } +} + +function Build-Frontend { + param([string]$SourcePath) + + Write-Step "Building Vue.js frontend..." + + 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." + } + } + + # Install dependencies + Write-Step "Installing npm dependencies..." + npm install | Out-Default + + if (-not (Test-Path $nodeModulesPath)) { + throw "npm install failed: node_modules not created" + } + Write-Success "Dependencies installed" + + # Build for production + Write-Step "Building for production..." + $env:NODE_ENV = "production" + npm run build | Out-Default + Write-Success "Build completed" + + # Verify dist folder + $distPath = Join-Path $SourcePath "dist" + if (-not (Test-Path $distPath)) { + throw "Build failed: dist folder not found" + } + + $distFiles = Get-ChildItem -Path $distPath -Recurse -File + $totalSize = ($distFiles | Measure-Object -Property Length -Sum).Sum / 1MB + Write-Success "Generated $(($distFiles).Count) files ($([math]::Round($totalSize, 2)) MB)" + + return $distPath + } finally { + Pop-Location + } +} + +function Copy-BackendFiles { + param( + [string]$SourcePath, + [string]$DestPath + ) + + Write-Step "Copying backend files..." + + if (-not (Test-Path $SourcePath)) { + throw "Backend source path not found: $SourcePath" + } + + if (-not (Test-Path $DestPath)) { + New-Item -ItemType Directory -Path $DestPath -Force | Out-Null + } + + # Exclude patterns + $excludeDirs = @("venv", "__pycache__", ".pytest_cache", "logs", "temp", "node_modules") + $excludeFiles = @("*.pyc", "*.pyo", "*.log", ".env", ".env.local") + + $normalizedSourcePath = $SourcePath.TrimEnd('\', '/') + '\' + + $testExclude = { + param([string]$RelativePath, [bool]$IsDirectory, [array]$ExcludeDirs, [array]$ExcludeFiles) + + if ($IsDirectory) { + $dirName = Split-Path $RelativePath -Leaf + if ($ExcludeDirs -contains $dirName) { + return $true + } + } + + $pathParts = $RelativePath -split '[\\/]' + foreach ($part in $pathParts) { + if ($ExcludeDirs -contains $part) { + return $true + } + } + + if (-not $IsDirectory) { + foreach ($pattern in $ExcludeFiles) { + if ($RelativePath -like $pattern) { + return $true + } + } + } + + return $false + } + + Get-ChildItem -Path $SourcePath -Recurse | ForEach-Object { + if ($_.FullName.Length -le $normalizedSourcePath.Length) { + return + } + $relativePath = $_.FullName.Substring($normalizedSourcePath.Length) + + $shouldExclude = & $testExclude -RelativePath $relativePath -IsDirectory $_.PSIsContainer -ExcludeDirs $excludeDirs -ExcludeFiles $excludeFiles + if ($shouldExclude) { + return + } + + $destFile = Join-Path $DestPath $relativePath + + if ($_.PSIsContainer) { + if (-not (Test-Path $destFile)) { + New-Item -ItemType Directory -Path $destFile -Force | Out-Null + } + } else { + $destDir = Split-Path $destFile -Parent + if (-not (Test-Path $destDir)) { + New-Item -ItemType Directory -Path $destDir -Force | Out-Null + } + Copy-Item -Path $_.FullName -Destination $destFile -Force + } + } + + $backendFiles = Get-ChildItem -Path $DestPath -Recurse -File + Write-Success "Copied $(($backendFiles).Count) backend files" + + # Verify requirements.txt + $requirementsTxt = Join-Path $DestPath "requirements.txt" + if (-not (Test-Path $requirementsTxt)) { + Write-Error "CRITICAL: requirements.txt not found!" + throw "Backend package incomplete - missing requirements.txt" + } + Write-Success "Verified: requirements.txt present" +} + +function Copy-TelegramBotFiles { + param( + [string]$SourcePath, + [string]$DestPath + ) + + Write-Step "Copying Telegram bot files..." + + if (-not (Test-Path $SourcePath)) { + throw "Telegram bot source path not found: $SourcePath" + } + + if (-not (Test-Path $DestPath)) { + New-Item -ItemType Directory -Path $DestPath -Force | Out-Null + } + + # Exclude patterns + $excludeDirs = @("venv", "data", "logs", "temp", "backups", "__pycache__", ".pytest_cache", "tests", ".git") + $excludeFiles = @(".env", "*.pyc", "*.pyo", "*.log", "*.db", ".DS_Store", "Thumbs.db") + + # Copy app/ directory + $sourceApp = Join-Path $SourcePath "app" + $destApp = Join-Path $DestPath "app" + New-Item -ItemType Directory -Path $destApp -Force | Out-Null + + $fileCount = 0 + Get-ChildItem -Path $sourceApp -Recurse | ForEach-Object { + # Check exclusions + $inExcludedDir = $false + foreach ($excludeDir in $excludeDirs) { + if ($_.FullName -like "*\$excludeDir\*" -or $_.FullName -like "*/$excludeDir/*") { + $inExcludedDir = $true + break + } + } + + if ($inExcludedDir) { + return + } + + $isExcludedFile = $false + foreach ($pattern in $excludeFiles) { + if ($_.Name -like $pattern) { + $isExcludedFile = $true + break + } + } + + if ($isExcludedFile) { + return + } + + $relativePath = $_.FullName.Substring($sourceApp.Length) + $destFile = Join-Path $destApp $relativePath + + if ($_.PSIsContainer) { + if (-not (Test-Path $destFile)) { + New-Item -ItemType Directory -Path $destFile -Force | Out-Null + } + } else { + $destFileDir = Split-Path $destFile -Parent + if (-not (Test-Path $destFileDir)) { + New-Item -ItemType Directory -Path $destFileDir -Force | Out-Null + } + Copy-Item -Path $_.FullName -Destination $destFile -Force + $fileCount++ + } + } + + Write-Success "Copied $fileCount app files" + + # Copy requirements.txt + $sourceReq = Join-Path $SourcePath "requirements.txt" + $destReq = Join-Path $DestPath "requirements.txt" + if (Test-Path $sourceReq) { + Copy-Item -Path $sourceReq -Destination $destReq -Force + Write-Success "requirements.txt copied" + } + + # Create .env.example + $envTemplate = @" +# ROA2WEB Telegram Bot - Production Configuration +TELEGRAM_BOT_TOKEN=your_bot_token_from_BotFather +CLAUDE_API_KEY=your_claude_api_key +BACKEND_URL=http://localhost:8000 +BACKEND_TIMEOUT=30 +SQLITE_DB_PATH=C:\inetpub\wwwroot\roa2web\telegram-bot\data\telegram_bot.db +INTERNAL_API_HOST=127.0.0.1 +INTERNAL_API_PORT=8002 +LOG_LEVEL=INFO +LOG_FILE=C:\inetpub\wwwroot\roa2web\telegram-bot\logs\bot.log +ENVIRONMENT=production +AUTH_CODE_EXPIRY_MINUTES=15 +JWT_REFRESH_THRESHOLD_MINUTES=5 +SESSION_TIMEOUT_MINUTES=60 +MAX_CONVERSATION_HISTORY=20 +"@ + + $envPath = Join-Path $DestPath ".env.example" + Set-Content -Path $envPath -Value $envTemplate -Encoding UTF8 + Write-Success ".env.example template created" +} + +function Copy-SharedModules { + param( + [string]$SourcePath, + [string]$DestPath + ) + + Write-Step "Copying shared modules..." + + if (Test-Path $SourcePath) { + Copy-Item -Path $SourcePath -Destination $DestPath -Recurse -Force -Exclude @("__pycache__", "*.pyc", "tests") + Write-Success "Shared modules copied" + } else { + Write-Warning "Shared modules not found at: $SourcePath" + } +} + +function Copy-ConfigTemplates { + param( + [string]$SourcePath, + [string]$DestPath + ) + + Write-Step "Copying config templates..." + + if (Test-Path $SourcePath) { + Copy-Item -Path $SourcePath -Destination $DestPath -Recurse -Force + Write-Success "Config templates copied" + } +} + +function Copy-DeploymentScripts { + param( + [string]$ScriptsSourcePath, + [string]$DestPath, + [string]$ComponentType + ) + + Write-Step "Copying deployment scripts..." + + $scriptsDir = Join-Path $DestPath "scripts" + New-Item -ItemType Directory -Path $scriptsDir -Force | Out-Null + + # Essential scripts for all deployments + $scripts = @( + "Install-ROA2WEB.ps1", + "Install-TelegramBot.ps1", + "Deploy-ROA2WEB.ps1", + "Deploy-TelegramBot.ps1", + "Manage-ROA2WEB.ps1" + ) + + # Add utility scripts for complete deployments + if ($ComponentType -eq "All" -or $ComponentType -eq "TelegramBot") { + $scripts += @( + "Backup-TelegramDB.ps1", + "Setup-DailyBackup.ps1", + "Setup-ClaudeAuth.ps1" + ) + } + + if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend") { + $scripts += @( + "Enable-HTTPS.ps1" + ) + } + + $copiedCount = 0 + foreach ($script in $scripts) { + $scriptPath = Join-Path $ScriptsSourcePath $script + if (Test-Path $scriptPath) { + Copy-Item -Path $scriptPath -Destination $scriptsDir -Force + $copiedCount++ + } else { + Write-Warning "Script not found: $script" + } + } + + Write-Success "Copied $copiedCount deployment scripts" +} + +function New-DeploymentReadme { + param( + [string]$DestPath, + [string]$ComponentType + ) + + Write-Step "Creating deployment README..." + + $componentDesc = switch ($ComponentType) { + "All" { "COMPLETE DEPLOYMENT PACKAGE (Frontend + Backend + Telegram Bot)" } + "Frontend" { "FRONTEND + BACKEND DEPLOYMENT PACKAGE" } + "Backend" { "BACKEND DEPLOYMENT PACKAGE" } + "TelegramBot" { "TELEGRAM BOT DEPLOYMENT PACKAGE" } + } + + $readme = @" +================================================================================ + ROA2WEB DEPLOYMENT PACKAGE + $componentDesc + Generated: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss") +================================================================================ + +CONTENTS: +--------- +"@ + + if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend") { + $readme += @" + + backend/ FastAPI backend application (Python) + frontend/ Vue.js static files (production build) + shared/ Shared Python modules (auth, database, utils) + config/ Configuration templates (.env, web.config) +"@ + } + + if ($ComponentType -eq "All" -or $ComponentType -eq "TelegramBot") { + $readme += @" + + telegram-bot/ Telegram bot application +"@ + } + + $readme += @" + + scripts/ PowerShell deployment scripts + +DEPLOYMENT SCRIPTS: +------------------- + Install-ROA2WEB.ps1 First-time backend + frontend setup + Install-TelegramBot.ps1 First-time Telegram bot setup + Deploy-ROA2WEB.ps1 Update backend + frontend + Deploy-TelegramBot.ps1 Update Telegram bot + Manage-ROA2WEB.ps1 Unified service management (start/stop/restart) +"@ + + if ($ComponentType -eq "All" -or $ComponentType -eq "TelegramBot") { + $readme += @" + + Backup-TelegramDB.ps1 Backup Telegram bot database + Setup-DailyBackup.ps1 Schedule automated backups + Setup-ClaudeAuth.ps1 Configure Claude API credentials +"@ + } + + $readme += @" + + +================================================================================ +DEPLOYMENT WORKFLOW +================================================================================ + +>> FIRST TIME INSTALLATION: +--------------------------- +"@ + + if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend") { + $readme += @" + +1. Install Main Application (Backend + Frontend): + cd scripts + .\Install-ROA2WEB.ps1 + +2. Configure environment: + notepad C:\inetpub\wwwroot\roa2web\backend\.env + +3. Start services: + .\Manage-ROA2WEB.ps1 -Action Start -Component Backend +"@ + } + + if ($ComponentType -eq "All" -or $ComponentType -eq "TelegramBot") { + $readme += @" + + +4. Install Telegram Bot: + .\Install-TelegramBot.ps1 + +5. Configure Telegram bot: + notepad C:\inetpub\wwwroot\roa2web\telegram-bot\.env + +6. Start Telegram bot: + .\Manage-ROA2WEB.ps1 -Action Start -Component TelegramBot +"@ + } + + $readme += @" + + +>> UPDATES: +----------- +cd scripts +.\Manage-ROA2WEB.ps1 -Action Stop +.\Deploy-ROA2WEB.ps1 # Updates backend + frontend +.\Deploy-TelegramBot.ps1 # Updates Telegram bot +.\Manage-ROA2WEB.ps1 -Action Start + +>> SERVICE MANAGEMENT: +---------------------- +# Start all services +.\Manage-ROA2WEB.ps1 -Action Start + +# Stop all services +.\Manage-ROA2WEB.ps1 -Action Stop + +# Restart backend only +.\Manage-ROA2WEB.ps1 -Action Restart -Component Backend + +# Check status +.\Manage-ROA2WEB.ps1 -Action Status + +================================================================================ +REQUIREMENTS +================================================================================ + - Windows Server 2016+ or Windows 10/11 + - IIS with URL Rewrite Module + - Python 3.11+ + - PowerShell 5.1+ (run as Administrator) + +NOTES: +------ + - Virtual environments created automatically during installation + - .env files preserved during updates + - Automatic backup before each update + - Default install location: C:\inetpub\wwwroot\roa2web\ + +TROUBLESHOOTING: +---------------- + Backend logs: C:\inetpub\wwwroot\roa2web\logs\ + Telegram logs: C:\inetpub\wwwroot\roa2web\telegram-bot\logs\ + IIS logs: C:\inetpub\logs\LogFiles\ + +For detailed documentation, see: deployment/windows/docs/WINDOWS_DEPLOYMENT.md + +================================================================================ +"@ + + $readmePath = Join-Path $DestPath "README.txt" + Set-Content -Path $readmePath -Value $readme -Force + Write-Success "Deployment README created" +} + +function New-DeploymentPackage { + param( + [string]$OutputPath, + [string]$ComponentType, + [hashtable]$Paths + ) + + Write-Step "Creating deployment package structure..." + + # Clean output if requested + if ($Clean -and (Test-Path $OutputPath)) { + Write-Warning "Cleaning output directory..." + Remove-Item -Path $OutputPath -Recurse -Force + } + + if (-not (Test-Path $OutputPath)) { + New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null + } + + # Build based on component type + switch ($ComponentType) { + "All" { + # Frontend + $frontendDistPath = Build-Frontend -SourcePath $Paths.FrontendSource + $frontendDest = Join-Path $OutputPath "frontend" + New-Item -ItemType Directory -Path $frontendDest -Force | Out-Null + Write-Step "Copying frontend files..." + Copy-Item -Path "$frontendDistPath\*" -Destination $frontendDest -Recurse -Force + Write-Success "Frontend files copied" + + # Backend + $backendDest = Join-Path $OutputPath "backend" + Copy-BackendFiles -SourcePath $Paths.BackendSource -DestPath $backendDest + + # Shared modules + $sharedDest = Join-Path $OutputPath "shared" + Copy-SharedModules -SourcePath $Paths.SharedSource -DestPath $sharedDest + + # Config templates + $configDest = Join-Path $OutputPath "config" + Copy-ConfigTemplates -SourcePath $Paths.ConfigSource -DestPath $configDest + + # Telegram Bot + $telegramDest = Join-Path $OutputPath "telegram-bot" + Copy-TelegramBotFiles -SourcePath $Paths.TelegramBotSource -DestPath $telegramDest + } + + "Frontend" { + # Frontend build + $frontendDistPath = Build-Frontend -SourcePath $Paths.FrontendSource + $frontendDest = Join-Path $OutputPath "frontend" + New-Item -ItemType Directory -Path $frontendDest -Force | Out-Null + Write-Step "Copying frontend files..." + Copy-Item -Path "$frontendDistPath\*" -Destination $frontendDest -Recurse -Force + Write-Success "Frontend files copied" + + # Backend + $backendDest = Join-Path $OutputPath "backend" + Copy-BackendFiles -SourcePath $Paths.BackendSource -DestPath $backendDest + + # Shared modules + $sharedDest = Join-Path $OutputPath "shared" + Copy-SharedModules -SourcePath $Paths.SharedSource -DestPath $sharedDest + + # Config templates + $configDest = Join-Path $OutputPath "config" + Copy-ConfigTemplates -SourcePath $Paths.ConfigSource -DestPath $configDest + } + + "Backend" { + # Backend only + $backendDest = Join-Path $OutputPath "backend" + Copy-BackendFiles -SourcePath $Paths.BackendSource -DestPath $backendDest + + # Shared modules + $sharedDest = Join-Path $OutputPath "shared" + Copy-SharedModules -SourcePath $Paths.SharedSource -DestPath $sharedDest + + # Config templates + $configDest = Join-Path $OutputPath "config" + Copy-ConfigTemplates -SourcePath $Paths.ConfigSource -DestPath $configDest + } + + "TelegramBot" { + # Telegram Bot only + $telegramDest = Join-Path $OutputPath "telegram-bot" + Copy-TelegramBotFiles -SourcePath $Paths.TelegramBotSource -DestPath $telegramDest + } + } + + # Copy deployment scripts + Copy-DeploymentScripts -ScriptsSourcePath $PSScriptRoot -DestPath $OutputPath -ComponentType $ComponentType + + # Create README + New-DeploymentReadme -DestPath $OutputPath -ComponentType $ComponentType + + # Calculate package size + $packageFiles = Get-ChildItem -Path $OutputPath -Recurse -File + $packageSize = ($packageFiles | Measure-Object -Property Length -Sum).Sum / 1MB + + Write-Success "Deployment package created" + Write-Success "Total files: $(($packageFiles).Count)" + Write-Success "Total size: $([math]::Round($packageSize, 2)) MB" + + return $OutputPath +} + +# ============================================================================= +# MAIN BUILD FLOW +# ============================================================================= + +function Main { + $banner = @" + + ==================================================================== + ROA2WEB - Unified Build Script (v2.0) + Building: $Component + ==================================================================== + +"@ + Write-Host $banner -ForegroundColor Cyan + + try { + # Resolve paths + $paths = @{ + BackendSource = Resolve-FullPath -Path $config.BackendSource + FrontendSource = Resolve-FullPath -Path $config.FrontendSource + TelegramBotSource = Resolve-FullPath -Path $config.TelegramBotSource + SharedSource = Resolve-FullPath -Path $config.SharedSource + ConfigSource = Resolve-FullPath -Path $config.ConfigSource + } + + $outputFullPath = if ([System.IO.Path]::IsPathRooted($OutputPath)) { $OutputPath } else { Resolve-FullPath -Path $OutputPath } + + Write-Host "`nConfiguration:" -ForegroundColor Yellow + Write-Host " Component: $Component" + Write-Host " Output Path: $outputFullPath" + + # Validate Node.js for frontend builds + if ($Component -eq "All" -or $Component -eq "Frontend") { + Test-NodeJS + } + + # Build package + $packagePath = New-DeploymentPackage ` + -OutputPath $outputFullPath ` + -ComponentType $Component ` + -Paths $paths + + # Show success + Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan + Write-Host " BUILD COMPLETED SUCCESSFULLY" -ForegroundColor Green + Write-Host ("=" * 70) -ForegroundColor Cyan + + Write-Host "`nDeployment Package: $packagePath" -ForegroundColor Yellow + Write-Host "`nNext Steps:" -ForegroundColor Yellow + Write-Host " 1. Transfer package to Windows Server" -ForegroundColor Gray + Write-Host " 2. On server, run deployment scripts from scripts/ directory" -ForegroundColor Gray + Write-Host " 3. Use Manage-ROA2WEB.ps1 for service management" -ForegroundColor Gray + + Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan + + } catch { + Write-Host "`n[BUILD FAILED] $_" -ForegroundColor Red + Write-Host $_.ScriptStackTrace -ForegroundColor Red + exit 1 + } +} + +# Run main build +Main diff --git a/deployment/windows/scripts/Build-TelegramBot.ps1 b/deployment/windows/scripts/Build-TelegramBot.ps1 index 617efd9..8d360cb 100644 --- a/deployment/windows/scripts/Build-TelegramBot.ps1 +++ b/deployment/windows/scripts/Build-TelegramBot.ps1 @@ -1,3 +1,24 @@ +<# +================================================================================ +⚠️ DEPRECATED - This script is deprecated in favor of Build-ROA2WEB.ps1 +================================================================================ + +This script is maintained for backward compatibility but will be removed in +a future version. Please use the new unified build script instead: + + .\Build-ROA2WEB.ps1 -Component TelegramBot + +The new script provides: + - Unified build process for all components + - Better parameter validation + - Consistent output structure + - Support for building All, Frontend, Backend, or TelegramBot + +For complete package: .\Build-ROA2WEB.ps1 -Component All + +================================================================================ +#> + <# .SYNOPSIS Build ROA2WEB Telegram Bot for Windows Server Deployment diff --git a/deployment/windows/scripts/Manage-ROA2WEB.ps1 b/deployment/windows/scripts/Manage-ROA2WEB.ps1 new file mode 100644 index 0000000..5b8f293 --- /dev/null +++ b/deployment/windows/scripts/Manage-ROA2WEB.ps1 @@ -0,0 +1,498 @@ +<# +.SYNOPSIS + Unified Service Management for ROA2WEB Application + +.DESCRIPTION + Manages Windows services for ROA2WEB Backend and Telegram Bot. + Provides unified interface for start, stop, restart, and status operations. + +.PARAMETER Action + Action to perform: Start, Stop, Restart, Status + +.PARAMETER Component + Component(s) to manage: + - All (default): Manage both Backend and TelegramBot + - Backend: Manage only Backend service + - TelegramBot: Manage only Telegram Bot service + +.PARAMETER Timeout + Timeout in seconds for service operations (default: 30) + +.EXAMPLE + .\Manage-ROA2WEB.ps1 -Action Start + Start all services (Backend + TelegramBot) + +.EXAMPLE + .\Manage-ROA2WEB.ps1 -Action Stop -Component Backend + Stop only Backend service + +.EXAMPLE + .\Manage-ROA2WEB.ps1 -Action Restart -Component TelegramBot + Restart only Telegram Bot service + +.EXAMPLE + .\Manage-ROA2WEB.ps1 -Action Status + Show status of all services + +.NOTES + Author: ROA2WEB Team + Version: 2.0 (Unified Management Script) + Requires: Administrator privileges +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory=$true)] + [ValidateSet("Start", "Stop", "Restart", "Status")] + [string]$Action, + + [ValidateSet("All", "Backend", "TelegramBot")] + [string]$Component = "All", + + [int]$Timeout = 30 +) + +$ErrorActionPreference = "Stop" + +# ============================================================================= +# CONFIGURATION +# ============================================================================= + +$config = @{ + Backend = @{ + ServiceName = "ROA2WEB-Backend" + DisplayName = "ROA2WEB Backend" + HealthUrl = "http://localhost:8000/health" + HealthTimeout = 5 + } + TelegramBot = @{ + ServiceName = "ROA2WEB-TelegramBot" + DisplayName = "ROA2WEB Telegram Bot" + HealthUrl = "http://localhost:8002/internal/health" + HealthTimeout = 10 + } +} + +# ============================================================================= +# 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 Yellow +} + +function Test-Administrator { + $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent() + $principal = New-Object Security.Principal.WindowsPrincipal($currentUser) + return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) +} + +function Get-ServiceSafe { + param( + [string]$ServiceName + ) + + try { + return Get-Service -Name $ServiceName -ErrorAction Stop + } catch { + return $null + } +} + +function Test-HealthEndpoint { + param( + [string]$Url, + [int]$TimeoutSec + ) + + try { + $response = Invoke-WebRequest -Uri $Url -UseBasicParsing -TimeoutSec $TimeoutSec -ErrorAction Stop + + if ($response.StatusCode -eq 200) { + # Try to parse JSON if available + try { + $content = $response.Content | ConvertFrom-Json + return @{ + Success = $true + Status = $content.status + Details = $content + } + } catch { + return @{ + Success = $true + Status = "healthy" + Details = $null + } + } + } + + return @{ + Success = $false + Status = "unhealthy" + Details = $null + } + } catch { + return @{ + Success = $false + Status = "unreachable" + Details = $null + Error = $_.Exception.Message + } + } +} + +function Start-ServiceComponent { + param( + [string]$ComponentName, + [hashtable]$ComponentConfig + ) + + Write-Step "Starting $($ComponentConfig.DisplayName)..." + + $service = Get-ServiceSafe -ServiceName $ComponentConfig.ServiceName + + if (-not $service) { + Write-Error "Service '$($ComponentConfig.ServiceName)' not found" + Write-Warning "Run Install script first to create the service" + return $false + } + + if ($service.Status -eq "Running") { + Write-Success "Service is already running" + return $true + } + + try { + # Start service + Start-Service -Name $ComponentConfig.ServiceName + Write-Info "Service start command issued" + + # Wait for service to start + $elapsed = 0 + while ($service.Status -ne "Running" -and $elapsed -lt $Timeout) { + Start-Sleep -Seconds 1 + $service.Refresh() + $elapsed++ + if ($elapsed % 5 -eq 0) { + Write-Info "Waiting for service to start... ($elapsed/$Timeout)" + } + } + + if ($service.Status -eq "Running") { + Write-Success "Service started successfully" + + # Wait a bit for service to fully initialize + $waitTime = if ($ComponentName -eq "TelegramBot") { 5 } else { 3 } + Start-Sleep -Seconds $waitTime + + # Test health endpoint + $health = Test-HealthEndpoint -Url $ComponentConfig.HealthUrl -TimeoutSec $ComponentConfig.HealthTimeout + + if ($health.Success) { + Write-Success "Health check passed: $($health.Status)" + + # Show additional details for Telegram Bot + if ($ComponentName -eq "TelegramBot" -and $health.Details) { + if ($health.Details.database) { + Write-Success "Database: $($health.Details.database.status)" + } + } + } else { + Write-Warning "Health check failed: $($health.Status) (service may still be starting)" + if ($health.Error) { + Write-Warning "Error: $($health.Error)" + } + } + + return $true + } else { + Write-Error "Service failed to start (Status: $($service.Status))" + return $false + } + } catch { + Write-Error "Failed to start service: $_" + return $false + } +} + +function Stop-ServiceComponent { + param( + [string]$ComponentName, + [hashtable]$ComponentConfig + ) + + Write-Step "Stopping $($ComponentConfig.DisplayName)..." + + $service = Get-ServiceSafe -ServiceName $ComponentConfig.ServiceName + + if (-not $service) { + Write-Error "Service '$($ComponentConfig.ServiceName)' not found" + return $false + } + + if ($service.Status -eq "Stopped") { + Write-Success "Service is already stopped" + return $true + } + + try { + # Stop service + Stop-Service -Name $ComponentConfig.ServiceName -Force + Write-Info "Service stop command issued" + + # Wait for service to stop + $elapsed = 0 + while ($service.Status -ne "Stopped" -and $elapsed -lt $Timeout) { + Start-Sleep -Seconds 1 + $service.Refresh() + $elapsed++ + if ($elapsed % 5 -eq 0) { + Write-Info "Waiting for service to stop... ($elapsed/$Timeout)" + } + } + + if ($service.Status -eq "Stopped") { + Write-Success "Service stopped successfully" + return $true + } else { + Write-Error "Service did not stop within timeout (Status: $($service.Status))" + Write-Warning "You may need to force kill the process" + return $false + } + } catch { + Write-Error "Failed to stop service: $_" + return $false + } +} + +function Restart-ServiceComponent { + param( + [string]$ComponentName, + [hashtable]$ComponentConfig + ) + + Write-Step "Restarting $($ComponentConfig.DisplayName)..." + + # Stop service + $stopResult = Stop-ServiceComponent -ComponentName $ComponentName -ComponentConfig $ComponentConfig + + if (-not $stopResult) { + Write-Error "Failed to stop service, aborting restart" + return $false + } + + # Wait a moment + Start-Sleep -Seconds 2 + + # Start service + $startResult = Start-ServiceComponent -ComponentName $ComponentName -ComponentConfig $ComponentConfig + + if ($startResult) { + Write-Success "Service restarted successfully" + return $true + } else { + Write-Error "Failed to start service after stop" + return $false + } +} + +function Get-ServiceStatus { + param( + [string]$ComponentName, + [hashtable]$ComponentConfig + ) + + $service = Get-ServiceSafe -ServiceName $ComponentConfig.ServiceName + + $statusInfo = @{ + Component = $ComponentConfig.DisplayName + ServiceName = $ComponentConfig.ServiceName + Status = "Not Installed" + StartType = "N/A" + Health = "Unknown" + HealthDetails = $null + } + + if ($service) { + $statusInfo.Status = $service.Status + $statusInfo.StartType = $service.StartType + + if ($service.Status -eq "Running") { + # Test health endpoint + $health = Test-HealthEndpoint -Url $ComponentConfig.HealthUrl -TimeoutSec $ComponentConfig.HealthTimeout + $statusInfo.Health = $health.Status + $statusInfo.HealthDetails = $health.Details + } + } + + return $statusInfo +} + +function Show-ServiceStatus { + param( + [string]$ComponentName, + [hashtable]$ComponentConfig + ) + + $status = Get-ServiceStatus -ComponentName $ComponentName -ComponentConfig $ComponentConfig + + Write-Host "`n$($status.Component):" -ForegroundColor Cyan + Write-Host " Service Name: $($status.ServiceName)" -ForegroundColor Gray + + # Color-code status + $statusColor = switch ($status.Status) { + "Running" { "Green" } + "Stopped" { "Yellow" } + "Not Installed" { "Red" } + default { "Gray" } + } + Write-Host " Status: $($status.Status)" -ForegroundColor $statusColor + Write-Host " Start Type: $($status.StartType)" -ForegroundColor Gray + + if ($status.Status -eq "Running") { + $healthColor = switch ($status.Health) { + "healthy" { "Green" } + "ok" { "Green" } + "unhealthy" { "Red" } + "unreachable" { "Yellow" } + default { "Gray" } + } + Write-Host " Health: $($status.Health)" -ForegroundColor $healthColor + + # Show additional details for Telegram Bot + if ($ComponentName -eq "TelegramBot" -and $status.HealthDetails) { + if ($status.HealthDetails.database) { + Write-Host " Database: $($status.HealthDetails.database.status)" -ForegroundColor Gray + } + if ($status.HealthDetails.telegram) { + Write-Host " Telegram: $($status.HealthDetails.telegram.status)" -ForegroundColor Gray + } + } + } +} + +# ============================================================================= +# MAIN EXECUTION +# ============================================================================= + +function Main { + $banner = @" + + ==================================================================== + ROA2WEB - Service Management (v2.0) + Action: $Action | Component: $Component + ==================================================================== + +"@ + Write-Host $banner -ForegroundColor Cyan + + # Check administrator privileges + if (-not (Test-Administrator)) { + Write-Error "This script requires Administrator privileges" + Write-Host "`nPlease run PowerShell as Administrator and try again." -ForegroundColor Yellow + exit 1 + } + + # Determine which components to manage + $components = @() + switch ($Component) { + "All" { + $components = @( + @{ Name = "Backend"; Config = $config.Backend }, + @{ Name = "TelegramBot"; Config = $config.TelegramBot } + ) + } + "Backend" { + $components = @( + @{ Name = "Backend"; Config = $config.Backend } + ) + } + "TelegramBot" { + $components = @( + @{ Name = "TelegramBot"; Config = $config.TelegramBot } + ) + } + } + + # Execute action + $allSuccess = $true + + switch ($Action) { + "Start" { + foreach ($comp in $components) { + $result = Start-ServiceComponent -ComponentName $comp.Name -ComponentConfig $comp.Config + if (-not $result) { + $allSuccess = $false + } + } + } + + "Stop" { + foreach ($comp in $components) { + $result = Stop-ServiceComponent -ComponentName $comp.Name -ComponentConfig $comp.Config + if (-not $result) { + $allSuccess = $false + } + } + } + + "Restart" { + foreach ($comp in $components) { + $result = Restart-ServiceComponent -ComponentName $comp.Name -ComponentConfig $comp.Config + if (-not $result) { + $allSuccess = $false + } + } + } + + "Status" { + foreach ($comp in $components) { + Show-ServiceStatus -ComponentName $comp.Name -ComponentConfig $comp.Config + } + + Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan + exit 0 + } + } + + # Show final status + Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan + + if ($allSuccess) { + Write-Host " OPERATION COMPLETED SUCCESSFULLY" -ForegroundColor Green + Write-Host ("=" * 70) -ForegroundColor Cyan + exit 0 + } else { + Write-Host " OPERATION COMPLETED WITH ERRORS" -ForegroundColor Red + Write-Host ("=" * 70) -ForegroundColor Cyan + Write-Host "`nSome services may require manual intervention." -ForegroundColor Yellow + Write-Host "Check service logs for details:" -ForegroundColor Yellow + Write-Host " Backend: C:\inetpub\wwwroot\roa2web\logs\" -ForegroundColor Gray + Write-Host " Telegram Bot: C:\inetpub\wwwroot\roa2web\telegram-bot\logs\" -ForegroundColor Gray + exit 1 + } +} + +# Run main +Main diff --git a/deployment/windows/scripts/README.md b/deployment/windows/scripts/README.md new file mode 100644 index 0000000..ad31399 --- /dev/null +++ b/deployment/windows/scripts/README.md @@ -0,0 +1,449 @@ +# 🛠️ ROA2WEB Windows Deployment Scripts + +Complete reference for ROA2WEB Windows deployment PowerShell scripts (v2.0 - Unified System). + +## 📋 Script Overview + +### 🔨 Build Scripts + +#### **Build-ROA2WEB.ps1** ⭐ (UNIFIED - Recommended) +**Purpose**: Unified build script for all components + +**Usage**: +```powershell +# Build complete package (default) +.\Build-ROA2WEB.ps1 + +# Build specific components +.\Build-ROA2WEB.ps1 -Component Frontend # Frontend + Backend +.\Build-ROA2WEB.ps1 -Component Backend # Backend only +.\Build-ROA2WEB.ps1 -Component TelegramBot # Telegram Bot only + +# Custom output path +.\Build-ROA2WEB.ps1 -OutputPath "D:\builds\roa2web-$(Get-Date -Format 'yyyyMMdd')" +``` + +**Parameters**: +- `-Component` All|Frontend|Backend|TelegramBot (default: All) +- `-OutputPath` (default: `./deploy-package`) +- `-Clean` $true|$false (default: $true) + +**Output**: Creates `deploy-package/` with complete deployment files + +--- + +#### Build-Frontend.ps1 ⚠️ DEPRECATED +**Status**: Deprecated in favor of `Build-ROA2WEB.ps1 -Component Frontend` + +Use: `.\Build-ROA2WEB.ps1 -Component Frontend` instead + +--- + +#### Build-TelegramBot.ps1 ⚠️ DEPRECATED +**Status**: Deprecated in favor of `Build-ROA2WEB.ps1 -Component TelegramBot` + +Use: `.\Build-ROA2WEB.ps1 -Component TelegramBot` instead + +--- + +### 🚀 Installation Scripts + +#### **Install-ROA2WEB.ps1** +**Purpose**: First-time installation of Backend + Frontend + +**Usage**: +```powershell +.\Install-ROA2WEB.ps1 + +# Custom parameters +.\Install-ROA2WEB.ps1 -InstallPath "C:\Apps\roa2web" -ServicePort 8000 +``` + +**What it does**: +1. Installs Chocolatey, Python 3.11+, NSSM +2. Installs IIS URL Rewrite & ARR modules +3. Creates directory structure +4. Creates Python virtual environment +5. Installs Python dependencies +6. Creates Windows Service (ROA2WEB-Backend) +7. Configures IIS website & application + +**Parameters**: +- `-InstallPath` (default: `C:\inetpub\wwwroot\roa2web`) +- `-ServicePort` (default: 8000) +- `-IISSiteName`, `-IISAppName` +- `-CreateNewSite`, `-SkipPython`, `-SkipIIS` + +--- + +#### **Install-TelegramBot.ps1** +**Purpose**: First-time installation of Telegram Bot + +**Usage**: +```powershell +.\Install-TelegramBot.ps1 + +# Custom parameters +.\Install-TelegramBot.ps1 -InstallPath "C:\Apps\telegram-bot" -ServicePort 8002 +``` + +**What it does**: +1. Validates Python 3.11+ installation +2. Installs NSSM (if needed) +3. Creates directory structure (data/, logs/, backups/) +4. Creates Python virtual environment +5. Installs Python dependencies +6. Creates Windows Service (ROA2WEB-TelegramBot) +7. Creates .env template + +**Parameters**: +- `-InstallPath` (default: `C:\inetpub\wwwroot\roa2web\telegram-bot`) +- `-ServicePort` (default: 8002) +- `-SourcePath` (auto-detected) + +--- + +### 📦 Deployment Scripts + +#### **Deploy-ROA2WEB.ps1** +**Purpose**: Deploy updates to existing Backend + Frontend + +**Usage**: +```powershell +# Auto-detects source path (if run from deploy-package/scripts/) +.\Deploy-ROA2WEB.ps1 + +# Explicit source path +.\Deploy-ROA2WEB.ps1 -SourcePath "C:\Deploy\roa2web-v2" + +# Disable automatic restart +.\Deploy-ROA2WEB.ps1 -RestartService $false +``` + +**What it does**: +1. Creates backup of current deployment +2. Stops backend service +3. Updates backend & frontend files (preserves .env) +4. Checks requirements.txt - updates dependencies if changed +5. Restarts backend service +6. Tests health endpoint +7. Cleans old backups (keeps last 10) + +**Parameters**: +- `-InstallPath` (default: `C:\inetpub\wwwroot\roa2web`) +- `-SourcePath` (auto-detected from script location) +- `-BackupEnabled`, `-RestartService`, `-UpdateBackend`, `-UpdateFrontend` +- `-ForceInstallDependencies` + +--- + +#### **Deploy-TelegramBot.ps1** +**Purpose**: Deploy updates to existing Telegram Bot + +**Usage**: +```powershell +# Auto-detects source path +.\Deploy-TelegramBot.ps1 + +# With automatic rollback on failure +.\Deploy-TelegramBot.ps1 -RollbackOnFailure $true +``` + +**What it does**: +1. Creates backup (app/, requirements.txt, .env, database) +2. Stops bot service +3. Removes old app/ directory +4. Copies new app/ files +5. Checks requirements.txt - updates dependencies if changed +6. Preserves .env (never overwrites) +7. Updates management scripts +8. Restarts service +9. Tests health endpoint +10. **Automatic rollback** on failure (if enabled) +11. Cleans old backups (keeps last 10) + +**Parameters**: +- `-InstallPath` (default: `C:\inetpub\wwwroot\roa2web\telegram-bot`) +- `-SourcePath` (auto-detected) +- `-BackupEnabled`, `-RestartService`, `-RollbackOnFailure` + +--- + +### ⚙️ Service Management + +#### **Manage-ROA2WEB.ps1** ⭐ (UNIFIED - Recommended) +**Purpose**: Unified service management for all components + +**Usage**: +```powershell +# Start all services +.\Manage-ROA2WEB.ps1 -Action Start + +# Stop all services +.\Manage-ROA2WEB.ps1 -Action Stop + +# Restart all services +.\Manage-ROA2WEB.ps1 -Action Restart + +# Check status of all services +.\Manage-ROA2WEB.ps1 -Action Status + +# Manage specific component +.\Manage-ROA2WEB.ps1 -Action Start -Component Backend +.\Manage-ROA2WEB.ps1 -Action Restart -Component TelegramBot +.\Manage-ROA2WEB.ps1 -Action Status -Component Backend +``` + +**Parameters**: +- `-Action` Start|Stop|Restart|Status (required) +- `-Component` All|Backend|TelegramBot (default: All) +- `-Timeout` (default: 30 seconds) + +**Features**: +- ✅ Health checks after start operations +- ✅ Colored status output +- ✅ Detailed error messages +- ✅ Administrator privilege verification + +--- + +#### Start-ROA2WEB.ps1 ⚠️ REMOVED +**Status**: Removed - Use `Manage-ROA2WEB.ps1 -Action Start -Component Backend` + +--- + +#### Stop-ROA2WEB.ps1 ⚠️ REMOVED +**Status**: Removed - Use `Manage-ROA2WEB.ps1 -Action Stop -Component Backend` + +--- + +#### Restart-ROA2WEB.ps1 ⚠️ REMOVED +**Status**: Removed - Use `Manage-ROA2WEB.ps1 -Action Restart -Component Backend` + +--- + +#### Start-TelegramBot.ps1 ⚠️ REMOVED +**Status**: Removed - Use `Manage-ROA2WEB.ps1 -Action Start -Component TelegramBot` + +--- + +#### Stop-TelegramBot.ps1 ⚠️ REMOVED +**Status**: Removed - Use `Manage-ROA2WEB.ps1 -Action Stop -Component TelegramBot` + +--- + +#### Restart-TelegramBot.ps1 ⚠️ REMOVED +**Status**: Removed - Use `Manage-ROA2WEB.ps1 -Action Restart -Component TelegramBot` + +--- + +### 🛠️ Utility Scripts + +#### **Backup-TelegramDB.ps1** +**Purpose**: Backup Telegram bot SQLite database + +**Usage**: +```powershell +# Basic backup +.\Backup-TelegramDB.ps1 + +# Compressed backup +.\Backup-TelegramDB.ps1 -Compress $true + +# Keep more backups +.\Backup-TelegramDB.ps1 -RetentionCount 20 +``` + +**What it does**: +1. Stops bot service gracefully +2. Creates timestamped backup of `telegram_bot.db` +3. Optionally compresses backup +4. Restarts service +5. Cleans old backups (configurable retention) + +--- + +#### **Setup-DailyBackup.ps1** +**Purpose**: Schedule automated daily database backups + +**Usage**: +```powershell +# Setup daily backup at 2 AM +.\Setup-DailyBackup.ps1 + +# Custom time and retention +.\Setup-DailyBackup.ps1 -Time "03:00" -RetentionDays 30 +``` + +**What it does**: +1. Creates Windows Scheduled Task +2. Runs `Backup-TelegramDB.ps1` daily at specified time +3. Configurable time, retention, and compression + +--- + +#### **Setup-ClaudeAuth.ps1** +**Purpose**: Setup Claude API authentication for Telegram bot + +**Usage**: +```powershell +.\Setup-ClaudeAuth.ps1 +``` + +**What it does**: +1. **Method 1 (Recommended)**: Browser-based Claude Pro/Max login + - Runs `claude-code login` if available + - Copies credentials to bot installation directory +2. **Method 2**: Manual API key entry +3. Validates credentials +4. Updates .env file +5. Restarts bot service + +**Features**: +- ✅ Supports both Claude Pro/Max and API key +- ✅ Auto-detects credentials location +- ✅ Validates authentication before applying + +--- + +#### **Enable-HTTPS.ps1** +**Purpose**: Enable HTTPS for IIS website + +**Usage**: +```powershell +# Create self-signed certificate +.\Enable-HTTPS.ps1 + +# Use existing certificate +.\Enable-HTTPS.ps1 -CertPath "C:\Certs\roa2web.pfx" -CertPassword "password" +``` + +**What it does**: +1. Creates/imports SSL certificate +2. Configures HTTPS binding (port 443) +3. Enables HTTP to HTTPS redirect +4. Activates HSTS (HTTP Strict Transport Security) + +--- + +## 📊 Script Comparison Matrix + +| Feature | Build-ROA2WEB | Build-Frontend | Build-TelegramBot | Manage-ROA2WEB | Old Start/Stop | +|---------|---------------|----------------|-------------------|----------------|----------------| +| **Status** | ✅ Active | ⚠️ Deprecated | ⚠️ Deprecated | ✅ Active | 🗑️ Removed | +| **Components** | All | Frontend+Backend | TelegramBot | All | Single | +| **Unified** | ✅ Yes | ❌ No | ❌ No | ✅ Yes | ❌ No | +| **Flexible** | ✅ High | ⚠️ Medium | ⚠️ Medium | ✅ High | ❌ Low | +| **Health Checks** | ✅ Yes | ❌ No | ❌ No | ✅ Yes | ⚠️ Basic | + +--- + +## 🚀 Quick Reference + +### First-Time Deployment + +```powershell +# 1. Build on development machine +cd deployment/windows/scripts +.\Build-ROA2WEB.ps1 + +# 2. Transfer deploy-package/ to server + +# 3. Install on server (as Administrator) +cd C:\Deploy\deploy-package\scripts +.\Install-ROA2WEB.ps1 +.\Install-TelegramBot.ps1 + +# 4. Configure +notepad C:\inetpub\wwwroot\roa2web\backend\.env +notepad C:\inetpub\wwwroot\roa2web\telegram-bot\.env + +# 5. Start services +.\Manage-ROA2WEB.ps1 -Action Start +``` + +### Deploy Updates + +```powershell +# 1. Build new package on development machine +.\Build-ROA2WEB.ps1 + +# 2. Transfer to server + +# 3. Deploy (as Administrator) +cd C:\Deploy\new-package\scripts +.\Manage-ROA2WEB.ps1 -Action Stop +.\Deploy-ROA2WEB.ps1 +.\Deploy-TelegramBot.ps1 +.\Manage-ROA2WEB.ps1 -Action Start +``` + +### Daily Operations + +```powershell +# Check status +.\Manage-ROA2WEB.ps1 -Action Status + +# Restart services +.\Manage-ROA2WEB.ps1 -Action Restart + +# Restart specific component +.\Manage-ROA2WEB.ps1 -Action Restart -Component Backend + +# Backup database +.\Backup-TelegramDB.ps1 +``` + +--- + +## 📝 Notes + +- **Administrator Privileges**: All scripts require PowerShell as Administrator +- **Automatic Backups**: Deploy scripts create backups before updating +- **Health Checks**: Manage-ROA2WEB.ps1 validates services after starting +- **Rollback Support**: Deploy-TelegramBot.ps1 supports automatic rollback on failure +- **Configuration Preservation**: .env files are never overwritten during updates +- **Dependency Management**: Scripts only reinstall Python packages if requirements.txt changes + +--- + +## 🐛 Troubleshooting + +### Script Execution Policy Error + +```powershell +Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser +``` + +### Service Won't Start + +```powershell +# Check service status +.\Manage-ROA2WEB.ps1 -Action Status + +# View logs +Get-Content C:\inetpub\wwwroot\roa2web\logs\backend-stderr.log -Tail 50 +Get-Content C:\inetpub\wwwroot\roa2web\telegram-bot\logs\stderr.log -Tail 50 +``` + +### Build Fails + +- Ensure Node.js 16+ is installed (for Frontend builds) +- Close VS Code and IDEs (file locks) +- Run as Administrator + +--- + +## 📚 Documentation + +- **Deployment Package Guide**: [`../DEPLOY_PACKAGE.md`](../DEPLOY_PACKAGE.md) +- **Complete Deployment Guide**: [`../docs/WINDOWS_DEPLOYMENT.md`](../docs/WINDOWS_DEPLOYMENT.md) +- **Troubleshooting**: [`../docs/TELEGRAM_BOT_TROUBLESHOOTING.md`](../docs/TELEGRAM_BOT_TROUBLESHOOTING.md) +- **Quick Start**: [`../README.md`](../README.md) +- **Project Documentation**: [`../../../CLAUDE.md`](../../../CLAUDE.md) + +--- + +**Version**: 2.0 (Unified System) +**Last Updated**: 2025-11-11 +**Author**: ROA2WEB Team diff --git a/deployment/windows/scripts/Restart-ROA2WEB.ps1 b/deployment/windows/scripts/Restart-ROA2WEB.ps1 deleted file mode 100644 index 72f5f4e..0000000 --- a/deployment/windows/scripts/Restart-ROA2WEB.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -<# -.SYNOPSIS - Restart ROA2WEB Backend Service - -.DESCRIPTION - Stops and starts the ROA2WEB backend Windows service. - -.EXAMPLE - .\Restart-ROA2WEB.ps1 -#> - -[CmdletBinding()] -param( - [string]$ServiceName = "ROA2WEB-Backend" -) - -$ErrorActionPreference = "Stop" - -Write-Host "`n[*] Restarting ROA2WEB Backend Service..." -ForegroundColor Cyan - -try { - # Stop service - Write-Host "`n[*] Stopping service..." -ForegroundColor Yellow - & "$PSScriptRoot\Stop-ROA2WEB.ps1" -ServiceName $ServiceName - - # Wait a moment - Start-Sleep -Seconds 2 - - # Start service - Write-Host "`n[*] Starting service..." -ForegroundColor Yellow - & "$PSScriptRoot\Start-ROA2WEB.ps1" -ServiceName $ServiceName - - Write-Host "`n[OK] Service restarted successfully" -ForegroundColor Green - exit 0 -} catch { - Write-Host "`n[ERROR] Failed to restart service: $_" -ForegroundColor Red - exit 1 -} diff --git a/deployment/windows/scripts/Restart-TelegramBot.ps1 b/deployment/windows/scripts/Restart-TelegramBot.ps1 deleted file mode 100644 index 53ebc95..0000000 --- a/deployment/windows/scripts/Restart-TelegramBot.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -<# -.SYNOPSIS - Restart ROA2WEB Telegram Bot Service - -.DESCRIPTION - Stops and starts the ROA2WEB Telegram Bot Windows service. - -.EXAMPLE - .\Restart-TelegramBot.ps1 -#> - -[CmdletBinding()] -param( - [string]$ServiceName = "ROA2WEB-TelegramBot" -) - -$ErrorActionPreference = "Stop" - -Write-Host "`n[*] Restarting ROA2WEB Telegram Bot Service..." -ForegroundColor Cyan - -try { - # Stop service - Write-Host "`n[*] Stopping service..." -ForegroundColor Yellow - & "$PSScriptRoot\Stop-TelegramBot.ps1" -ServiceName $ServiceName - - # Wait a moment - Start-Sleep -Seconds 2 - - # Start service - Write-Host "`n[*] Starting service..." -ForegroundColor Yellow - & "$PSScriptRoot\Start-TelegramBot.ps1" -ServiceName $ServiceName - - Write-Host "`n[OK] Service restarted successfully" -ForegroundColor Green - exit 0 -} catch { - Write-Host "`n[ERROR] Failed to restart service: $_" -ForegroundColor Red - exit 1 -} diff --git a/deployment/windows/scripts/Start-ROA2WEB.ps1 b/deployment/windows/scripts/Start-ROA2WEB.ps1 deleted file mode 100644 index 0e6a693..0000000 --- a/deployment/windows/scripts/Start-ROA2WEB.ps1 +++ /dev/null @@ -1,66 +0,0 @@ -<# -.SYNOPSIS - Start ROA2WEB Backend Service - -.DESCRIPTION - Starts the ROA2WEB backend Windows service and validates it's running properly. - -.EXAMPLE - .\Start-ROA2WEB.ps1 -#> - -[CmdletBinding()] -param( - [string]$ServiceName = "ROA2WEB-Backend", - [int]$Timeout = 30 -) - -$ErrorActionPreference = "Stop" - -Write-Host "`n[*] Starting ROA2WEB Backend Service..." -ForegroundColor Cyan - -try { - $service = Get-Service -Name $ServiceName -ErrorAction Stop - - if ($service.Status -eq "Running") { - Write-Host " [OK] Service is already running" -ForegroundColor Green - exit 0 - } - - # Start service - Start-Service -Name $ServiceName - Write-Host " [*] Service start command issued" -ForegroundColor Yellow - - # Wait for service to start - $elapsed = 0 - while ($service.Status -ne "Running" -and $elapsed -lt $Timeout) { - Start-Sleep -Seconds 1 - $service.Refresh() - $elapsed++ - Write-Host " [*] Waiting for service to start... ($elapsed/$Timeout)" -ForegroundColor Yellow - } - - if ($service.Status -eq "Running") { - Write-Host " [OK] Service started successfully" -ForegroundColor Green - - # Wait a bit and test health endpoint - Start-Sleep -Seconds 3 - try { - $response = Invoke-WebRequest -Uri "http://localhost:8000/health" -UseBasicParsing -TimeoutSec 5 - if ($response.StatusCode -eq 200) { - Write-Host " [OK] Health check passed" -ForegroundColor Green - } - } catch { - Write-Host " [WARN] Health check failed (service may still be starting)" -ForegroundColor Yellow - } - - exit 0 - } else { - Write-Host " [ERROR] Service failed to start (Status: $($service.Status))" -ForegroundColor Red - Write-Host " Check logs: C:\inetpub\wwwroot\roa2web\logs\backend-stderr.log" -ForegroundColor Yellow - exit 1 - } -} catch { - Write-Host " [ERROR] Failed to start service: $_" -ForegroundColor Red - exit 1 -} diff --git a/deployment/windows/scripts/Start-TelegramBot.ps1 b/deployment/windows/scripts/Start-TelegramBot.ps1 deleted file mode 100644 index 22a9638..0000000 --- a/deployment/windows/scripts/Start-TelegramBot.ps1 +++ /dev/null @@ -1,70 +0,0 @@ -<# -.SYNOPSIS - Start ROA2WEB Telegram Bot Service - -.DESCRIPTION - Starts the ROA2WEB Telegram Bot Windows service and validates it's running properly. - -.EXAMPLE - .\Start-TelegramBot.ps1 -#> - -[CmdletBinding()] -param( - [string]$ServiceName = "ROA2WEB-TelegramBot", - [int]$Timeout = 30, - [int]$HealthPort = 8002 -) - -$ErrorActionPreference = "Stop" - -Write-Host "`n[*] Starting ROA2WEB Telegram Bot Service..." -ForegroundColor Cyan - -try { - $service = Get-Service -Name $ServiceName -ErrorAction Stop - - if ($service.Status -eq "Running") { - Write-Host " [OK] Service is already running" -ForegroundColor Green - exit 0 - } - - # Start service - Start-Service -Name $ServiceName - Write-Host " [*] Service start command issued" -ForegroundColor Yellow - - # Wait for service to start - $elapsed = 0 - while ($service.Status -ne "Running" -and $elapsed -lt $Timeout) { - Start-Sleep -Seconds 1 - $service.Refresh() - $elapsed++ - Write-Host " [*] Waiting for service to start... ($elapsed/$Timeout)" -ForegroundColor Yellow - } - - if ($service.Status -eq "Running") { - Write-Host " [OK] Service started successfully" -ForegroundColor Green - - # Wait a bit and test health endpoint - Start-Sleep -Seconds 5 - try { - $response = Invoke-WebRequest -Uri "http://localhost:$HealthPort/internal/health" -UseBasicParsing -TimeoutSec 10 - if ($response.StatusCode -eq 200) { - $content = $response.Content | ConvertFrom-Json - Write-Host " [OK] Health check passed: $($content.status)" -ForegroundColor Green - Write-Host " [OK] Database: $($content.database.status)" -ForegroundColor Green - } - } catch { - Write-Host " [WARN] Health check failed (service may still be starting): $_" -ForegroundColor Yellow - Write-Host " Check logs: C:\inetpub\wwwroot\roa2web\telegram-bot\logs\stderr.log" -ForegroundColor Yellow - } - - exit 0 - } else { - Write-Host " [ERROR] Service failed to start (Status: $($service.Status))" -ForegroundColor Red - Write-Host " Check logs: C:\inetpub\wwwroot\roa2web\telegram-bot\logs\stderr.log" -ForegroundColor Yellow - exit 1 - } -} catch { - Write-Host " [ERROR] Failed to start service: $_" -ForegroundColor Red - exit 1 -} diff --git a/deployment/windows/scripts/Stop-ROA2WEB.ps1 b/deployment/windows/scripts/Stop-ROA2WEB.ps1 deleted file mode 100644 index 8a059f0..0000000 --- a/deployment/windows/scripts/Stop-ROA2WEB.ps1 +++ /dev/null @@ -1,54 +0,0 @@ -<# -.SYNOPSIS - Stop ROA2WEB Backend Service - -.DESCRIPTION - Stops the ROA2WEB backend Windows service gracefully. - -.EXAMPLE - .\Stop-ROA2WEB.ps1 -#> - -[CmdletBinding()] -param( - [string]$ServiceName = "ROA2WEB-Backend", - [int]$Timeout = 30 -) - -$ErrorActionPreference = "Stop" - -Write-Host "`n[*] Stopping ROA2WEB Backend Service..." -ForegroundColor Cyan - -try { - $service = Get-Service -Name $ServiceName -ErrorAction Stop - - if ($service.Status -eq "Stopped") { - Write-Host " [OK] Service is already stopped" -ForegroundColor Green - exit 0 - } - - # Stop service - Stop-Service -Name $ServiceName -Force - Write-Host " [*] Service stop command issued" -ForegroundColor Yellow - - # Wait for service to stop - $elapsed = 0 - while ($service.Status -ne "Stopped" -and $elapsed -lt $Timeout) { - Start-Sleep -Seconds 1 - $service.Refresh() - $elapsed++ - Write-Host " [*] Waiting for service to stop... ($elapsed/$Timeout)" -ForegroundColor Yellow - } - - if ($service.Status -eq "Stopped") { - Write-Host " [OK] Service stopped successfully" -ForegroundColor Green - exit 0 - } else { - Write-Host " [ERROR] Service did not stop within timeout (Status: $($service.Status))" -ForegroundColor Red - Write-Host " You may need to force kill the process" -ForegroundColor Yellow - exit 1 - } -} catch { - Write-Host " [ERROR] Failed to stop service: $_" -ForegroundColor Red - exit 1 -} diff --git a/deployment/windows/scripts/Stop-TelegramBot.ps1 b/deployment/windows/scripts/Stop-TelegramBot.ps1 deleted file mode 100644 index 799ff29..0000000 --- a/deployment/windows/scripts/Stop-TelegramBot.ps1 +++ /dev/null @@ -1,54 +0,0 @@ -<# -.SYNOPSIS - Stop ROA2WEB Telegram Bot Service - -.DESCRIPTION - Stops the ROA2WEB Telegram Bot Windows service gracefully. - -.EXAMPLE - .\Stop-TelegramBot.ps1 -#> - -[CmdletBinding()] -param( - [string]$ServiceName = "ROA2WEB-TelegramBot", - [int]$Timeout = 30 -) - -$ErrorActionPreference = "Stop" - -Write-Host "`n[*] Stopping ROA2WEB Telegram Bot Service..." -ForegroundColor Cyan - -try { - $service = Get-Service -Name $ServiceName -ErrorAction Stop - - if ($service.Status -eq "Stopped") { - Write-Host " [OK] Service is already stopped" -ForegroundColor Green - exit 0 - } - - # Stop service - Stop-Service -Name $ServiceName -Force - Write-Host " [*] Service stop command issued" -ForegroundColor Yellow - - # Wait for service to stop - $elapsed = 0 - while ($service.Status -ne "Stopped" -and $elapsed -lt $Timeout) { - Start-Sleep -Seconds 1 - $service.Refresh() - $elapsed++ - Write-Host " [*] Waiting for service to stop... ($elapsed/$Timeout)" -ForegroundColor Yellow - } - - if ($service.Status -eq "Stopped") { - Write-Host " [OK] Service stopped successfully" -ForegroundColor Green - exit 0 - } else { - Write-Host " [ERROR] Service did not stop within timeout (Status: $($service.Status))" -ForegroundColor Red - Write-Host " You may need to force kill the process" -ForegroundColor Yellow - exit 1 - } -} catch { - Write-Host " [ERROR] Failed to stop service: $_" -ForegroundColor Red - exit 1 -}