fix(zioinfo): add /var/www/zioinfo copy step in deploy + restore stash files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
DESKTOP-TKLFCPR\ython 2026-06-01 20:42:12 +09:00
parent ea51238c1d
commit 53f34835f1
4 changed files with 294 additions and 1 deletions

View File

@ -0,0 +1,101 @@
"""stash에서 핵심 파일만 추출 → 빌드 → 배포"""
import paramiko, sys, time, shutil, os
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()
def run(label, cmd, timeout=60):
print(f'\n[{label}]')
_, o, e = c.exec_command(cmd, timeout=timeout)
out = o.read().decode('utf-8','replace').strip()
if out: print(out[:600])
return out
SRC = '/opt/zioinfo/src'
# 1. stash에서 frontend 파일만 직접 추출
run('stash에서 Company.jsx 추출',
f'git -C {SRC} checkout stash -- frontend/src/pages/Company.jsx 2>&1 || echo FAIL')
run('stash에서 Company.css 추출',
f'git -C {SRC} checkout stash -- frontend/src/pages/Company.css 2>&1 || echo FAIL')
run('stash에서 Home.jsx 추출 (변경 있으면)',
f'git -C {SRC} checkout stash -- frontend/src/pages/Home.jsx 2>&1 || echo SKIP')
run('stash에서 java 파일 추출',
f'''git -C {SRC} checkout stash -- \
backend/src/main/java/kr/co/zioinfo/web/config/DataInitializer.java \
backend/src/main/java/kr/co/zioinfo/web/controller/AdminController.java \
backend/src/main/java/kr/co/zioinfo/web/controller/ApiController.java 2>&1 || echo SKIP''')
# 2. 추출된 파일 확인
run('Company.jsx 줄 수', f'wc -l {SRC}/frontend/src/pages/Company.jsx 2>/dev/null')
run('변경된 파일 확인', f'git -C {SRC} diff --stat HEAD 2>/dev/null | head -10')
# 3. npm 빌드 + /var/www/zioinfo 복사
run('npm 빌드',
f'cd {SRC}/frontend && npm run build 2>&1 | tail -5', timeout=120)
run('/var/www/zioinfo 복사',
f'cp -r {SRC}/backend/src/main/resources/static/. /var/www/zioinfo/ && echo "copied $(ls /var/www/zioinfo/assets | wc -l) files"')
# 4. 로컬로 파일 다운로드
print('\n[로컬 workspace 업데이트]')
key_files = [
'frontend/src/pages/Company.jsx',
'frontend/src/pages/Company.css',
'frontend/src/pages/Home.jsx',
'backend/src/main/java/kr/co/zioinfo/web/config/DataInitializer.java',
'backend/src/main/java/kr/co/zioinfo/web/controller/AdminController.java',
'backend/src/main/java/kr/co/zioinfo/web/controller/ApiController.java',
]
downloaded = []
for f in key_files:
remote = f'{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)
print(f' OK: {f}')
downloaded.append(f)
except Exception as e:
print(f' SKIP {f}: {e}')
# 5. repos commit + Gitea bundle push
if downloaded:
import subprocess
subprocess.run(['git', '-C', 'C:/GUARDiA/repos/zioinfo-web', 'add', '-A'])
r = subprocess.run(['git', '-C', 'C:/GUARDiA/repos/zioinfo-web', 'status', '--short'],
capture_output=True, text=True)
if r.stdout.strip():
subprocess.run(['git', '-C', 'C:/GUARDiA/repos/zioinfo-web', 'commit',
'-m', 'restore: extract Company.jsx and backend from server stash'])
print('\n[repos 커밋 완료]')
# bundle push
bundle = 'C:/GUARDiA/repos/zioinfo-web.bundle'
subprocess.run(['git', '-C', 'C:/GUARDiA/repos/zioinfo-web', 'bundle', 'create', bundle, '--all'])
sftp.put(bundle, '/tmp/zioinfo-web.bundle')
os.remove(bundle)
run('Gitea push',
"rm -rf /tmp/zw_push && git clone /tmp/zioinfo-web.bundle /tmp/zw_push 2>/dev/null && "
"cd /tmp/zw_push && "
"git remote set-url origin 'http://zio:Zio%40Admin2026%21@127.0.0.1:9003/zio/zioinfo-web.git' && "
"git push origin main --force 2>&1 | tail -3 && "
"rm -rf /tmp/zw_push /tmp/zioinfo-web.bundle && echo 'pushed'", timeout=120)
else:
print('\n변경 없음 (이미 최신)')
# 6. Spring Boot 재시작 (mvn build는 시간 오래 걸리므로 스킵, /var/www만 업데이트)
run('zioinfo 서비스 재시작', 'systemctl restart zioinfo && sleep 3 && systemctl is-active zioinfo')
# 7. 최종 확인
run('Company.jsx 최신 (greeting 내용)',
f'grep -c "안녕하십니까\|홍영택" {SRC}/frontend/src/pages/Company.jsx 2>/dev/null')
run('/var/www/zioinfo 최신 파일',
'ls -la /var/www/zioinfo/assets/ | sort -k6,7 -r | head -5')
sftp.close()
c.close()
print('\n=== 완료 ===')

View File

@ -0,0 +1,74 @@
"""deploy_server.py zioinfo-web에 /var/www/zioinfo 복사 단계 추가"""
import paramiko, sys, time
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)
def run(label, cmd, timeout=60):
print(f'\n[{label}]')
_, o, _ = c.exec_command(cmd, timeout=timeout)
print(o.read().decode('utf-8','replace').strip()[:600])
# 현재 npm build 이후 단계 확인
run('현재 zioinfo npm build 이후 단계',
"grep -n 'npm build\\|mvn\\|deploy jar\\|www\\|static\\|copy\\|cp ' "
"/opt/zioinfo/deploy_server.py | head -15")
# deploy_server.py 수정: npm build 후 /var/www/zioinfo에 복사 추가
run('deploy_server.py 수정',
r"""python3 << 'PYEOF'
with open('/opt/zioinfo/deploy_server.py', 'r') as f:
content = f.read()
# npm build 다음에 copy to /var/www/zioinfo 추가
OLD = ''' ("npm build", ["bash", "-c",
f"cd {SRC}/frontend && npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps && npm run build"]),
("mvn package", ["bash", "-c",'''
NEW = ''' ("npm build", ["bash", "-c",
f"cd {SRC}/frontend && npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps && npm run build"]),
("copy to www", ["bash", "-c",
f"cp -r {SRC}/backend/src/main/resources/static/. /var/www/zioinfo/ && echo 'copied'"]),
("mvn package", ["bash", "-c",'''
if OLD in content:
content = content.replace(OLD, NEW)
with open('/opt/zioinfo/deploy_server.py', 'w') as f:
f.write(content)
print('수정 완료')
else:
# 이미 있거나 형식이 다름 - 직접 확인
idx = content.find('npm build')
print(f'npm build 위치: {idx}')
print(content[idx:idx+300])
PYEOF
""")
run('수정 결과 확인',
"grep -n 'npm build\\|copy to www\\|var/www\\|mvn package' /opt/zioinfo/deploy_server.py | head -10")
# 서비스 재시작
run('서비스 재시작',
'systemctl restart zioinfo-deploy && sleep 2 && systemctl is-active zioinfo-deploy')
# zioinfo-web 즉시 재배포 트리거
run('zioinfo-web 재배포 트리거',
"curl -sf -X POST http://localhost:9999 "
"-H 'Content-Type: application/json' "
"-H 'X-Gitea-Event: push' "
"-d '{\"repository\":{\"name\":\"zioinfo-web\"},\"ref\":\"refs/heads/main\"}' 2>/dev/null")
# 배포 완료 대기 (npm build + mvn package는 시간이 걸림)
print('\n배포 진행 중 (최대 3분)...')
for i in range(20):
time.sleep(10)
_, o, _ = c.exec_command('tail -3 /var/log/zioinfo/deploy.log 2>/dev/null', timeout=10)
last = o.read().decode('utf-8','replace').strip()
print(f' [{i*10}s] {last.splitlines()[-1] if last else "..."}')
if '배포 완료' in last or 'health check' in last and '완료' in last:
break
run('배포 로그 최종', 'tail -15 /var/log/zioinfo/deploy.log 2>/dev/null')
run('/var/www/zioinfo 업데이트 확인', 'ls -la /var/www/zioinfo/assets/ | tail -3')
c.close()

View File

@ -0,0 +1,118 @@
"""서버 stash 복원 → 파일 추출 → 로컬 workspace 업데이트 → Gitea push → 배포"""
import paramiko, sys, time, 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()
GITEA_B64 = base64.b64encode(b'zio:Zio@Admin2026!').decode()
def run(label, cmd, timeout=30):
print(f'\n[{label}]')
_, o, e = c.exec_command(cmd, timeout=timeout)
out = o.read().decode('utf-8','replace').strip()
err = e.read().decode('utf-8','replace').strip()
if out: print(out[:600])
if err and 'warning' not in err.lower() and 'hint' not in err.lower():
bad = [l for l in err.splitlines() if not any(k in l.lower() for k in ['warn','hint','note'])]
if bad: print(f' ERR: {bad[-1][:200]}')
return out
# 1. stash pop (충돌 시 ours 전략으로)
run('stash pop 시도',
'cd /opt/zioinfo/src && '
'git stash pop 2>&1 | head -20')
# 2. 충돌 파일 확인 및 처리
run('충돌 파일 확인',
'cd /opt/zioinfo/src && git status --short 2>/dev/null | head -20')
# 충돌 시 stash의 버전을 우선 적용
run('충돌 해결 (stash 버전 우선)',
"""cd /opt/zioinfo/src
if git status --short 2>/dev/null | grep -q '^UU\|^AA\|^DD'; then
git checkout --theirs . 2>/dev/null
git add . 2>/dev/null
echo "충돌 해결: stash 버전 적용"
else
echo "충돌 없음"
fi
git status --short | head -10
""")
# 3. 변경된 핵심 파일 확인
run('변경된 파일 (frontend)',
'cd /opt/zioinfo/src && git diff HEAD --name-only -- frontend/ 2>/dev/null | head -20')
# 4. 핵심 파일들을 로컬로 가져오기
print('\n[핵심 파일 다운로드]')
key_files = [
'frontend/src/pages/Company.jsx',
'frontend/src/pages/Company.css',
'backend/src/main/java/kr/co/zioinfo/web/config/DataInitializer.java',
'backend/src/main/java/kr/co/zioinfo/web/controller/AdminController.java',
'backend/src/main/java/kr/co/zioinfo/web/controller/ApiController.java',
]
import os
updated = []
for f in key_files:
remote_path = f'/opt/zioinfo/src/{f}'
local_path = f'C:/GUARDiA/workspace/zioinfo-web/{f}'
local_dir = os.path.dirname(local_path)
os.makedirs(local_dir, exist_ok=True)
try:
sftp.get(remote_path, local_path)
print(f' 다운로드: {f}')
updated.append(f)
except Exception as e:
print(f' SKIP {f}: {e}')
# 5. repos/zioinfo-web에도 복사
print('\n[repos/zioinfo-web 업데이트]')
for f in updated:
src = f'C:/GUARDiA/workspace/zioinfo-web/{f}'
dst = f'C:/GUARDiA/repos/zioinfo-web/{f}'
dst_dir = os.path.dirname(dst)
os.makedirs(dst_dir, exist_ok=True)
import shutil
shutil.copy2(src, dst)
print(f' 복사: {f}')
# 6. repos/zioinfo-web commit
import subprocess
result = subprocess.run(
['git', '-C', 'C:/GUARDiA/repos/zioinfo-web', 'status', '--short'],
capture_output=True, text=True)
if result.stdout.strip():
subprocess.run(['git', '-C', 'C:/GUARDiA/repos/zioinfo-web', 'add', '-A'])
subprocess.run(['git', '-C', 'C:/GUARDiA/repos/zioinfo-web', 'commit',
'-m', 'restore: recover yesterday work from server stash'])
print('\n[repos 커밋 완료]')
else:
print('\n변경 없음 - stash가 이미 반영된 상태')
# 7. 서버에서 직접 빌드 + /var/www/zioinfo 업데이트
run('서버 직접 빌드 + 배포',
"""cd /opt/zioinfo/src
# npm build
echo "=npm build="
cd frontend && npm run build 2>&1 | tail -3
cd ..
# copy to www
echo "=copy to www="
cp -r backend/src/main/resources/static/. /var/www/zioinfo/
echo "=copy done="
ls /var/www/zioinfo/assets/ | wc -l
""", timeout=120)
# 8. 서비스 재시작
run('서비스 재시작', 'systemctl restart zioinfo && sleep 5 && systemctl is-active zioinfo')
# 9. 확인
run('/var/www/zioinfo 업데이트 확인',
'ls -la /var/www/zioinfo/assets/ | sort -k6,7 | tail -5')
sftp.close()
c.close()
print('\n=== 완료 ===')

View File

@ -23,7 +23,7 @@ pipeline {
} }
} }
stage('Deploy') { stage('Deploy') {
when { branch 'main' } when { expression { env.GIT_BRANCH ==~ /.*main/ || env.BRANCH_NAME == 'main' } }
steps { steps {
sh """ sh """
rsync -a --exclude=__pycache__ --exclude=.git \ rsync -a --exclude=__pycache__ --exclude=.git \