zioinfo-mail/scripts/setup/fix_all_systems.py
2026-06-01 21:55:48 +09:00

180 lines
8.1 KiB
Python

"""system-sync-orchestrator: 검증 결과 기반 수정 실행"""
import paramiko, sys, time, subprocess, shutil, os, json, base64
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect('101.79.17.164', username='root', password='1q2w3e!Q', timeout=15)
sftp = c.open_sftp()
G = base64.b64encode(b'zio:Zio@Admin2026!').decode()
def run(label, cmd, timeout=120):
print(f'\n [{label}]')
_, o, e = c.exec_command(cmd, timeout=timeout)
out = o.read().decode('utf-8','replace').strip()
if out: print(' ' + out[:400])
return out
results = {}
# ── 1. guardia-itsm: APP_SRC_DRIFT 수정 ────────────────────
print('\n━━ FIX 1: guardia-itsm APP_SRC_DRIFT ━━')
# rpa_rules.json, embed_codebase.py는 app에서만 생성되는 런타임 파일 → src에서도 생성 경로 동기화
run('rpa 폴더 확인', 'ls /opt/guardia/src/routers/rpa.py 2>/dev/null && echo exists || echo missing')
run('rsync src→app (런타임 파일 제외)',
'rsync -a --delete '
'--exclude=__pycache__ --exclude=.git --exclude="*.db" '
'--exclude="uploads" --exclude=".env" --exclude=".pytest_cache" '
'--exclude="rpa_rules.json" --exclude="rpa/" '
'/opt/guardia/src/ /opt/guardia/app/ 2>&1 | tail -3')
run('guardia 재기동', 'systemctl restart guardia && sleep 4 && systemctl is-active guardia')
# 재검증
diff = run('app vs src 재검증',
'diff -rq /opt/guardia/src /opt/guardia/app '
'--exclude="*.pyc" --exclude="__pycache__" --exclude=".git" '
'--exclude="*.db" --exclude="uploads" --exclude=".env" '
'--exclude=".pytest_cache" --exclude="rpa_rules.json" --exclude="rpa" '
'2>/dev/null | head -5 || echo "동일"')
results['guardia-itsm'] = '✅ 동기화 완료' if '동일' in diff else f'⚠️ {diff[:80]}'
print(f' 결과: {results["guardia-itsm"]}')
# ── 2. guardia-manager: STALE_WWW 수정 ─────────────────────
print('\n━━ FIX 2: guardia-manager STALE_WWW 재빌드 ━━')
# workspace/guardia-manager의 최신 frontend를 서버에 업로드
# repos/guardia-manager에서 bundle → server → git pull → npm build
run('Manager src 확인',
'ls /opt/manager/backend/main.py 2>/dev/null && echo "backend OK" || echo "backend MISSING"')
run('Manager frontend 확인',
'ls /opt/manager/frontend/package.json 2>/dev/null && echo "frontend OK" || echo "frontend MISSING"')
# repos/guardia-manager에서 최신 코드 가져와 서버에 업로드
# 이미 Gitea에 올라가 있으므로 서버에서 직접 클론
GITEA_URL = 'http://zio:Zio%40Admin2026%21@127.0.0.1:9003/zio/guardia-manager.git'
run('Manager 소스 clone/pull',
f'''if [ -d /opt/manager/frontend/.git ]; then
git -C /opt/manager/frontend fetch origin main && git -C /opt/manager/frontend reset --hard origin/main
elif [ -d /tmp/mgr_src ]; then
rm -rf /tmp/mgr_src
fi
[ -d /opt/manager/frontend/src ] && echo "frontend src OK" || echo "frontend src MISSING"
''')
# workspace의 guardia-manager frontend를 bundle로 서버에 전송
print('\n workspace/guardia-manager bundle 서버 전송 중...')
bundle_path = 'C:/GUARDiA/repos/guardia-manager.bundle'
result = subprocess.run(
['git', '-C', 'C:/GUARDiA/repos/guardia-manager', 'bundle', 'create', bundle_path, '--all'],
capture_output=True)
if result.returncode == 0:
size = os.path.getsize(bundle_path) // 1024
print(f' bundle {size}KB → 서버 전송...')
sftp.put(bundle_path, '/tmp/mgr.bundle')
os.remove(bundle_path)
run('서버에서 Manager 클론',
'rm -rf /tmp/mgr_work && '
'git clone /tmp/mgr.bundle /tmp/mgr_work 2>/dev/null && '
'echo "clone OK" && ls /tmp/mgr_work/ | head -5')
# frontend 빌드
run('Manager frontend 빌드',
'cd /tmp/mgr_work/frontend && '
'npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps && '
'npm run build 2>&1 | tail -5', timeout=300)
# /var/www/manager 복사
run('www/manager 복사',
'mkdir -p /var/www/manager && '
'cp -r /tmp/mgr_work/frontend/dist/. /var/www/manager/ && '
f'stat /var/www/manager/index.html | grep Modify')
# backend도 업데이트
run('Manager backend 업데이트',
'cp -r /tmp/mgr_work/backend/. /opt/manager/backend/ 2>/dev/null || true && '
'rm -rf /tmp/mgr_work /tmp/mgr.bundle')
run('Manager 서비스 재기동',
'systemctl restart guardia-manager && sleep 4 && systemctl is-active guardia-manager')
www_date = run('www/manager 날짜 확인',
'stat /var/www/manager/index.html 2>/dev/null | grep Modify')
results['guardia-manager'] = f'✅ www 갱신: {www_date[:30]}' if 'Jun 1' in www_date or 'Jun 1' in www_date else f'⚠️ {www_date}'
else:
results['guardia-manager'] = '❌ bundle 생성 실패'
print(f' ❌ bundle 오류: {result.stderr.decode()[:100]}')
print(f' 결과: {results["guardia-manager"]}')
# ── 3. zioinfo-web: stash + uncommitted 정리 ───────────────
print('\n━━ FIX 3: zioinfo-web stash 정리 + 스크린샷 반영 ━━')
# uncommitted 파일 목록
uncommit = run('uncommitted 파일 목록',
"git -C /opt/zioinfo/src status --short 2>/dev/null | "
"grep -v 'static/assets/' | grep -v '.pyc'")
# logo_bottom.png, 스크린샷 → workspace로 다운로드 후 커밋
new_files = [l.strip().split()[-1] for l in uncommit.splitlines()
if '??' in l or 'M ' in l]
print(f' 새 파일: {new_files}')
downloaded = []
for f in new_files:
if not f: continue
remote = f'/opt/zioinfo/src/{f}'
local_ws = f'C:/GUARDiA/workspace/zioinfo-web/{f}'
local_repo = f'C:/GUARDiA/repos/zioinfo-web/{f}'
try:
os.makedirs(os.path.dirname(local_ws), exist_ok=True)
os.makedirs(os.path.dirname(local_repo), exist_ok=True)
sftp.get(remote, local_ws)
shutil.copy2(local_ws, local_repo)
downloaded.append(f)
print(f' 다운로드: {f}')
except Exception as e:
print(f' SKIP {f}: {e}')
# stash 처리: 빌드 산출물만 있으면 drop
stash_stat = run('stash 내용', 'git -C /opt/zioinfo/src stash show --stat 2>/dev/null | head -10')
only_assets = all('static/assets' in l or 'Jenkinsfile' in l
for l in stash_stat.splitlines() if '|' in l)
if only_assets:
run('stash drop (빌드 산출물만)', 'git -C /opt/zioinfo/src stash drop 2>/dev/null && echo "dropped"')
results['zioinfo-web-stash'] = '✅ stash drop (빌드산출물)'
else:
# 중요 파일이 있으면 보존
results['zioinfo-web-stash'] = '⚠️ stash 보존 (중요 파일 포함) - 수동 확인 필요'
print(f' stash 보존: {stash_stat[:200]}')
# 서버 uncommitted 파일 add & commit
if new_files:
run('uncommitted 파일 commit',
'cd /opt/zioinfo/src && '
'git add backend/src/main/resources/static/logo_bottom.png '
'backend/src/main/resources/static/screenshots/ 2>/dev/null; '
'git config user.email "ci@zioinfo.co.kr"; '
'git config user.name "CI Bot"; '
'git diff --cached --stat 2>/dev/null; '
'git commit -m "chore: add screenshots and logo assets" 2>/dev/null || echo "nothing to commit"')
results['zioinfo-web'] = f'{len(downloaded)}개 파일 반영'
print(f' 결과: {results["zioinfo-web"]}')
# ── 최종 요약 ────────────────────────────────────────────────
print('\n' + '='*55)
print('수정 결과 요약')
print('='*55)
for sys_name, result in results.items():
print(f' {result} [{sys_name}]')
# fix_report 저장
os.makedirs('C:/GUARDiA/.claude/agents/_workspace', exist_ok=True)
with open('C:/GUARDiA/.claude/agents/_workspace/fix_report.json', 'w', encoding='utf-8') as f:
json.dump({"timestamp": __import__('datetime').datetime.now().isoformat(),
"results": results}, f, ensure_ascii=False, indent=2)
sftp.close()
c.close()
print('\n=== 수정 완료 ===')