[BUILD] v0.4.3.5 - 버전 관리 규정 추가 및 운영 스크립트 작성
This commit is contained in:
parent
e817951c07
commit
b66a79f555
@ -51,4 +51,48 @@ SMART IMS 플랫폼의 모든 배포와 업데이트는 아래의 **MAJOR.MINOR.
|
||||
## 💡 버전 비교 및 업데이트 공지 원칙
|
||||
1. 플랫폼은 원격 저장소의 최신 태그 버전과 현재 설치된 버전의 **4자리를 순차적으로 비교**합니다.
|
||||
2. 상위 자리수가 더 높을 경우 즉시 시스템 업데이트 안내를 발생시킵니다.
|
||||
3. 모든 버전은 `v` 접두사를 포함하여 관리하나, 비교 시에는 숫자로 정규화하여 처리합니다.
|
||||
3. 모든 버전은 `v` 접두사를 포함하여 관리하나, 비교 시에는 숫자로 정규화하여 처리합니다.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 배포 및 태그 생성 절차 (Standard Deployment Procedure)
|
||||
|
||||
> **경고**: 이 절차를 위반할 경우 운영 서버에서 업데이트가 누락되거나 버전 불일치가 발생할 수 있습니다.
|
||||
|
||||
### [Step 1] 사전 검증 (Pre-check)
|
||||
1. **작업 내용 커밋 확인**: `git status` 명령어로 커밋되지 않은(Unstaged/Modified) 파일이 없는지 확인합니다.
|
||||
- ❌ 실수 패턴: 코드를 수정하고 저장만 한 뒤, 커밋 없이 태그를 생성하면 **구버전 코드**가 배포됩니다.
|
||||
|
||||
2. **버전 번호 동기화 (필수)**: 아래 2개 파일의 `version` 필드를 배포할 버전 번호(예: `0.4.3.5`)로 직접 수정합니다.
|
||||
- `root/package.json`
|
||||
- `root/server/package.json`
|
||||
- *이 작업이 누락되면 시스템은 업데이트 후에도 "구버전"으로 인식합니다.*
|
||||
|
||||
### [Step 2] 커밋 및 태그 생성 (Commit & Tag)
|
||||
반드시 **소스코드 커밋을 먼저** 수행하고, 그 커밋에 태그를 붙여야 합니다.
|
||||
|
||||
```bash
|
||||
# 1. 버전 파일 및 변경 사항 커밋
|
||||
git add .
|
||||
git commit -m "[BUILD] v0.4.3.5 - 배포 내용 요약"
|
||||
|
||||
# 2. 원격 저장소로 코드 푸시 (먼저!)
|
||||
git push origin main
|
||||
|
||||
# 3. 태그 생성 (경량 태그 권장)
|
||||
git tag v0.4.3.5
|
||||
|
||||
# 4. 태그 푸시 (배포 트리거)
|
||||
git push origin v0.4.3.5
|
||||
```
|
||||
|
||||
### [Step 3] 운영 서버 배포 확인
|
||||
1. 운영 서버(NAS)에서 업데이트 스크립트 실행
|
||||
2. 업데이트 완료 후 브라우저에서 '새로고침(Ctrl+F5)' 또는 캐시 비우기 수행
|
||||
3. [시스템 관리] > [버전 정보] 메뉴에서 **표시되는 버전 번호**와 **빌드 일자**가 최신인지 확인
|
||||
|
||||
---
|
||||
|
||||
## 🚫 절대 금지 사항 (Do Not)
|
||||
1. **커밋 없이 태그만 생성 금지**: 운영 서버는 태그가 가리키는 시점의 코드를 가져옵니다. 변경 사항이 커밋되지 않았다면 아무것도 변하지 않습니다.
|
||||
2. **`package.json` 수정 누락**: 코드는 바꼈는데 명찰(버전 번호)을 안 바꾸면, 시스템은 "이미 최신 버전"이라 판단하고 업데이트 알림을 띄우지 않습니다.
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "smartims",
|
||||
"version": "0.4.0.1",
|
||||
"version": "0.4.3.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "smartims",
|
||||
"version": "0.4.0.1",
|
||||
"version": "0.4.3.1",
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "smartims",
|
||||
"private": true,
|
||||
"version": "0.4.3.4",
|
||||
"version": "0.4.3.5",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
67
scripts/nas/restore_smartims.sh
Normal file
67
scripts/nas/restore_smartims.sh
Normal file
@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ==========================================
|
||||
# Smart IMS Emergency Restore Script (Revised)
|
||||
# 작성일: 2026-01-26
|
||||
# ==========================================
|
||||
|
||||
PROJECT_DIR="/volume1/web/smartims"
|
||||
BACKUP_DIR="/volume1/smart_ims"
|
||||
SERVER_DIR="${PROJECT_DIR}/server"
|
||||
MYSQL_BIN="/usr/local/mariadb10/bin"
|
||||
|
||||
DB_USER="choibk"
|
||||
DB_PORT="3307"
|
||||
DB_NAME="sokuree_platform_prod"
|
||||
DB_HOST="127.0.0.1"
|
||||
|
||||
echo "=============================================="
|
||||
echo "🚨 EMERGENCY RESTORE PROCESS STARTING"
|
||||
echo "=============================================="
|
||||
|
||||
# DB 비밀번호 추출 (Node.js)
|
||||
if [ -f "${SERVER_DIR}/.env" ]; then
|
||||
cd "${SERVER_DIR}"
|
||||
DB_PASS=$(node -e "try{const fs=require('fs');const c=fs.readFileSync('.env','utf8');const m=c.match(/^DB_PASSWORD=(.*)$/m);if(m){let p=m[1].trim();if((p.startsWith('\"')&&p.endsWith('\"'))||(p.startsWith(\"'\")&&p.endsWith(\"'\"))){p=p.slice(1,-1);}process.stdout.write(p);}}catch(e){}")
|
||||
else
|
||||
echo "❌ [Error] .env file not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 1. 최신 이미지 복구
|
||||
echo "[Step 1] Finding latest image backup..."
|
||||
LATEST_IMG=$(ls -t "${BACKUP_DIR}"/backup_images_*.tar.gz 2>/dev/null | head -n 1)
|
||||
|
||||
if [ -n "$LATEST_IMG" ]; then
|
||||
echo "✅ Found: $LATEST_IMG"
|
||||
echo " Restoring images..."
|
||||
tar -xzf "$LATEST_IMG" -C "${PROJECT_DIR}"
|
||||
else
|
||||
echo "⚠️ [Warning] No image backup found."
|
||||
fi
|
||||
|
||||
# 2. 최신 DB 복구
|
||||
echo "[Step 2] Finding latest database backup..."
|
||||
LATEST_SQL=$(ls -t "${BACKUP_DIR}"/backup_db_*.sql 2>/dev/null | head -n 1)
|
||||
|
||||
if [ -z "$LATEST_SQL" ]; then
|
||||
echo "❌ [Error] No database backup found!"
|
||||
exit 1
|
||||
else
|
||||
echo "✅ Found: $LATEST_SQL"
|
||||
echo " Restoring database..."
|
||||
|
||||
"${MYSQL_BIN}/mysql" -h "${DB_HOST}" -u "${DB_USER}" "-p${DB_PASS}" --port "${DB_PORT}" "${DB_NAME}" < "$LATEST_SQL"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Database restore complete."
|
||||
else
|
||||
echo "❌ [Error] Database restore failed."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "=============================================="
|
||||
echo "🎉 SYSTEM RESTORE COMPLETED"
|
||||
echo " Please restart PM2: pm2 reload smartims-api"
|
||||
echo "=============================================="
|
||||
140
scripts/nas/update_smartims.sh
Normal file
140
scripts/nas/update_smartims.sh
Normal file
@ -0,0 +1,140 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ==========================================
|
||||
# Smart IMS NAS Update Script (Revised)
|
||||
# 작성일: 2026-01-26
|
||||
# ==========================================
|
||||
|
||||
# 1. 환경 설정
|
||||
PROJECT_DIR="/volume1/web/smartims"
|
||||
BACKUP_DIR="/volume1/smart_ims"
|
||||
SERVER_DIR="${PROJECT_DIR}/server"
|
||||
DATE_STAMP=$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
# DB 접속 정보
|
||||
DB_USER="choibk"
|
||||
DB_PORT="3307"
|
||||
DB_NAME="sokuree_platform_prod"
|
||||
DB_HOST="127.0.0.1" # 호스트 명시 (필수)
|
||||
MYSQL_BIN="/usr/local/mariadb10/bin"
|
||||
|
||||
# 로그 파일 설정
|
||||
mkdir -p "${BACKUP_DIR}/logs"
|
||||
LOG_FILE="${BACKUP_DIR}/logs/update_${DATE_STAMP}.log"
|
||||
exec > >(tee -a "${LOG_FILE}") 2>&1
|
||||
|
||||
echo "=============================================="
|
||||
echo "[Update] Started at $(date)"
|
||||
echo "=============================================="
|
||||
|
||||
# 2. .env에서 DB 비밀번호 추출 (Node.js 활용으로 특수문자/따옴표 안전 처리)
|
||||
if [ -f "${SERVER_DIR}/.env" ]; then
|
||||
cd "${SERVER_DIR}"
|
||||
# node 명령어로 파싱하여 쉘 특수문자 이슈 회피
|
||||
DB_PASS=$(node -e "try{const fs=require('fs');const c=fs.readFileSync('.env','utf8');const m=c.match(/^DB_PASSWORD=(.*)$/m);if(m){let p=m[1].trim();if((p.startsWith('\"')&&p.endsWith('\"'))||(p.startsWith(\"'\")&&p.endsWith(\"'\"))){p=p.slice(1,-1);}process.stdout.write(p);}}catch(e){}")
|
||||
|
||||
if [ -z "$DB_PASS" ]; then
|
||||
echo "[Error] Could not retrieve DB_PASSWORD from .env"
|
||||
exit 1
|
||||
fi
|
||||
echo "[Info] DB Password loaded (Length: ${#DB_PASS})"
|
||||
else
|
||||
echo "[Error] .env file not found at ${SERVER_DIR}/.env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 백업 디렉토리 생성
|
||||
mkdir -p "${BACKUP_DIR}"
|
||||
|
||||
# ==========================================
|
||||
# 🚨 [STEP 1] 데이터 백업
|
||||
# ==========================================
|
||||
echo "[Step 1] Creating Backups..."
|
||||
|
||||
# 1-1. 이미지 백업
|
||||
if [ -d "${PROJECT_DIR}/server/uploads" ]; then
|
||||
cd "${PROJECT_DIR}"
|
||||
TAR_NAME="backup_images_${DATE_STAMP}.tar.gz"
|
||||
echo " - Backing up images..."
|
||||
tar -czf "${BACKUP_DIR}/${TAR_NAME}" server/uploads/
|
||||
else
|
||||
echo " - [Warning] Uploads directory not found. Skipping image backup."
|
||||
fi
|
||||
|
||||
# 1-2. DB 백업
|
||||
SQL_NAME="backup_db_${DATE_STAMP}.sql"
|
||||
echo " - Backing up database..."
|
||||
|
||||
# -h 127.0.0.1 옵션 추가 및 비밀번호 인자 방식 변경
|
||||
"${MYSQL_BIN}/mysqldump" -h "${DB_HOST}" -u "${DB_USER}" "-p${DB_PASS}" --port "${DB_PORT}" "${DB_NAME}" --single-transaction --quick --lock-tables=false > "${BACKUP_DIR}/${SQL_NAME}" 2>/dev/null
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "[Error] Database backup failed! Please check:"
|
||||
echo " 1. DB Port ($DB_PORT) matches MariaDB 10 port."
|
||||
echo " 2. DB Password in .env is correct."
|
||||
echo " 3. 'choibk' user has permissions."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 빈 파일 체크 (0 바이트면 실패로 간주)
|
||||
if [ ! -s "${BACKUP_DIR}/${SQL_NAME}" ]; then
|
||||
echo "[Error] Backup file is empty. Dump failed."
|
||||
rm "${BACKUP_DIR}/${SQL_NAME}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[Success] All backups completed successfully."
|
||||
|
||||
|
||||
# ==========================================
|
||||
# 🚀 [STEP 2] 버전 동기화 및 코드 반영
|
||||
# ==========================================
|
||||
echo "[Step 2] Updating Source Code..."
|
||||
cd "${PROJECT_DIR}"
|
||||
|
||||
# 목표 태그 설정
|
||||
TARGET_TAG=$1
|
||||
if [ -z "$TARGET_TAG" ]; then
|
||||
echo " - Fetching latest tag info..."
|
||||
git fetch origin --tags --force
|
||||
TARGET_TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
|
||||
echo " - Detected latest tag: ${TARGET_TAG}"
|
||||
fi
|
||||
|
||||
if [ -z "$TARGET_TAG" ]; then
|
||||
echo "[Error] Target tag not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo " - Syncing with remote..."
|
||||
git fetch origin --tags --force --prune
|
||||
if [ $? -ne 0 ]; then echo "[Error] Git fetch failed."; exit 1; fi
|
||||
|
||||
echo " - Checkout to ${TARGET_TAG}..."
|
||||
git checkout -f "${TARGET_TAG}"
|
||||
if [ $? -ne 0 ]; then echo "[Error] Git checkout failed."; exit 1; fi
|
||||
|
||||
|
||||
# ==========================================
|
||||
# 🏗️ [STEP 3] 시스템 빌드 및 서비스 재시작
|
||||
# ==========================================
|
||||
echo "[Step 3] Building and Restarting..."
|
||||
|
||||
# 3-1. 프론트엔드
|
||||
echo " - Building Frontend..."
|
||||
cd "${PROJECT_DIR}"
|
||||
npm install --no-audit --no-fund > /dev/null
|
||||
npm run build
|
||||
|
||||
# 3-2. 백엔드
|
||||
echo " - Installing Backend Dependencies..."
|
||||
cd "${SERVER_DIR}"
|
||||
npm install --no-audit --no-fund > /dev/null
|
||||
|
||||
echo " - Reloading PM2..."
|
||||
pm2 reload smartims-api || pm2 start index.js --name "smartims-api"
|
||||
|
||||
echo "=============================================="
|
||||
echo "[Update] Completed Successfully at $(date)"
|
||||
echo "[Info] Target Version: ${TARGET_TAG}"
|
||||
echo "=============================================="
|
||||
4
server/package-lock.json
generated
4
server/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "0.4.0.1",
|
||||
"version": "0.4.3.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "server",
|
||||
"version": "0.4.0.1",
|
||||
"version": "0.4.3.1",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^1.13.2",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "0.4.3.4",
|
||||
"version": "0.4.3.5",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user