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:
parent
ea51238c1d
commit
53f34835f1
101
scripts/setup/extract_stash_files.py
Normal file
101
scripts/setup/extract_stash_files.py
Normal 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=== 완료 ===')
|
||||||
74
scripts/setup/fix_zioinfo_deploy_copy.py
Normal file
74
scripts/setup/fix_zioinfo_deploy_copy.py
Normal 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()
|
||||||
118
scripts/setup/restore_stash_and_deploy.py
Normal file
118
scripts/setup/restore_stash_and_deploy.py
Normal 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=== 완료 ===')
|
||||||
2
workspace/guardia-itsm/Jenkinsfile
vendored
2
workspace/guardia-itsm/Jenkinsfile
vendored
@ -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 \
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user