TorbatYar/scripts/deploy_session_fix.py
Mortezakoohjani 12c8615615 Ship enterprise Accounting FE/API with CRUD parity and production wiring.
Adds accounting-service PATCH/archive, fiscal helpers, COA templates and setup status, plus SuperApp Accounting UI (DS, scoreboard, masters, vouchers, ledger, ops modules) with session refresh and HTTPS public API URLs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 15:26:43 +03:30

95 lines
3.4 KiB
Python

#!/usr/bin/env python3
"""Deploy session-refresh fix: identity-access + frontend."""
from __future__ import annotations
import base64
import os
import tarfile
from pathlib import Path
import paramiko
ROOT = Path(__file__).resolve().parents[1]
APP_HOST, APP_USER, APP_PASS = "192.168.10.162", "morteza", "Moli@5404"
REMOTE = "/home/morteza/torbatyar"
EXCLUDE_DIRS = {".git", "node_modules", ".next", ".venv", "venv", "__pycache__", ".pytest_cache", ".mypy_cache", ".ruff_cache", ".idea", ".vscode"}
EXCLUDE_FILES = {".DS_Store", "Thumbs.db", ".env"}
def connect():
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect(APP_HOST, username=APP_USER, password=APP_PASS, timeout=30, allow_agent=False, look_for_keys=False)
return c
def run(c, cmd, timeout=1200):
cmd = cmd.replace("\r\n", "\n").replace("\r", "\n").strip() + "\n"
b64 = base64.b64encode(cmd.encode()).decode()
full = f"echo {APP_PASS!r} | sudo -S -p '' bash -c 'echo {b64} | base64 -d | bash'"
print("\n>>>", cmd[:200].replace("\n", " | "))
_, out, err = c.exec_command(full, timeout=timeout, get_pty=True)
text = (out.read() + err.read()).decode("utf-8", "replace")
code = out.channel.recv_exit_status()
print(text[-4500:].encode("ascii", "replace").decode("ascii"))
return code
def make_tarball() -> Path:
out = ROOT / "scripts" / "_deploy_session_bundle.tar.gz"
with tarfile.open(out, "w:gz") as tar:
for dirpath, dirnames, filenames in os.walk(ROOT):
p = Path(dirpath)
dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIRS and not d.startswith(".cursor")]
for name in filenames:
fp = p / name
rel = fp.relative_to(ROOT)
if any(part in EXCLUDE_DIRS for part in rel.parts):
continue
if rel.name in EXCLUDE_FILES or rel.suffix in {".pyc", ".log"}:
continue
if rel.as_posix().startswith("scripts/_deploy"):
continue
tar.add(fp, arcname=str(rel).replace("\\", "/"))
print(f"bundle {out.stat().st_size/1024/1024:.1f} MB")
return out
def main() -> int:
tarball = make_tarball()
c = connect()
try:
sftp = c.open_sftp()
sftp.put(str(tarball), "/tmp/torbatyar_session_bundle.tar.gz")
sftp.close()
if run(
c,
f"""
set -e
cd {REMOTE}
cp -a .env /tmp/ty.env.bak
tar -xzf /tmp/torbatyar_session_bundle.tar.gz -C {REMOTE}
cp /tmp/ty.env.bak .env
rm -f /tmp/torbatyar_session_bundle.tar.gz
docker compose up -d --build --force-recreate identity-access-service frontend
sleep 8
curl -sf http://127.0.0.1:8001/health
echo
# refresh endpoint must exist (401/422 without body is fine; 404 means missing)
code=$(curl -s -o /dev/null -w '%{{http_code}}' -X POST http://127.0.0.1:8001/api/v1/auth/refresh -H 'Content-Type: application/json' -d '{{}}')
echo refresh_endpoint_http=$code
curl -s -o /dev/null -w 'frontend=%{{http_code}}\\n' http://127.0.0.1:3000/accounting
docker compose ps identity-access-service frontend
""",
timeout=1800,
):
raise RuntimeError("deploy failed")
finally:
c.close()
print("\n=== SESSION FIX DEPLOYED ===")
return 0
if __name__ == "__main__":
raise SystemExit(main())