#!/usr/bin/env python3 import paramiko import os import tarfile import io from pathlib import Path import time # Server details HOST = '5.0.0.181' USER = 'root' PASSWORD = 'Ozzyos1bsd3' REMOTE_PATH = '/opt/Frontend/meeting-assistant-fe/' try: print('[1] Connecting to server...') ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(HOST, username=USER, password=PASSWORD, timeout=30) print(f' ✓ Connected to {HOST}') # Stop and remove container print('[2] Stopping and removing container...') stdin, stdout, stderr = ssh.exec_command('podman stop meeting-assistant-fe && podman rm meeting-assistant-fe 2>/dev/null || true') stdout.channel.recv_exit_status() print(' ✓ Container stopped and removed') # Create tar archive in memory print('[3] Creating tar archive of project...') tar_buffer = io.BytesIO() with tarfile.open(fileobj=tar_buffer, mode='w:gz') as tar: project_dir = Path('.') exclude_dirs = {'node_modules', '.git', '.next', 'dist', '.env', '.env.local', '.DS_Store'} for item in project_dir.rglob('*'): # Skip excluded directories if any(excl in item.parts for excl in exclude_dirs): continue if item.is_file(): arcname = str(item.relative_to(project_dir)) tar.add(item, arcname=arcname) tar_buffer.seek(0) tar_size = len(tar_buffer.getvalue()) print(f' ✓ Archive created ({tar_size / 1024 / 1024:.2f} MB)') # Upload via SFTP print('[4] Uploading project to server...') sftp = ssh.open_sftp() remote_tar = f'{REMOTE_PATH}project.tar.gz' sftp.putfo(tar_buffer, remote_tar) sftp.close() print(f' ✓ Uploaded to {remote_tar}') # Extract on server print('[5] Extracting archive on server...') stdin, stdout, stderr = ssh.exec_command(f'cd {REMOTE_PATH} && tar -xzf project.tar.gz && rm project.tar.gz') stdout.channel.recv_exit_status() print(' ✓ Archive extracted') # Rebuild image print('[6] Rebuilding Docker image...') stdin, stdout, stderr = ssh.exec_command(f'cd {REMOTE_PATH} && podman build -t meeting-assistant-fe . 2>&1') build_output = stdout.read().decode() build_err = stderr.read().decode() exit_code = stdout.channel.recv_exit_status() if exit_code != 0: print(f' ⚠️ Build warnings/info:\n{build_output}\n{build_err}') print(' ✓ Image built') # Start container print('[7] Starting new container...') stdin, stdout, stderr = ssh.exec_command('podman run -d --name meeting-assistant-fe --restart unless-stopped -p 3010:80 meeting-assistant-fe') container_id = stdout.read().decode().strip() stdout.channel.recv_exit_status() print(f' ✓ Container started (ID: {container_id[:12]}...)') # Wait for container to be ready time.sleep(2) # Verify print('[8] Verifying deployment...') stdin, stdout, stderr = ssh.exec_command('curl -s -o /dev/null -w "%{http_code}" http://localhost:3010/') exit_code = stdout.channel.recv_exit_status() response = stdout.read().decode().strip() print(f' ✓ Response code: {response}') if response == '200': print('\n✅ Deployment successful! PWA is live at http://5.0.0.181:3010/') else: print(f'\n⚠️ Unexpected response code: {response}') # Check container logs stdin, stdout, stderr = ssh.exec_command('podman logs meeting-assistant-fe --tail 20') logs = stdout.read().decode() print(f'Container logs:\n{logs}') ssh.close() except Exception as e: print(f'\n❌ Deployment failed: {e}') import traceback traceback.print_exc()