chore: exdev 배포 경로 단일화 및 서버 재구축 스크립트 추가
- Git 저장소/배포 work-tree를 /Users/aidev/apps/goldenChart로 통일 - 레거시 dev 경로는 심볼릭 링크로 흡수, deploy.sh에 소스 검증·no-cache 옵션 - server-rebuild-exdev.sh, verify-source-sync.sh 추가 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+1
-1
@@ -17,7 +17,7 @@ RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; BO
|
|||||||
REMOTE_HOST="${REMOTE_HOST:-exdev.co.kr}"
|
REMOTE_HOST="${REMOTE_HOST:-exdev.co.kr}"
|
||||||
REMOTE_USER="${REMOTE_USER:-aidev}"
|
REMOTE_USER="${REMOTE_USER:-aidev}"
|
||||||
REMOTE_PORT="${REMOTE_PORT:-22}"
|
REMOTE_PORT="${REMOTE_PORT:-22}"
|
||||||
REMOTE_PROJECT_DIR="${REMOTE_PROJECT_DIR:-/Users/aidev/dev/goldenChart}"
|
REMOTE_PROJECT_DIR="${REMOTE_PROJECT_DIR:-/Users/aidev/apps/goldenChart}"
|
||||||
FRONTEND_PORT="${FRONTEND_PORT:-80}"
|
FRONTEND_PORT="${FRONTEND_PORT:-80}"
|
||||||
BACKEND_PORT="${BACKEND_PORT:-8080}"
|
BACKEND_PORT="${BACKEND_PORT:-8080}"
|
||||||
|
|
||||||
|
|||||||
+28
-7
@@ -13,8 +13,11 @@ DOCKER_COMPOSE_FILE="${DOCKER_COMPOSE_FILE:-${WORK_TREE}/docker-compose.yml}"
|
|||||||
DEPLOY_LOG="${DEPLOY_LOG:-/Volumes/ADATA/logs/deploy/deploy.log}"
|
DEPLOY_LOG="${DEPLOY_LOG:-/Volumes/ADATA/logs/deploy/deploy.log}"
|
||||||
LOG_TAG="[goldenChart-deploy]"
|
LOG_TAG="[goldenChart-deploy]"
|
||||||
SERVICE_NAME="${SERVICE_NAME:-all}"
|
SERVICE_NAME="${SERVICE_NAME:-all}"
|
||||||
|
DOCKER_NO_CACHE="${DOCKER_NO_CACHE:-0}"
|
||||||
BACKEND_HEALTH_URL="${BACKEND_HEALTH_URL:-http://localhost:8080/api/indicators/list}"
|
BACKEND_HEALTH_URL="${BACKEND_HEALTH_URL:-http://localhost:8080/api/indicators/list}"
|
||||||
FRONTEND_URL="${FRONTEND_URL:-http://localhost:80}"
|
FRONTEND_URL="${FRONTEND_URL:-http://localhost:80}"
|
||||||
|
# 단일 배포 경로 (다른 work-tree 사용 금지)
|
||||||
|
LEGACY_WORK_TREE="/Users/aidev/dev/goldenChart"
|
||||||
|
|
||||||
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:${PATH:-/usr/bin:/bin}"
|
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:${PATH:-/usr/bin:/bin}"
|
||||||
|
|
||||||
@@ -51,23 +54,41 @@ info "[Phase 1] Git checkout"
|
|||||||
[ ! -d "$WORK_TREE" ] && mkdir -p "$WORK_TREE"
|
[ ! -d "$WORK_TREE" ] && mkdir -p "$WORK_TREE"
|
||||||
[ ! -d "$GIT_DIR" ] && err "GIT_DIR 없음: $GIT_DIR"
|
[ ! -d "$GIT_DIR" ] && err "GIT_DIR 없음: $GIT_DIR"
|
||||||
git --work-tree="$WORK_TREE" --git-dir="$GIT_DIR" checkout -f "$BRANCH"
|
git --work-tree="$WORK_TREE" --git-dir="$GIT_DIR" checkout -f "$BRANCH"
|
||||||
|
COMMIT="$(git --git-dir="$GIT_DIR" rev-parse HEAD)"
|
||||||
info "체크아웃 완료: $(git --git-dir="$GIT_DIR" rev-parse --short HEAD)"
|
info "체크아웃 완료: $(git --git-dir="$GIT_DIR" rev-parse --short HEAD)"
|
||||||
|
|
||||||
|
# work-tree 에 중첩 .git 금지 (bare checkout 과 혼선 방지)
|
||||||
|
if [ -d "$WORK_TREE/.git" ]; then
|
||||||
|
err "work-tree에 중첩 .git 존재 — 제거 후 재배포: rm -rf $WORK_TREE/.git"
|
||||||
|
fi
|
||||||
|
WT_HEAD="$(git --git-dir="$GIT_DIR" --work-tree="$WORK_TREE" rev-parse HEAD)"
|
||||||
|
[ "$WT_HEAD" = "$COMMIT" ] || err "work-tree HEAD 불일치: $WT_HEAD != $COMMIT"
|
||||||
|
if [ -f "$WORK_TREE/frontend/src/utils/ChartManager.ts" ]; then
|
||||||
|
info "소스 검증 ChartManager.sha256=$(shasum -a 256 "$WORK_TREE/frontend/src/utils/ChartManager.ts" | awk '{print $1}')"
|
||||||
|
fi
|
||||||
|
if [ -e "$LEGACY_WORK_TREE" ] && [ ! -L "$LEGACY_WORK_TREE" ]; then
|
||||||
|
warn "레거시 경로 존재(단일화 권장): $LEGACY_WORK_TREE — 배포는 $WORK_TREE 만 사용"
|
||||||
|
fi
|
||||||
|
|
||||||
[ ! -f "$DOCKER_COMPOSE_FILE" ] && err "docker-compose.yml 없음: $DOCKER_COMPOSE_FILE"
|
[ ! -f "$DOCKER_COMPOSE_FILE" ] && err "docker-compose.yml 없음: $DOCKER_COMPOSE_FILE"
|
||||||
cd "$WORK_TREE"
|
cd "$WORK_TREE"
|
||||||
|
|
||||||
# Phase 2 — Docker 이미지 빌드 (호스트 npm 사용 안 함 → postcss 홈 디렉터리 간섭 방지)
|
# Phase 2 — Docker 이미지 빌드 (호스트 npm 사용 안 함 → postcss 홈 디렉터리 간섭 방지)
|
||||||
info "[Phase 2] Docker 이미지 빌드 ($SERVICE_NAME)"
|
info "[Phase 2] Docker 이미지 빌드 ($SERVICE_NAME)"
|
||||||
|
|
||||||
build_frontend() {
|
_dc_build() {
|
||||||
info "docker compose build frontend"
|
local svc="$1"
|
||||||
docker compose -f "$DOCKER_COMPOSE_FILE" build frontend
|
if [ "$DOCKER_NO_CACHE" = "1" ]; then
|
||||||
|
info "docker compose build --no-cache $svc"
|
||||||
|
docker compose -f "$DOCKER_COMPOSE_FILE" build --no-cache "$svc"
|
||||||
|
else
|
||||||
|
info "docker compose build $svc"
|
||||||
|
docker compose -f "$DOCKER_COMPOSE_FILE" build "$svc"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
build_backend() {
|
build_frontend() { _dc_build frontend; }
|
||||||
info "docker compose build backend"
|
build_backend() { _dc_build backend; }
|
||||||
docker compose -f "$DOCKER_COMPOSE_FILE" build backend
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$SERVICE_NAME" in
|
case "$SERVICE_NAME" in
|
||||||
frontend) build_frontend ;;
|
frontend) build_frontend ;;
|
||||||
|
|||||||
Executable
+50
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# GoldenChart post-receive — Track A (git push main → deploy.sh)
|
||||||
|
# 설치: cp scripts/post-receive /Volumes/ADATA/git/goldenChart.git/hooks/post-receive
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
GIT_DIR="/Volumes/ADATA/git/goldenChart.git"
|
||||||
|
DEPLOY_SCRIPT="/Volumes/ADATA/git/deploy.sh"
|
||||||
|
SUMMARY_SCRIPT="/Volumes/ADATA/git/git-push-summary.sh"
|
||||||
|
DEPLOY_LOG="/Volumes/ADATA/logs/deploy/deploy.log"
|
||||||
|
SUMMARY_DIR="/Volumes/ADATA/logs/deploy/push-summaries"
|
||||||
|
HOOK_TAG="[post-receive]"
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$DEPLOY_LOG")" "$SUMMARY_DIR"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG =============================="
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG Track A — git push 수신"
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG =============================="
|
||||||
|
|
||||||
|
while read -r OLDREV NEWREV REFNAME; do
|
||||||
|
BRANCH_NAME="${REFNAME#refs/heads/}"
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG 브랜치: $BRANCH_NAME ($OLDREV → $NEWREV)"
|
||||||
|
|
||||||
|
if [ -x "$SUMMARY_SCRIPT" ]; then
|
||||||
|
SUMMARY_FILE="$("$SUMMARY_SCRIPT" "$GIT_DIR" "$OLDREV" "$NEWREV" "$REFNAME" "$SUMMARY_DIR" || true)"
|
||||||
|
if [ -n "${SUMMARY_FILE:-}" ] && [ -f "$SUMMARY_FILE" ]; then
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG 변경 요약: $SUMMARY_FILE"
|
||||||
|
head -20 "$SUMMARY_FILE" | sed "s/^/$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG /"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG [WARN] 요약 스크립트 없음: $SUMMARY_SCRIPT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$BRANCH_NAME" = "main" ]; then
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG main → deploy.sh 실행"
|
||||||
|
export SERVICE_NAME="${SERVICE_NAME:-all}"
|
||||||
|
"$DEPLOY_SCRIPT" 2>&1 | tee -a "$DEPLOY_LOG"
|
||||||
|
EXIT_CODE=${PIPESTATUS[0]}
|
||||||
|
if [ "$EXIT_CODE" -ne 0 ]; then
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG [ERROR] 배포 실패 (exit: $EXIT_CODE)"
|
||||||
|
exit "$EXIT_CODE"
|
||||||
|
fi
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG 배포 완료"
|
||||||
|
else
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG '$BRANCH_NAME' — 배포 스킵 (main만)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG =============================="
|
||||||
|
echo ""
|
||||||
Executable
+172
@@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# ==============================================================================
|
||||||
|
# exdev.co.kr — Git bare + work-tree + Jenkins 완전 재구축
|
||||||
|
# 실행 위치: 서버 (aidev@exdev.co.kr) 또는 로컬에서 ssh로 원격 실행
|
||||||
|
#
|
||||||
|
# 유지 경로 (현재 운영과 동일):
|
||||||
|
# GIT_DIR = /Volumes/ADATA/git/goldenChart.git
|
||||||
|
# WORK_TREE = /Users/aidev/apps/goldenChart
|
||||||
|
# DEPLOY_SCRIPT= /Volumes/ADATA/git/deploy.sh
|
||||||
|
# DEPLOY_LOG = /Volumes/ADATA/logs/deploy/deploy.log
|
||||||
|
# Jenkins = http://127.0.0.1:8090 job: goldenChart-Pipeline
|
||||||
|
# ==============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:${PATH:-/usr/bin:/bin}"
|
||||||
|
|
||||||
|
GIT_DIR="/Volumes/ADATA/git/goldenChart.git"
|
||||||
|
WORK_TREE="/Users/aidev/apps/goldenChart"
|
||||||
|
DEPLOY_SCRIPT="/Volumes/ADATA/git/deploy.sh"
|
||||||
|
DEPLOY_LOG="/Volumes/ADATA/logs/deploy/deploy.log"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
JENKINS_HOME="${JENKINS_HOME:-$HOME/.jenkins}"
|
||||||
|
JENKINS_JOB="goldenChart-Pipeline"
|
||||||
|
STAMP="$(date +%Y%m%d-%H%M%S)"
|
||||||
|
BACKUP_ROOT="/Volumes/ADATA/backup/goldenChart-rebuild-${STAMP}"
|
||||||
|
|
||||||
|
log() { echo "[rebuild $(date '+%H:%M:%S')] $*"; }
|
||||||
|
|
||||||
|
log "백업 디렉터리: $BACKUP_ROOT"
|
||||||
|
mkdir -p "$BACKUP_ROOT" "$(dirname "$DEPLOY_LOG")" /Volumes/ADATA/logs/deploy/push-summaries
|
||||||
|
|
||||||
|
# ── 1. Jenkins Job 제거 (데이터는 유지, job만 초기화) ─────────────────────
|
||||||
|
log "Jenkins job 제거: $JENKINS_JOB"
|
||||||
|
rm -rf "${JENKINS_HOME}/jobs/${JENKINS_JOB}"
|
||||||
|
rm -f "${JENKINS_HOME}/jobs/${JENKINS_JOB}.xml" 2>/dev/null || true
|
||||||
|
|
||||||
|
# ── 2. work-tree 백업 (.env·데이터 보존) ───────────────────────────────────
|
||||||
|
if [ -d "$WORK_TREE" ]; then
|
||||||
|
log "work-tree 백업 → $BACKUP_ROOT/work-tree-snapshot"
|
||||||
|
mkdir -p "$BACKUP_ROOT/work-tree-snapshot"
|
||||||
|
[ -f "$WORK_TREE/.env" ] && cp -a "$WORK_TREE/.env" "$BACKUP_ROOT/.env"
|
||||||
|
# embedded .git 제거 대상 — 백업만
|
||||||
|
if [ -d "$WORK_TREE/.git" ]; then
|
||||||
|
log "work-tree 내 중첩 .git 백업 (배포 혼선 원인)"
|
||||||
|
cp -a "$WORK_TREE/.git" "$BACKUP_ROOT/work-tree-snapshot/dot-git-nested"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── 3. bare 저장소 제거 후 재생성 ───────────────────────────────────────────
|
||||||
|
if [ -d "$GIT_DIR" ]; then
|
||||||
|
log "bare 저장소 백업 → $BACKUP_ROOT/goldenChart.git.tgz"
|
||||||
|
tar -czf "$BACKUP_ROOT/goldenChart.git.tgz" -C "$(dirname "$GIT_DIR")" "$(basename "$GIT_DIR")" 2>/dev/null || true
|
||||||
|
log "bare 저장소 제거: $GIT_DIR"
|
||||||
|
rm -rf "$GIT_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "bare 저장소 초기화"
|
||||||
|
git init --bare "$GIT_DIR"
|
||||||
|
git --git-dir="$GIT_DIR" symbolic-ref HEAD refs/heads/main
|
||||||
|
|
||||||
|
# ── 4. 레거시 work-tree 제거·단일 경로 고정 ─────────────────────────────────
|
||||||
|
LEGACY_WORK_TREE="/Users/aidev/dev/goldenChart"
|
||||||
|
if [ -e "$LEGACY_WORK_TREE" ] || [ -L "$LEGACY_WORK_TREE" ]; then
|
||||||
|
log "레거시 경로 백업·이동: $LEGACY_WORK_TREE"
|
||||||
|
if [ -d "$LEGACY_WORK_TREE" ] && [ ! -L "$LEGACY_WORK_TREE" ]; then
|
||||||
|
tar -czf "$BACKUP_ROOT/legacy-dev-goldenChart.tgz" -C "$(dirname "$LEGACY_WORK_TREE")" "$(basename "$LEGACY_WORK_TREE")" 2>/dev/null || true
|
||||||
|
mv "$LEGACY_WORK_TREE" "$BACKUP_ROOT/legacy-dev-goldenChart-dir" 2>/dev/null || true
|
||||||
|
else
|
||||||
|
rm -f "$LEGACY_WORK_TREE" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
ln -sfn "$WORK_TREE" "$LEGACY_WORK_TREE"
|
||||||
|
log " → $LEGACY_WORK_TREE → $WORK_TREE (심볼릭 링크)"
|
||||||
|
|
||||||
|
# ── 5. work-tree 정리 (중첩 .git 제거, 소스만 비움) ───────────────────────
|
||||||
|
log "work-tree 정리: $WORK_TREE"
|
||||||
|
mkdir -p "$WORK_TREE"
|
||||||
|
if [ -d "$WORK_TREE/.git" ]; then
|
||||||
|
rm -rf "$WORK_TREE/.git"
|
||||||
|
log " → 중첩 .git 제거 완료"
|
||||||
|
fi
|
||||||
|
# 소스 파일만 삭제 (.env·data·docker 볼륨 경로 유지)
|
||||||
|
find "$WORK_TREE" -mindepth 1 -maxdepth 1 \
|
||||||
|
! -name '.env' \
|
||||||
|
! -name '.env.*' \
|
||||||
|
! -name 'data' \
|
||||||
|
-exec rm -rf {} + 2>/dev/null || true
|
||||||
|
|
||||||
|
[ -f "$BACKUP_ROOT/.env" ] && cp -a "$BACKUP_ROOT/.env" "$WORK_TREE/.env" && log " → .env 복원"
|
||||||
|
|
||||||
|
# ── 6. deploy.sh · post-receive 설치 ───────────────────────────────────────
|
||||||
|
log "deploy.sh 설치"
|
||||||
|
cp -f "$REPO_ROOT/scripts/deploy.sh" "$DEPLOY_SCRIPT"
|
||||||
|
chmod +x "$DEPLOY_SCRIPT"
|
||||||
|
|
||||||
|
log "post-receive 훅 설치"
|
||||||
|
cp -f "$REPO_ROOT/scripts/post-receive" "$GIT_DIR/hooks/post-receive"
|
||||||
|
chmod +x "$GIT_DIR/hooks/post-receive"
|
||||||
|
|
||||||
|
if [ -x /Volumes/ADATA/git/git-push-summary.sh ]; then
|
||||||
|
log "git-push-summary.sh 유지"
|
||||||
|
else
|
||||||
|
log "[WARN] /Volumes/ADATA/git/git-push-summary.sh 없음 — push 요약 생략"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── 7. Jenkins Job 재생성 ──────────────────────────────────────────────────
|
||||||
|
log "Jenkins job 생성: $JENKINS_JOB"
|
||||||
|
mkdir -p "${JENKINS_HOME}/jobs/${JENKINS_JOB}"
|
||||||
|
cat > "${JENKINS_HOME}/jobs/${JENKINS_JOB}/config.xml" << 'JENKINS_XML'
|
||||||
|
<?xml version='1.1' encoding='UTF-8'?>
|
||||||
|
<project>
|
||||||
|
<description>GoldenChart — Track B (deploy.sh, file:// bare repo)</description>
|
||||||
|
<keepDependencies>false</keepDependencies>
|
||||||
|
<properties/>
|
||||||
|
<scm class="hudson.plugins.git.GitSCM" plugin="git@5.0.0">
|
||||||
|
<configVersion>2</configVersion>
|
||||||
|
<userRemoteConfigs>
|
||||||
|
<hudson.plugins.git.UserRemoteConfig>
|
||||||
|
<url>file:///Volumes/ADATA/git/goldenChart.git</url>
|
||||||
|
</hudson.plugins.git.UserRemoteConfig>
|
||||||
|
</userRemoteConfigs>
|
||||||
|
<branches>
|
||||||
|
<hudson.plugins.git.BranchSpec>
|
||||||
|
<name>*/main</name>
|
||||||
|
</hudson.plugins.git.BranchSpec>
|
||||||
|
</branches>
|
||||||
|
<doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
|
||||||
|
<submoduleCfg class="empty-list"/>
|
||||||
|
<extensions/>
|
||||||
|
</scm>
|
||||||
|
<canRoam>true</canRoam>
|
||||||
|
<disabled>false</disabled>
|
||||||
|
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
|
||||||
|
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
|
||||||
|
<triggers/>
|
||||||
|
<concurrentBuild>false</concurrentBuild>
|
||||||
|
<builders>
|
||||||
|
<hudson.tasks.Shell>
|
||||||
|
<command>#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:$PATH"
|
||||||
|
echo "=== goldenChart Jenkins Build #${BUILD_NUMBER} ==="
|
||||||
|
echo "시각: $(date)"
|
||||||
|
SERVICE_NAME="${SERVICE_NAME:-all}" /Volumes/ADATA/git/deploy.sh
|
||||||
|
</command>
|
||||||
|
</hudson.tasks.Shell>
|
||||||
|
</builders>
|
||||||
|
<publishers/>
|
||||||
|
<buildWrappers/>
|
||||||
|
</project>
|
||||||
|
JENKINS_XML
|
||||||
|
|
||||||
|
# Jenkins 설정 리로드 (실패해도 job 파일은 생성됨)
|
||||||
|
if command -v jenkins-cli >/dev/null 2>&1; then
|
||||||
|
jenkins-cli reload-configuration 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
if curl -sf -o /dev/null "http://127.0.0.1:8090/login" 2>/dev/null; then
|
||||||
|
curl -sf -X POST "http://127.0.0.1:8090/reload" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f /tmp/goldenchart_deploy.lock 2>/dev/null || true
|
||||||
|
|
||||||
|
log "============================================================"
|
||||||
|
log "서버 Git/Jenkins 재구축 완료 (소스는 아직 비어 있음)"
|
||||||
|
log " GIT_DIR : $GIT_DIR"
|
||||||
|
log " WORK_TREE : $WORK_TREE (중첩 .git 없음)"
|
||||||
|
log " Jenkins : $JENKINS_JOB → file://$GIT_DIR"
|
||||||
|
log ""
|
||||||
|
log "다음: 로컬에서 실행"
|
||||||
|
log " cd <goldenChart> && git push origin main"
|
||||||
|
log "============================================================"
|
||||||
Executable
+37
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# 로컬 ↔ 서버 work-tree 소스 동일성 검증
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REMOTE="${REMOTE:-aidev@exdev.co.kr}"
|
||||||
|
WORK_TREE="${WORK_TREE:-/Users/aidev/apps/goldenChart}"
|
||||||
|
LOCAL_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
|
||||||
|
FILES=(
|
||||||
|
frontend/src/utils/ChartManager.ts
|
||||||
|
frontend/src/utils/IchimokuCloudPlugin.ts
|
||||||
|
frontend/package-lock.json
|
||||||
|
scripts/deploy.sh
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "=== 로컬 ↔ 서버 체크섬 ($REMOTE:$WORK_TREE) ==="
|
||||||
|
FAIL=0
|
||||||
|
for f in "${FILES[@]}"; do
|
||||||
|
L="$LOCAL_ROOT/$f"
|
||||||
|
[ -f "$L" ] || { echo "MISSING local $f"; FAIL=1; continue; }
|
||||||
|
LHASH=$(shasum -a 256 "$L" | awk '{print $1}')
|
||||||
|
RHASH=$(ssh -o BatchMode=yes "$REMOTE" "shasum -a 256 '$WORK_TREE/$f' 2>/dev/null" | awk '{print $1}')
|
||||||
|
if [ "$LHASH" = "$RHASH" ]; then
|
||||||
|
echo "OK $f"
|
||||||
|
else
|
||||||
|
echo "DIFF $f"
|
||||||
|
echo " local=$LHASH"
|
||||||
|
echo " remote=$RHASH"
|
||||||
|
FAIL=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "=== Git HEAD ==="
|
||||||
|
echo -n "local: "; git -C "$LOCAL_ROOT" rev-parse HEAD
|
||||||
|
echo -n "remote: "; ssh -o BatchMode=yes "$REMOTE" "git --git-dir=/Volumes/ADATA/git/goldenChart.git rev-parse HEAD"
|
||||||
|
echo ""
|
||||||
|
[ "$FAIL" -eq 0 ] && echo "검증 통과" || { echo "검증 실패"; exit 1; }
|
||||||
Reference in New Issue
Block a user