103 lines
3.7 KiB
Python
103 lines
3.7 KiB
Python
#!/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()
|