#!/usr/bin/env python3 """Deploy Webhook 서버에 guardia-itsm 배포 스텝 추가""" import paramiko, time, sys HOST='101.79.17.164'; USER='root'; PASS='1q2w3e!Q' client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(HOST, username=USER, password=PASS, timeout=15) sftp = client.open_sftp() def run(label, cmd, timeout=30): print(f'[{label}]') chan = client.get_transport().open_session() chan.set_combine_stderr(True) chan.exec_command(cmd) start = time.time() while not chan.exit_status_ready(): if chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096)); sys.stdout.flush() if time.time()-start > timeout: break time.sleep(0.3) while chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096)) sys.stdout.flush() chan.recv_exit_status() new_deploy_server = '''#!/usr/bin/env python3 """ ZioInfo + GUARDiA CI/CD Webhook Server 포트: 9999 - zioinfo-web push → 홈페이지 빌드/배포 - guardia-itsm push → GUARDiA ITSM 재배포 """ import http.server, subprocess, threading, json, hmac, hashlib, logging, os SECRET = b"zioinfo-deploy-2026" ZIOINFO_SRC = "/opt/zioinfo/src" GUARDIA_SRC = "/opt/guardia/src" LOG = "/var/log/zioinfo/deploy.log" logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", handlers=[logging.FileHandler(LOG), logging.StreamHandler()]) def deploy_zioinfo(): logging.info("=== zioinfo-web 배포 시작 ===") steps = [ ("git pull", ["git", "-C", ZIOINFO_SRC, "pull", "origin", "main"]), ("npm build", ["bash", "-c", f"cd {ZIOINFO_SRC}/frontend && npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps && npm run build"]), ("mvn package", ["bash", "-c", f"cd {ZIOINFO_SRC}/backend && /usr/bin/mvn clean package -DskipTests -q"]), ("deploy jar", ["bash", "-c", f"cp {ZIOINFO_SRC}/backend/target/zioinfo-web-*.jar /opt/zioinfo/app/app.jar"]), ("deploy static", ["bash", "-c", f"cp -r {ZIOINFO_SRC}/backend/src/main/resources/static/. /var/www/zioinfo/"]), ("restart", ["systemctl", "restart", "zioinfo"]), ] for name, cmd in steps: logging.info(f"[{name}] 실행 중...") r = subprocess.run(cmd, capture_output=True, text=True, timeout=600) if r.returncode != 0: logging.error(f"[{name}] 실패: {r.stderr[-300:]}") return False logging.info(f"[{name}] 완료") logging.info("=== zioinfo-web 배포 완료 ===") return True def deploy_guardia(): logging.info("=== GUARDiA ITSM 배포 시작 ===") steps = [ ("git clone/pull", ["bash", "-c", f"[ -d {GUARDIA_SRC}/.git ] && git -C {GUARDIA_SRC} pull origin main " f"|| git clone http://zio:Zio%40Admin2026%21@localhost:3000/zio/guardia-itsm.git {GUARDIA_SRC}"]), ("rsync", ["bash", "-c", f"rsync -a --exclude=__pycache__ --exclude=*.db --exclude=.git " f"{GUARDIA_SRC}/ /opt/guardia/app/"]), ("pip install", ["/opt/guardia/venv/bin/pip", "install", "-r", "/opt/guardia/app/requirements.txt", "-q"]), ("restart", ["systemctl", "restart", "guardia"]), ] for name, cmd in steps: logging.info(f"[{name}] 실행 중...") r = subprocess.run(cmd, capture_output=True, text=True, timeout=300) if r.returncode != 0: logging.error(f"[{name}] 실패: {r.stderr[-300:]}") return False logging.info(f"[{name}] 완료") logging.info("=== GUARDiA ITSM 배포 완료 ===") return True class WebhookHandler(http.server.BaseHTTPRequestHandler): def do_POST(self): length = int(self.headers.get("Content-Length", 0)) body = self.rfile.read(length) sig = self.headers.get("X-Gitea-Signature", "") expected = hmac.new(SECRET, body, hashlib.sha256).hexdigest() if sig and not hmac.compare_digest(sig, expected): self.send_response(403); self.end_headers(); return self.send_response(202); self.end_headers() self.wfile.write(b"Deploy queued") # 어떤 저장소인지 판단 try: payload = json.loads(body) repo = payload.get("repository", {}).get("name", "") except Exception: repo = "" if "guardia" in repo.lower(): threading.Thread(target=deploy_guardia, daemon=True).start() else: threading.Thread(target=deploy_zioinfo, daemon=True).start() def log_message(self, fmt, *args): logging.info(fmt % args) if __name__ == "__main__": os.makedirs("/var/log/zioinfo", exist_ok=True) logging.info("ZioInfo + GUARDiA Deploy Webhook 서버 시작 (포트 9999)") server = http.server.HTTPServer(("0.0.0.0", 9999), WebhookHandler) server.serve_forever() ''' with sftp.open('/opt/zioinfo/deploy_server.py', 'w') as f: f.write(new_deploy_server) sftp.close() run('Deploy 서버 재시작', 'systemctl restart zioinfo-deploy && sleep 3 && systemctl is-active zioinfo-deploy') run('Webhook 테스트', 'curl -s -X POST http://localhost:9999/ -d "{}" -w " HTTP %{http_code}"') client.close() print('완료: Deploy Webhook 서버 업데이트 (zioinfo + guardia 모두 지원)')